//
you're reading...
Windows, WinPE

Automating BIOS upgrade and settings replication on Lenovo systems in WinPE

In my line of work BIOS upgrade/downgrade is a topic that keeps coming back quite frequently. Along with actual BIOS firmware update there also may be few settings that need to be applied and if you are dealing with bulk deployments – it makes sense to automate the process to save time and eliminate human error. Lenovo has a few tools out there to do the job, yet throughout the years I have found that they are not necessarily well-documented. This post gives you an outline of challenges I had to face back in the day, with an example script of automating outlined tasks on Lenovo T450 laptop.

In order to go through all of the above lets first define the goals and constrains of the scenario.

The goals:

  • Upgrade/downgrade BIOS to agreed firmware level
  • Apply multiple BIOS settings (including security settings and boot order)
  • Apply BIOS password (preferably not visible to deployment engineers)
  • Burn asset tag into relevant field in BIOS

Constraints:

  • Configuration tasks needs to be done in Windows PE
  • Devices need to be PXEbooted (no USB media available)
  • Contents of the hard drive cannot be modified
  • Network share available to deployment engineers has read-only access

Prep work

Before we can start it is important to obtain correct tools from Lenovo support website. The utilities vary from one hardware platform to another and they also keep on changing. For example, utility to read/write asset information used to be called WinAIAPackage.exe (aiaread.exe/aiawrite.exe for DOS), but then changed name to WinAIA.exe (and WinAIA64.exe). Also you need to ensure that you are using utility version appropriate for your environment’s architecture (32/64 bit). In this example, we shall use three utilities to accomplish our goals:

  • BIOS Update Utility (WINUPTP.EXE)
  • Utility To Read and Write Asset ID Information for Windows (WinAIA.exe)
  • ThinkPad Setup Settings Capture/Playback Utility for Windows (SRSETUPWIN) for Windows (srsetupewin32.exe)

Before we dive into the code, we need to define a folder structure for all files. First of all, in the below example, all utilities are mapped to a network share as t: drive (which is read only). All utilities are in their respective folders on the root of t: drive. BIOS update folders should also reside on the root of t:, however each folder name should be changed to match machine model rather than original BIOS version. Scripts for each machine models are being stored in root (with file names matching model versions), while captured BIOS settings files are being stored in a single folder not to clutter root even more.

Detecting hardware platform

I have divided the task into two logical blocks. First script is an entry point for every machine. Its task is to determine machine model (and current BIOS version) and based on  that call a script for given hardware platform. BIOS images will be different between hardware platform, as well as files containing the settings, hence the segregation.

Most favoured way of collecting system information on Windows platform is to leverage WMI queries. Performing this task is fairly simple and consists of two steps. In the first FOR loop we need to execute our query and capture the output. In the second FOR loop, we need to go through the captured output and pick relevant data. Since info we are after is not available in one place, we need to interrogate two different classes (‘computersystem’ and ‘BIOS’). Once all information is at hand, script tries to execute script file named after detected machine model. If it doesn’t exist – an appropriate error message is presented to the user.

echo off

:START
REM Change drive letter to t:
t:
cd \

ECHO # Gathering information about computer...
REM Get the system settings
FOR /F "tokens=*" %%A IN ('WMIC computersystem Get /Format:list ^| FIND "="') DO (
SET __ComputerSystem.%%A
)

REM To display array uncomment the line below
REM SET __ComputerSystem.

REM Go through the array to find the computer model and assign it to a new variable
FOR /F "tokens=2* delims=.=" %%A IN ('SET __ComputerSystem.') DO IF "%%A"=="Model" SET systemmodel=%%B

ECHO # System has been reported as %systemmodel%.

REM Get the BIOS basic info
FOR /F "tokens=*" %%A IN ('WMIC bios get /Format:list ^| FIND "="') DO (
SET __BIOS.%%A
)

REM Go through the array to find the BIOS version and serial number
FOR /F "tokens=2* delims=.=" %%A IN ('SET __BIOS.') DO (
IF "%%A"=="SMBIOSBIOSVersion" SET currentBIOSversion=%%B
IF "%%A"=="SerialNumber" SET lenovoSerial=%%B
)

