As I was preparing my new lab environment I found that my recently bought Lenovo M72e machines had a variety of different settings and BIOS levels, including alarm-based scheduled wake-ups so for consistency I wanted to update the BIOS on them and reset to known settings. This turned out to be very difficult, and I am far from alone in this opinion with forum quotes like “Lenovo has turned into a total mess. I miss IBM.” and “Probably my last Lenovo… never experienced such absurd bios issue with my other tiny pc, which is HP EliteDesk 800 G2 Mini”.

My first machine I tried to update was running BIOS version 21 - it’s full version string is F4KT21AUS - F4 is the machine type, I think based on download filenames KT is the package type, 21 is the version and AUS seems to be regional.

Creating a WinPE bootable USB drive - the way that worked

After failing miserably to get the BIOS to update using either the official ISO boot CD or my own DOS USB drive (see below), I resorted to trying to update from within Windows using a Windows Preinstallation Environment (WinPE) USB drive. This is based on some instructions I found online for updating Lenovo BIOS and Microsoft’s documentation which I modified to include the BIOS update on the drive.

First thing is to install the Windows 10 ADK and Windows PE add-on for the ADK on an existing Windows 10 install.

Then I could create the bootable drive:

  1. Open the “Deployment and Imageing Tools Environment” as an Administrator (Start -> Windows Kits)
  2. Create a working Windows PE copy: copype x86 C:\LenovoBIOS (note the amd64 option gives a 64-bit only OS and the BIOS package executable is 32-bit, which will not run - hence x86)
  3. Mount the image: Dism /Mount-Image /ImageFile:C:\LenovoBIOS\media\sources\boot.wim /Index:1 /MountDir:C:\LenovoBIOS\mount
  4. Add thse optional components in this order (taken from the instructions I found online):
    1. HTA:

      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-HTA.cab"
      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\en-us\WinPE-HTA_en-us.cab"
      
    2. Scripting:

      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-Scripting.cab"
      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\en-us\WinPE-Scripting_en-us.cab"
      
    3. WMI:

      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-WMI.cab"
      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\en-us\WinPE-WMI_en-us.cab"
      
    4. .NET Framework (NetFX):

      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-NetFX.cab"
      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\en-us\WinPE-NetFX_en-us.cab"
      
    5. Powershell:

      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\WinPE-Powershell.cab"
      Dism /Image:C:\LenovoBIOS\mount /Add-Package /PackagePath:"C:\Program Files (x86)\Windows Kits\10\Assessment and Deployment Kit\Windows Preinstallation Environment\x86\WinPE_OCs\en-us\WinPE-Powershell_en-us.cab"
      
  5. Use 7-zip to extract the Windows BIOS update package and copy to C:\LenovoBIOS\mount
  6. Close the image: Dism /Unmount-Image /MountDir:C:\LenovoBIOS\mount /commit
  7. Write to USB stick: MakeWinPEMedia /UFD C:\LenovoBIOS F: (where F: is the USB drive’s letter - it will be formatted by the MakeWinPEMedia command)

BIOS updating

With the WinPE USB disk, the BIOS updated directly from version 45 to 61 without a problem however on one machine the internal network card lost its MAC address (displayed as NOT AVAILABLE in the BIOS) and the card was unavailable for PXE booting or in any OS (full-blown Windows or Linux). In the end, I used the ‘clear CMOS’ jumper to wipe the BIOS settings (a ‘load defaults’ from within the BIOS interface had no effect) at which point the MAC address reappeared in the BIOS and I was able to use the network card for both PXE booting and within an OS.

BIOS settings on machines

