Automating Firmware Updates

Apple recently posted a firmware update for the MacBook that they claim addresses the spontaneous shutdown issue. If you have a lot of MacBooks at your site, you’ll have lots of fun visiting each one and doing the update.

It turns out that this updater can be run via command-line; either remotely via ARD or ssh, or via a local script on the machine. This opens up the possibility of automating it.

In order to run the updater via the command-line, it must first be installed. You can use ARD or radmind or FileWave to install it. Then your script needs to call it:

/Applications/Utilities/MacBook\ SMC\ Firmware\ Update.app/Contents/MacOS/MacBook\ SMC\ Firmware\ Update -remote

gives you the command-line interface with prompts;

/Applications/Utilities/MacBook\ SMC\ Firmware\ Update.app/Contents/MacOS/MacBook\ SMC\ Firmware\ Update -remote -y

says yes to the prompts automatically.
In theory, you could have a script as simple as this:

#!/bin/sh

/Applications/Utilities/MacBook\ SMC\ Firmware\ Update.app/Contents/MacOS/MacBook\ SMC\ Firmware\ Update -remote -y

If the firmware has already been updated, or you run this on the wrong hardware, it should just fail gracefully. But I wanted something a little more robust, so I wrote this:

#!/usr/bin/perl -w

# A script to automate a firmware update on MacBook1,1
# by Greg Neagle, Walt Disney Feature Animation, 27 Oct 2006

use strict;

my $REQUIRED_MACHINE_MODEL = "MacBook1,1";
my $REQUIRED_OSVERSION = "8.7.1";
my $REQUIRED_OSVERSION_READABLE = "10.4.7";
my $UPDATED_SMCVERSION = "1.4f12";
my $SMC_UPDATER_APP = "/Applications/Utilities/MacBook SMC Firmware Update.app/Contents/MacOS/MacBook SMC Firmware Update";

my $consoleuser = "";
open WHO, "who |" or die "Can't read from who: $!";
my $users = do { local $/;  };
close WHO;
if ($users =~ / console /) {
        $users =~ /^(\\w+)\\s+console\\s+/m ;
        $consoleuser = $1;
}

if ($consoleuser) {
        print "$consoleuser is logged in.  Exiting.\\n";
        exit;
}

my $MACHINE_MODEL = `/usr/sbin/system_profiler SPHardwareDataType | grep "Machine Model"`;
chomp $MACHINE_MODEL;
$MACHINE_MODEL =~ s/^\\s+Machine Model: //;
if ($MACHINE_MODEL ne $REQUIRED_MACHINE_MODEL) {
        print "This firmware update is not for this model.\\n";
        exit;
}

my $OSVERSION = `/usr/bin/uname -r`;
chomp $OSVERSION;
if ($OSVERSION lt $REQUIRED_OSVERSION) {
        print "You must update to Mac OS X $REQUIRED_OSVERSION_READABLE to update the firmware.\\n";
        exit;
}

my $SMCVERSION = `/usr/sbin/system_profiler SPHardwareDataType | grep "SMC Version"`;
chomp $SMCVERSION;
$SMCVERSION =~ s/^\\s+SMC Version: //;
if ($SMCVERSION lt $UPDATED_SMCVERSION) {
        print "SMC Firmware needs update to version $UPDATED_SMCVERSION.\\n";
} else {
        print "SMC Firmware is up to date.\\n";
        exit;
}

if (-x $SMC_UPDATER_APP) {
        system $SMC_UPDATER_APP, "-remote", "-y";
}

This script adds a little more error checking: if a user is logged in at the console, it exits. It does some sanity checking to make sure it’s running on the right model of hardware, and that the correct version of the OS is installed, and that the firmware actually needs updating. I made these enhancements so I could simply deliver this script with radmind. This way it could run on every reboot, but once the SMC firmware is up to date, it would exit gracefully and do nothing.

It looks like the other SMC firmware updates for other Intel Macs could be automated the same way, but that EFI firmware updates will still need to be done manually because on those, someone needs to hold the power button down at boot time.

Automating Firmware Updates

One thought on “Automating Firmware Updates

Comments are closed.