REM BIOS version in Lenvo format consists of 8 characters
SET lenovoBIOS=%currentBIOSversion:~0,8%

REM Look for batch file that matches detected machine model
IF EXIST %systemmodel%.cmd (CALL %systemmodel%.cmd) ELSE (GOTO UNRECOGNIZED_MODEL)

REM Script finishes here, section below is to appear only in case of an error
GOTO :EOF

:UNRECOGNIZED_MODEL

ECHO ******************************************************
ECHO *     Computer model has not been recognized!        *
ECHO *         Please contact Tech Support!               *
ECHO ******************************************************

pause > nul
GOTO START

Running hardware-specific script

Down below is a sample code for applying all updates and settings as required. The script in nutshell is fairly simple. First, we need to define what is required to accomplish our goals (BIOS version, password, previously captured file with BIOS settings and asset tag). Once all is at hand, we need to check if BIOS version matches required version and take appropriate action. If BIOS needs updating, it will also require a reboot to complete the task. Once BIOS is running correct version of the BIOS, remaining settings can be applied. While script seems to be excessively long, it actually covers a lot of gotchas I have learnt to deal with in my experience.

Updating the BIOS

Running BIOS update should be a straightforward task and while it is down to calling just one executable, there are many things you need to take care of first:

  • Ensure you change current directory to folder that contains WINUPTP.EXE file
  • For laptops, ensure you have loaded battery driver (use ‘drvload x:\Windows\inf\battery.inf’ command)
  • Ensure you have write access to directory you are executing your update from. If you are running update from network share with ready-only access, consider copying it to the RAM drive (x: drive by default)
  • Ensure you have at least 20 MB of free space on a drive you are running your update from, otherwise update process seems to fail with misleading (BIOS image file cannot be found) error message. You may also need to increase scratch space (amount of RAM allocated for your PE image) for your WinPE.  You can easily find Microsoft TechNet articles on how to do accomplish that. This should not be a problem for Windows PE 5.0 and above.
  • When executing WINUPTP.EXE in silent mode, it continues to run its task even though it returns exit code, implement at least 30 seconds delay before rebooting the machine.

Applying BIOS settings and password

Similarly, applying BIOS settings should be a straightforward task, but there are some pitfalls you need to be aware of:

  • Copy settings file and executable onto RAM drive. While running it directly (even from read-only) share works fine for single machines, running the script on multiple machines simultaneously (e.g. 20 systems starting at exactly the same time) will result in a lot of missed machines without any error codes returned. It would appear as if srsetupwin32/64 locks the settings file while reading it. Also ensure to copy srsetupwin32/64.dll file along with executable to the same directory.
  • In order to apply BIOS password contained within settings file, the BIOS needs to… already have a password set! These two passwords can be different, but you need to know current password in order to change it. I suppose it is Lenovo’s way of ensuring that you don’t set a password for unsuspecting users. You can supply BIOS password with /PAP, /APAP or /KPAP switch (see command’s help to check what the difference is).
@echo off

REM Variables available from parent script:
REM %lenovoBIOS%
REM %lenovoSerial%

REM Variables that may change depending on customer requirements
SET requiredBIOS=JBET45WW
SET requiredPassword=Secret!
SET requiredSettings=lenovo_t450_v110.dat
REM Read asset tag captured earlier into a text file
SET assetTag=
SET /p assetTag=<z:\assetnumber.txt

ECHO # Current BIOS version is %lenovoBIOS%, required BIOS version is %requiredBIOS%.
ECHO.

REM If BIOS version is different from the required jump to BIOS_UPDATE section
IF NOT "%lenovoBIOS%"=="%requiredBIOS%" GOTO BIOS_UPDATE

REM If the BIOS version is correct, skip the BIOS update and go to BIOS_SETTINGS section
ECHO # No BIOS update necessary!
GOTO BIOS_SETTINGS

:BIOS_UPDATE
ECHO # BIOS update is required.
ECHO # Loading battery drivers...

drvload x:\Windows\inf\Battery.inf
ECHO.

