Update HP BIOS from the Internet using HPCMS
- Log in to post comments
Hi guys,
Apologies if this is not the right forum to ask this question, but I have adapted a script which was a comment by a Jonathan in Gary Blok's blog article (https://garytown.com/update-hp-bios-using-powershell-and-internet-connection) to download and install the latest version of the HP BIOS. I have this working locally (after a bit of tinkering) but it fails in the MDT task sequence (it runs after the OS has been installed and a restart performed, also tried moving the TS to after the OS installed but before a restart). I'm no powershell expert but know enough to be able to adapt existing scripts generally, but this one has me scratching my head. If anyone has any idea of what I am missing, it would be greatly appreciated!
There are a few bits commented out here and there when i have been testing locally or via MDT, but rest assured, I have tried with them and without them enabled (in particular the return codes as a means of setting a Task Sequence variable as a condition to reboot the machine after BIOS install if necessary - that said, even when it does install locally, it doesn't return a process exit code of 2!).
Many thanks,
Steve
################################## <# SCRIPT INFO #################### Alternative script proposed by Jonathan on https://garytown.com/update-hp-bios-using-powershell-and-internet-connection # FUNCTIONS ###################### ##################################> Function Get-ScriptDirectory { If ($PSISE){ Split-Path $PSISE.CurrentFile.FullPath } Else{ $Global:PSScriptRoot } } ################################## #Log file info $tsenv = New-Object -COMObject Microsoft.SMS.TSEnvironment -ErrorAction SilentlyContinue $LogPath = $tsenv.Value("LogPath") #If testing locally use the logPath below #$LogPath = "$ENV:SystemDrive\Windows\Temp" $LogFileName = "HPBiosUpdate.log" $LogFile = Join-Path $LogPath $LogFileName $Today = Get-Date -Format yyyy-MM-dd $Time = Get-Date -Format HH:mm:ss #Start logging Out-File $LogFile -Append -InputObject ("") Out-File $LogFile -Append -InputObject ("") Out-File $LogFile -Append -InputObject ("$Today - $Time") Out-File $LogFile -Append -InputObject ("") #Define locations $ScriptDir = Get-ScriptDirectory #$ScriptDir = $PSScriptRoot $SaveToRoot = "$ENV:SystemDrive\Windows\Temp" $SaveToDirectory = "HP_BIOS" $SaveToLocation = "$SaveToRoot\$SaveToDirectory" $DownloadDir = "$($SaveToLocation)\HP_BIOS_Downloads" $ExtractDir = "$($SaveToLocation)\HP_BIOS_Extract" If (!(Test-Path $SaveToLocation)){ $null = New-Item -Path $SaveToRoot\ -Name $SaveToDirectory -ItemType "Directory" -Force } If (!(Test-Path $DownloadDir)){ $null = New-Item -Path $SaveToLocation\ -Name "HP_BIOS_Downloads" -ItemType "Directory" -Force } If (!(Test-Path $ExtractDir)){ $null = New-Item -Path $SaveToLocation\ -Name "HP_BIOS_Extract" -ItemType "Directory" -Force } #Define variables $OS = "Win10" $Category = "BIOS" $ProductCode = (Get-WmiObject -Class Win32_BaseBoard).Product $Model = (Get-WmiObject -Class Win32_ComputerSystem).Model $HP_CMSL_URL = "https://ftp.hp.com/pub/caps-softpaq/cmit/release/cmsl/hp-cmsl-latest.exe" #Detect HP BIOS PS module Try {Get-HPBiosVersion | Out-Null Write-Host "HP Client Management Script Library already installed" Out-File $LogFile -Append -InputObject ("HP Client Management Script Library already installed") } Catch {Write-Host "HP Client Management Script Library not loaded" Write-Host "Downloading from $HP_CMSL_URL" Out-File $LogFile -Append -InputObject ("HP Client Management Script Library not loaded") Out-File $LogFile -Append -InputObject ("Downloading from $HP_CMSL_URL") Invoke-WebRequest -Uri $HP_CMSL_URL -OutFile "$($DownloadDir)\HP_CMSL.exe" Write-Host "Installing HP Client Management Script Library from $($DownloadDir)\HP_CMSL.exe" Out-File $LogFile -Append -InputObject ("Installing HP Client Management Script Library from $($DownloadDir)\HP_CMSL.exe") Start-Process -FilePath "$($DownloadDir)\HP_CMSL.exe" -ArgumentList "/Silent /NoCancel /NoRestart /CloseApplications /Log" -Wait Write-Host "Finished downloading and installing HP Client Management Script Library" Out-File $LogFile -Append -InputObject ("Finished downloading and installing HP Client Management Script Library") } #Get BIOS info $CurrentBIOS = Get-HPBiosVersion Write-Host "Currently installed BIOS: version $($CurrentBIOS)" Write-Host "Checking product code $($ProductCode) for BIOS updates" Out-File $LogFile -Append -InputObject ("Currently installed BIOS: version $($CurrentBIOS)") Out-File $LogFile -Append -InputObject ("Checking product code $($ProductCode) for BIOS updates") $BIOS = Get-SoftpaqList -Platform $ProductCode -Os $OS -Category $Category $MostRecent = ($BIOS | Measure-Object -Property "ReleaseDate" -Maximum).Maximum $BIOS = $BIOS | Where "ReleaseDate" -eq "$MostRecent" If ([VERSION]$CurrentBIOS -ge [VERSION]$BIOS.Version){ Write-Host "BIOS already current" Out-File $LogFile -Append -InputObject ("BIOS already current") } Else{ Write-Host "Updated BIOS available: version $([VERSION]$BIOS.Version)" Out-File $LogFile -Append -InputObject ("Updated BIOS available: version $([VERSION]$BIOS.Version)") #Create folders $DownloadPath = "$($DownloadDir)\$($Model)\$($BIOS.Version)" $ExtractPath = "$($ExtractDir)\$($Model)\$($BIOS.Version)" If (!(Test-Path $DownloadPath)){ $null = New-Item $DownloadPath -ItemType Directory -Force } If (!(Test-Path $ExtractPath)){ $null = New-Item $ExtractPath -ItemType Directory -Force } } #Download BIOS files $BIOS_CVA = "$($DownloadPath)\$($BIOS.Id).cva" $BIOS_HTML = "$($DownloadPath)\$($BIOS.Id).html" $BIOS_EXE = "$($DownloadPath)\$($BIOS.Id).exe" $BIOS_TXT = "$($DownloadPath)\$($BIOS.ReleaseDate).txt" Write-Host "Downloading BIOS update for model $($Model) / product $($ProductCode) to $($DownloadPath)" Out-File $LogFile -Append -InputObject ("Downloading BIOS update for model $($Model) / product $($ProductCode) to $($DownloadPath)") Get-Softpaq -Number $BIOS.Id -SaveAs $BIOS_EXE -Verbose Write-Host "Downloading BIOS CVA file to $BIOS_CVA" Out-File $LogFile -Append -InputObject ("Downloading BIOS CVA file to $BIOS_CVA") Invoke-WebRequest -Uri $BIOS.MetaData -OutFile $BIOS_CVA Write-Host "Downloading BIOS HTML file to $BIOS_HTML" Out-File $LogFile -Append -InputObject ("Downloading BIOS HTML file to $BIOS_HTML") Invoke-WebRequest -Uri $BIOS.ReleaseNotes -OutFile $BIOS_HTML Write-Host "Writing README file with BIOS info to $BIOS_TXT" Out-File $LogFile -Append -InputObject ("Writing README file with BIOS info to $BIOS_TXT") $BIOS | Out-File -FilePath $BIOS_TXT #Extract BIOS files Write-Host "Extracting downloaded BIOS file to $($ExtractPath)" Out-File $LogFile -Append -InputObject ("Extracting downloaded BIOS file to $($ExtractPath)") Start-Process $BIOS_EXE -ArgumentList "-pdf -e -s -f$($ExtractPath)" -Wait #Suspend Bitlocker If ((Get-BitLockerVolume -MountPoint "$ENV:SystemDrive").VolumeStatus -eq "FullyDecrypted"){ Write-Host "Bitlocker not enabled" Out-File $LogFile -Append -InputObject ("Bitlocker not enabled") } Else{ Write-Host "Suspending Bitlocker" Out-File $LogFile -Append -InputObject ("Suspending Bitlocker") Suspend-BitLocker -MountPoint "$ENV:SystemDrive" -RebootCount 1 } #Search CVA to find path of executable that should be used to install the new BIOS version Write-Host "Looking for executable that should be used to install the new BIOS version in CVA file" Out-File $LogFile -Append -InputObject ("Looking for executable that should be used to install the new BIOS version in CVA file") $CVA_Install_Command = Get-Content $BIOS_CVA | Where {$_ -like "*SilentInstall*"} $CVA_Install_EXE = $CVA_Install_Command | %{$_.Split('"')[1]} Write-Host "Install command from CVA found: $CVA_Install_EXE" Out-File $LogFile -Append -InputObject ("Install command from CVA found: $CVA_Install_EXE") #Run update command with password file support $Updater_EXE = "$ExtractPath\$CVA_Install_EXE" $BIOS_PW = "$ScriptDir\HP_New.bin" If (Get-HPBiosSetupPasswordIsSet){ Write-Host "BIOS password protection detected" Out-File $LogFile -Append -InputObject ("BIOS password protection detected") If (!(Test-Path $BIOS_PW)){ Write-Host "HP BIOS password file missing: $BIOS_PW not found" -ForegroundColor Yellow Out-File $LogFile -Append -InputObject ("HP BIOS password file missing: $BIOS_PW not found") } Write-Host "Using $CVA_Install_EXE to Flash BIOS with arguments -s -r -b -l -p" Out-File $LogFile -Append -InputObject ("Using $CVA_Install_EXE to Flash BIOS with Args -s -r -b -l -p") #Flash BIOS Write-Host "Command = $Updater_EXE -s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log -p$($BIOS_PW)" Out-File $LogFile -Append -InputObject ("Command = $Updater_EXE -s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log -p$($BIOS_PW)") $Process = Start-Process $Updater_EXE -ArgumentList "-s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log -p$($BIOS_PW)" -PassThru -Wait $Process.WaitForExit() <#if ($Process.ExitCode -eq 2){ $tsenv.Value("SMSTS_BiosUpdateRebootRequired") = "True"} else{ $tsenv.Value("SMSTS_BiosUpdateRebootRequired") = "False"}#> } Else { Write-Host "BIOS password protection not detected" Write-Host "Using $CVA_Install_EXE to Flash BIOS with Args -s -r -b -l" Out-File $LogFile -Append -InputObject ("BIOS password protection not detected") Out-File $LogFile -Append -InputObject ("Using $CVA_Install_EXE to Flash BIOS with arguments -s -r -b -l") #Flash BIOS Write-Host "Command = $Updater_EXE -s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log" Out-File $LogFile -Append -InputObject ("Command = $Updater_EXE -s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log)") $Process = Start-Process $Updater_EXE -ArgumentList "-s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log" -PassThru -Wait $Process.WaitForExit() <#if ($Process.ExitCode -eq 2){ $tsenv.Value("SMSTS_BiosUpdateRebootRequired") = "True"} else{ $tsenv.Value("SMSTS_BiosUpdateRebootRequired") = "False"}#> } #Cleanup update files Write-Host "Removing folder $SaveToLocation to cleanup install files" Out-File $LogFile -Append -InputObject ("Removing folder $SaveToLocation to cleanup install files") Remove-Item -Recurse -Force $SaveToLocation -ErrorAction SilentlyContinue #Notify user #Write-Host "HP BIOS update applied, will install after next reboot" -ForegroundColor Green Out-File $LogFile -Append -InputObject ("HP BIOS update applied, will install after next reboot") Sleep 5
Looking at the script there are a bunch of places it could go wrong in your environment. That said if you all you are looking to do is get the latest bios installed you don't need that complicated of a script.
Assuming MDT here you have 2 steps you need to take
1. Copy the PowerShell modules into the PowerShell path. Start by downloading the 1.2.1 module and when you run the installer, select the unpack module cmd. Easy to just run this cmd (xcopy *.* "%ProgramFiles%\WindowsPowerShell\Modules" /E /Y) from the folder that has the actual modules.
2. run one of these two PowerShell cmds (make sure you set the execution policy appropriately.
Get-SoftpaqList -category bios |ForEach-Object {
Get-Softpaq $_.Id -action silentinstall}
or
Get-hpbiosupdates -flash -yes -bitlocker suspend
That should get the bios updated without too much additional work.
Thanks, I'll take a look. Agreed it may be overly complex though I was looking for something that would do the logging and only check for and install the updated BIOS if needed (using the encrypted '.bin' password file). We have something similar for our Dell machines which uses an adapted version of Gary B's scripts (we're in the process of trialling HP which is why I'm trying to set up the same functionality).
So, just to clarify, I need to install the powershell modules on the MDT server? Can I use a password.bin file with the Get-hpbiosupdates command (the documentation suggests this has to be a string)?
Anywhere you want to call the functions they need to be in the powershell modules path. So if you want to update the bios on a client, you'll want to copy them to the powerhsell path of winpe while it is running or the powershell path of the OS after it boots.
If you want to leverage them for driver download and import on your MDT server as my post here https://developers.hp.com/hp-client-management/blog/automating-mdt-drivers-hp-client-management-script-library you'll need them on your MDT server as well.
Hi everyone,
I am preparing PS script to keep up-to-date BIOS version for all HP devices in company.
I am using Get-HPBIOSUpdates -Download -SaveAs -Overwrite and then want to flash bios using downloaded file. I just want to clarify one point. How I can make sure, that the file has been downloaded succesfuuly? I did not find any verifications commands.
Thank you.
Hi everyone,
I am preparing PS script to keep up-to-date BIOS version for all HP devices in company.
I am using Get-HPBIOSUpdates -Download -SaveAs -Overwrite and then want to flash bios using downloaded file. I just want to clarify one point. How I can make sure, that the file has been successfully downloaded ? I did not find any verifications commands.
Thank you.
Currently the best way of doing this is to catch any exceptions thrown by the script. In the future, we are looking to add additonal metadata that will allow more elegant verification.
There are multiple checks downstream to make sure the file is correct, but for the download process the best way we have at this time is to handle exceptions.
Thank you!
sorry, was duplicated post.
Hi Colleagues,
Could you please which URL should be added to whitelist on firewall to allow HP CMSL download BIOS .bin files under system context in under enterprise network?
All that i found it "https://ftp.hp.com/pub/pcbios". Is it right adress?
Thank you in advance.
For BIOS files, that is correct: ftp.hp.com:443. There are different paths on there, depending on which CMSL features you use.
The tool also uses hpia.hpcloud.hp.com/ref:443 for data files.
I also added ftp.ext.hp.com and ftp-hpcom.glb1.hp.com to authotization bypass. And it works.
Thank you.
I have another question. How can I check if current OS is waiting for computer reboot to applying BIOS update after .bin files has been deployed to current system?Is it possbile get something like "pending reboot" state using HP CMSL? Or How i can check if a BIOS .bin file has been copied to EFI partition and it still there?