#!/bin/bash
# chkconfig: 2345 0 99
# description: script to apply cpu microcode

# vars:
#
# START			distribution specific way of kicking programs
# END			distribution specific way of checking return status
# PROGRAM		the executable to run
# ARGUMENTS		the argument we're going to call PROGRAM with

DEVICE=/dev/cpu/microcode
ARGUMENTS=-Qu
RETVAL=0
PROGRAM=/sbin/microcode_ctl
FIRMWARE=/etc/firmware/microcode.dat

. /etc/init.d/functions

# perform the update
function start ()
{
	RETVAL=1
	# Make sure we are on an intel machine
	vendor=`cat /proc/cpuinfo | \
	    grep "^vendor_id" | sort -u | \
	    awk -F ": " '{ print $2 }'`
	if [ "$vendor" != "GenuineIntel" ]; then
	    return
	fi

	# 2.6.9-42.31 or later required to support our latest microcode
	# Check for older kernel to see if we need to use older microcode
	kv=`uname -r`
	major=`echo $kv | cut -d"-" -f2 | cut -d"." -f1`
	minor=`echo $kv | cut -d"-" -f2 | cut -d"." -f2`
	if [ $(echo $minor | grep -c EL) -ge 1 ]; then
	    # We actually have no minor, we got the dist tag, so set minor to 0
	    minor=0
	fi
	if [ "$major" -lt "42" ] || [ "$major" -eq "42" -a "$minor" -lt "31" ]
	then
	    FIRMWARE=/etc/firmware/microcode_old.dat
	    ARGUMENTS="$ARGUMENTS -f $FIRMWARE"
	fi

	echo -n $"Applying Intel Microcode update: "

	if [ ! -e $FIRMWARE ];
	then
		echo $"$0: microcode datafile not present ($FIRMWARE)"
		exit 1
	fi

	/sbin/modprobe microcode
	/sbin/MAKEDEV cpu/microcode
	lt=0
	while [ ! -c $DEVICE ]; do
		lt=$[lt+1];
		[ $lt -gt 5 ] && break;
		sleep 1;
	done

	# Lets just be sure we have a device file...
	if [ ! -e $DEVICE ];
	then
		echo $"$0: microcode device $DEVICE doesn't exist?"
		exit 1
	elif [ ! -c $DEVICE ];
	then
		echo $"$0: $DEVICE not a character device?"
		exit 1
	fi

	daemon $PROGRAM $ARGUMENTS
	RETVAL=$?
	/sbin/rmmod microcode
	rm -f $DEVICE

	# trap the most common case, errno 19 = no device
	if [ $RETVAL -eq 19 ];
	then
		echo $"$0: kernel does not have microcode device support"
	fi
	echo
}


case "$1" in
  start|reload|force-reload|restart)
	start
	exit 0
	;;
  stop)
	;;
  status)
	# I wonder when the driver will let us do this...
	# maybe I'll write it ;)
	echo $"$0: reading microcode status is not yet supported"
	;;
  *)
	echo $"Usage: $0 {start|restart}"
	exit 1
esac