REM Copy files to RAM drive to allow log files
xcopy /e /y /h /i %systemmodel% x:\%systemmodel%

ECHO # BIOS update imminent!
ECHO # Starting BIOS update for %systemmodel%! Please wait...
ECHO.
x:
cd \
REM Run a BIOS update from relevant directory
cd %systemmodel%
WINUPTP.EXE -s

REM Delay the script for 60 seconds in order to allow the BIOS update to complete.
<nul (set/p z=Finalizing BIOS update)
FOR %%A IN (0 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30) DO (
<nul (set/p z=.) >nul ping 127.0.0.1
)
>nul ping 127.0.0.1

ECHO.
ECHO # BIOS update completed
ECHO # PRESS ANY KEY TO REBOOT...
ECHO.
pause > nul

REM Once BIOS has been updated a system need a reboot
wpeutil reboot

:BIOS_SETTINGS
t:
ECHO.
ECHO # Looking for BIOS settings...
ECHO.
REM Check if file with the settings exists

IF NOT EXIST %requiredSettings% GOTO NO_SETTINGS_FILE
ECHO # Applying BIOS settings...

REM Copy files onto RAM drive
xcopy /y t:\srsetupwin32\* x:\
xcopy /y t:\settings_repository\%requiredSettings%

REM Apply BIOS settings
x:
cd \
srsetupewin32.exe %requiredSettings% /U /Q /APAP %requiredPassword%
SET srsetuperrorcode=%errorlevel%
IF NOT %srsetuperrorcode%==0 GOTO SETTINGS_ERROR

ECHO.
ECHO # BIOS settings applied!
ECHO # Writing asset tag into the BIOS...

t:\WINAIA\WinAIA.exe -silent -set "USERASSETDATA.ASSET_NUMBER=%assetTag%"

SET winaiaerrorcode=%errorlevel%
IF NOT %winaiaerrorcode%==0 GOTO ASSET_ERROR

ECHO.
ECHO # Asset tag written into the BIOS!
REM Script finishes here, section below is to appear only in case of an error


GOTO :EOF

:NO_SETTINGS_FILE

ECHO ******************************************************
ECHO *    No BIOS settings file found for the system!     *
ECHO *          Please contact Tech Support!!!            *
ECHO ******************************************************

pause > nul

GOTO BIOS_SETTINGS

:SETTINGS_ERROR

ECHO Error code: %srsetuperrorcode%.
ECHO ******************************************************
ECHO *         srsetupewin32.exe returned error!          *
ECHO *          Please contact Tech Support!!!            *
ECHO ******************************************************
pause > nul 
GOTO BIOS_SETTINGS

:ASSET_ERROR

ECHO Error code: %winaiaerrorcode%.
ECHO ******************************************************
ECHO *           WinAIA.exe returned error!               *
ECHO *          Please contact Tech Support!!!            *
ECHO ******************************************************
pause > nul 
GOTO BIOS_SETTINGS

That is pretty much it. You can of course make it more or less interactive than it is in the example above, but I hope it gives a good overview of potential problems and solutions involved. Not everyone will stumble upon these challenges, as for each one of them certain conditions must be met. Nevertheless I hope this post will be of some use to fellow admins involved in mass deployment!

Discussion