Once updated, I proceeded to set the BIOS settings to my needs. I found followed this process:

  1. Enter BIOS (F1 during boot).
  2. Select Load Optimal Defaults (under Exit menu).
  3. Enable Intel(R) Virtualization Technology (under CPU Setup, under Advanced menu).
  4. Except on one machine (which is my “desktop” machine in the lab network), set After Power Loss to Power On (under Power menu) - this will allow me to turn the machines on remotely via the PDU (note wake on lan is also enabled by default, so multiple ways to wake up machines). The default setting is Last State.
  5. Set Configuration Change Detection to Enabled (under Security).
  6. Set CSM to Disabled (under Startup - automatically sets Boot Mode to UEFI Only).
  7. Set Secure Boot to Disabled (under Secure Boot, under Security menu - disabling CSM automatically turns it on)
  8. Set Keyboardless Operation to Enabled (under Startup).

Downloading all available BIOS versions

At one point, I used bash (and a handful of other utilities) to download all of the versions that exist from 20 onwards. I was thinking that I might be able to get around the boot-block not updating by doing a step-by-step upgrade from version 21 (see below) - however version 22 also did not update the boot block so that did not work in the end:

baseurl=https://download.lenovo.com/pccbbs/thinkcentre_bios
file_prefix=f4jt
file_suffix=usa
# First version digit
for i in {2..6}
do
  # 2nd digit, note versions are base 16 (hexadecimal)
  for j in {0..15}
  do
    file_name=$file_prefix$(printf %x $i)$(printf %x $j)$file_suffix.zip
    # Attempt to download the file
    if curl -fO $baseurl/$file_name
    then
        # Download succeeded, extract into directory named according to version.
        # Note use of '&& \' at the end of lines to ensure next command only executes if previous succeeded.
        mkdir $(basename $file_name .zip) && \
        unzip $file_name -d $(basename $file_name .zip) && \
        rm $file_name
    fi
  done
done

Upgrading the BIOS - failed attempt using bootable DOS USB and ISO images

Initially I tried downloading and installing the latest BIOS for the machine from Lenovo’s website (version 61), copying to a bootable USB and booting it (as suggested) - however this would not install with a message complaining “Error: A platform condition has prevented flashing.”. I also tried the CD image with a USB CD drive, for good measure, which failed in exactly the same way.

With the aid of the forum posts I linked to in the opening paragraph, I was able to download older versions by replacing the version number in the zip file’s download url (e.g. from the download page, https://download.lenovo.com/pccbbs/thinkcentre_bios/f4jt61usa.zip becomes https://download.lenovo.com/pccbbs/thinkcentre_bios/f4jt21usa.zip to get the version currently installed (21) instead of the latest version).

I found that an interim BIOS version (42) would install however there are two version numbers displayed in the BIOS - the “BIOS Revision Level” and the “Boot Block Revision Level”. These should be identical versions, as illustrated in this image from the Lenovo forums:

However, after a seemingly successful update to version 42 my boot block still showed F421A (or version 21). I re-flashed down to version 21 again and tried to install version 32 instead, which installed seemingly successfully and the BIOS revision had updated but again the boot block version remained stubbornly at 21. After a lot of faffing around, I discovered that the default flags Lenovo’s flash2.exe utility pass to afudos.exe (/p /n /sp) does not update the boot block (/b). I also found that trying to run afudos.exe directly from some update versions (e.g. versions 32 and 42) results in an “Insufficient memory” error however the same binary from earlier and later updates (e.g. 21 and 61) runs fine, as does running it via flash2.exe on the versions with the issue.

In the end, I had to put a full install of FreeDOS onto the memory stick I was using in order to get the memory drivers - the default boot option gives maximum free memory. I had been using a minimal version of FreeDOS, as created by Rufus, up until this point - going to the full version involved downloading the Rufus full image, extracting the files from the FD13FULL.IMG file and copying everything except setup.bat to the USB memory stick, overwriting the files Rufus had put there.

After doing this, I was able to run all of the afudos.exe versions however when I tried to update from 21 to 37 the system failed to start again after seemingly successfully applying the update. After leaving it for some time, I attempted to power it off and back on with no improvement (blank screen, no beeps, power light on and fan spinning but no other signs of life). I presumed the update had bricked the motherboard and bought a replacement off eBay. The replacement worked and came with BIOS version 45, reinforcing my theory that the BIOS update had failed and the old motherboard was now useless, which I updated using the Windows PE method above.