11 thoughts on “Automating BIOS upgrade and settings replication on Lenovo systems in WinPE

  1. I am just trying to do the Bios Update part but when I run winuptp -s or winuptp64 -s it does nothing. This is a ThinkPad Yoga.

    Like

    Posted by oliphanj | 2016-07-07, 14:56
    • I haven’t dealt with Yoga’s personally, but I have seen issue with winuptp returning straight to command prompt while it was still actually running in the background. After running your command type in ‘ECHO %errorlevel%’ to see if you got any errors. If the error code is 0, give it about a minute and run ‘winpeutil reboot’ to restart the computer (I am assuming you are running this in WinPE). On reboot, after completing POST the update utility should take over and flash the BIOS – at least this is what I have experienced in the past with T400/X200 series laptops.

      If BIOS flashes fine, just add a delay in your script after your silent upgrade command and you should be sorted.

      Like

      Posted by Mietek Rogala | 2016-07-07, 15:16
  2. It show no error and after reboot no bios update.

    Like

    Posted by oliphanj | 2016-07-07, 21:04
  3. I have same problem with T460s. Under Windows 7 i can update no problem. But under PE it does nothing. After it starts to update it should generate Winuptp.txt file to root folder but it does not. No idea what is the problem.

    Like

    Posted by Jami Susijärvi | 2017-03-13, 14:53
    • and i have tryed to run it from C: (formatted disk), from ramdrive X:, and also straight from the network folder (write access).

      Like

      Posted by Jami Susijärvi | 2017-03-13, 14:54
      • Hi Jami,

        Thanks for your comment. Can you make sure you loaded battery driver located in X:\Windows\inf\battery.inf? That’s first thing to check. Next try to run the command manually and then run “echo %errorlevel% to see if what’s the exit code returned by the command – this should give you some info to go by. Also you could try to run the command in WinPE without silent switch and see if you can execute it manually (via GUI). This could give you more details on the nature of the problem. I am suspecting you might be missing a WinPE component that the installer relies on…

        Like

        Posted by Mietek Rogala | 2017-03-13, 15:05
      • Yep, tryed all of those. Battery driver loads ok (tried also manually). Errorlevel is 0 (but it doesnt do even the log file (btw, it was winuptp.log not .txt)). If i try to run it without silent switch it doest open the gui.

        Missing WinPE components is possible, but what are those :) I now changed order of this in my TaskSequence (SCCM2012) to run it in full OS and it works ok. But thats not what i want to. I want to update bios and bios settings before dropping OS image to drive. To be sure example that bios is in UEFI mode.

        Like

        Posted by Jami Susijärvi | 2017-03-14, 09:05
      • I haven’t touched Lenovo tools in a good couple of years, so I can’t tell you of the top of my head what the requirements are these days. Lack of time also doesn’t allow me to go back and experiment… But if you want to play with optional component, you can modify your PE image offline using dism.exe and /add-package path. Alternatively, you can have a look at adding the components via SCCM console – just select Optional Components tab in boot image Properties.

        But let’s take a step back to see what you are trying to achieve. What you have in mind is to use _SMSTSBootUEFI Task Sequence variable to detect if machine is running in UEFI mode and if not, use the BIOS utility to change it? That’s not going to work, I am afraid. Let’s say that you have detected that machine is running in Legacy mode and you apply your BIOS settings including changing boot mode to UEFI. These settings will be applied upon next reboot, so you will have to use “Restart computer” step to do that (simply issuing “wpeutil reboot” will break your TS). This step will in turn pre-stage WinPE image on local HDD for CURRENT boot mode, i.e. legacy. Upon reboot BIOS would change the boot mode to UEFI and it would no longer be able to boot into PE image pre-staged for legacy boot mode. If this is only outstanding setting you are worried about, just drop it and move on (since you have achieved your goal in full OS). Unless you have the time to investigate further and find out why winuptp.exe refuses to run in WinPE… I’d love to hear if you manage to nail it down!

        Like

        Posted by Mietek Rogala | 2017-03-17, 20:09
      • I have spoken with two of my work colleagues who encountered the same problem with latest Lenovo packages. They resolved it independently by either:
        1) copying “C:\windows\System32\oledlg.dll” and “C:\Windows\System32\en-US\ole32.dll.mui” files from full OS and placing them into respective folders of WinPE image.
        2) Including “WinPE-HTA” component in their WinPE image.

        Both methods achieve the same thing (oledlg.dll is part of WinPE-HTA.cab), however I would personally recommend the latter.

        Like

        Posted by Mietek Rogala | 2017-10-09, 07:11
  4. Maybe you need oledlg.dll in the directory of your winuptp64.exe

    Like

    Posted by Rich Siegel | 2017-08-22, 17:58
    • Hi Rich – apologies, I missed your comment earlier… Yes, inclusion of oledlg.dll seems to solve the problem. Thanks for the tip! Cleanest way to do so is to include WinPE-HTA component in your WinPE image.

      Like

      Posted by Mietek Rogala | 2017-10-09, 09:33

Leave a comment

Categories