Update HP BIOS using PowerShell and Internet Connection

I’m on an HP kick, they have some awesome Client Management tools, and I’m playing around. Quick follow up to my last post about downloading HP BIOS to be used in creating a package,  This Script does a few things:

  1. Checks to see if you have the HP Client Powershell module, if not, downloads v1.1.1 and installs it.
  2. Checks your current BIOS version
  3. Checks internet for most recently released BIOS version for your device
  4. If newer BIOS is available than what is installed:
    1. Downloads Updated BIOS
    2. Extracts BIOS
    3. Suspends Bitlocker
    4. Installs BIOS

It does not automatically reboot, you can modify script to do that, or have your deployment solution do it.

*NOTE, this does NOT work in WinPE... I heard HP is working on updating the Modules so it does work in WinPE, which would be great. No ETA.  Once this happens, I'll test this again and update anything that needs to be updated.  WinPE is my goal for updating BIOS.

Other considerations, this requires active internet connection, you might have to update script to work with a proxy.

Tested on: HP EliteBook 840 G3

In Action: (Upgrade Required)
image

In Action: Already Current BIOS

image

 

Script:

 

 

Posted on GARYTOWN.COM

11 thoughts on “Update HP BIOS using PowerShell and Internet Connection”

  1. Thanks for this powerful script.! If some other guys have a user authenticated proxy like my company, you could add the following lines to support it:

    [system.net.webrequest]::defaultwebproxy = new-object system.net.webproxy('http://yourproxy.yourcompany.com:8080')
    [system.net.webrequest]::defaultwebproxy.credentials = [System.Net.CredentialCache]::DefaultNetworkCredentials
    [system.net.webrequest]::defaultwebproxy.BypassProxyOnLocal = $true

    This will use your current logged on user for proxy authentication. Actually I didn't use it in TS, as soon as I did i will update my comment. The solution would be something like https://docs.microsoft.com/en-us/dotnet/api/system.net.credentialcache?view=netframework-4.7.2

  2. Don't know if it's because of Office 365 being installed or the stricter security we have applied on Windows 10 1803 (Credential Guard etc) but your script throws the error 'Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send' when trying to download the softpaq.

    I added the below line to the top of your script to fix it

    [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12

    Also... the BIOS version is being reported as 'Updated BIOS available, Version: 1.6.0', but it's 1.06.00. This is correctly reported later on in the script 'Temp\Extracted\HP EliteBook 850 G5\01.06.00'

    It's very alpha I guess so I won't complain about the missing error checks and the script reporting my BIOS is already current when nothing was download so there was no BIOS version to compare 🙂

    (Tested on a HP EliteBook 850 G5)

  3. Z420 ...
    if (Test-Path "$($ExtractedPath)\HPQFlash\HPQFlash.exe")
    {
    Write-Output "Using HPQFlash.exe to Flash BIOS with Args -s -r -b -l"
    #Start-Process "$($ExtractedPath)\HPQFlash\HPQFlash.exe" -ArgumentList "-s -r -b -l$($HPContent)\HPBIOSUpdate.log" -wait
    }

  4. Many thanks for this.

    HP have updated the PowerShell libraries a couple of times (most recent is 25 April - https://ftp.hp.com/pub/caps-softpaq/cmit/release/cmsl/hp-cmsl-1.2.1.exe) and the latest version has a "-flash" switch in the Get-HPBiosUpdates command which might simplify your script (although I can't actually get it to work - it downloads the file, copies it to the EFI partition but then fails to install with a message "The system could not find one of the BIOS update binary files")

    • Thanks Steve, I just started using the new tools yesterday, just haven't head time to play with it in WinPE. However I know Mike Terrill has been playing a lot with the new toolset in WinPE. I've started to use the new tools, but not the -flash. I've been focused on using the command to download the Bin file, then update the CM Package information.. post coming soon.

  5. Hello,

    You should change the test version with
    if ([version]$CurrentBIOS -le [version]$Bios.Version)

    in order to avoid downgrading Bios. It seems that HP does not update the webservice used by their commandlet as often as the website :/

    Thank you this great script !

  6. Awesome idea and great script indeed! I've implemented this as a step in my OSD Task Sequence but finetuned it and added some features:
    - Log file creation so you can review all steps taken after the reboot on remote clients.
    - Will always download and install the latest version of HP Client Management Script Library instead of a fix SoftPaq when there is no version of it installed yet.
    - Downloads the corresponding CVA and HTML files too.
    - Reads the CVA file for the correct name and path of the BIOS flasher executable (silentinstall command line) and uses this one instead of guessing for possible values.
    - Checks if the BIOS is password protected and passes the password BIN file if needed. Place it in .\Password\HP_BIOS_PW.bin and the script will pick it up.
    - Update to cleanup the update files after execution.

    Here is my updated script for those who want it:

    ##################################
    # SCRIPT INFO ####################
    ##################################

    ##################################

    ##################################
    # FUNCTIONS ######################
    ##################################
    Function Get-ScriptDirectory
    {
    If ($PSISE)
    {
    Split-Path $PSISE.CurrentFile.FullPath
    }
    Else
    {
    $Global:PSScriptRoot
    }
    }
    ##################################

    #Log file info
    $Today = Get-Date -Format yyyy-MM-dd
    $Time = Get-Date -Format HH:mm:ss
    $LogDir = "$ENV:SystemDrive\Windows\Temp"
    $LogFileName = "LOG_HPBiosUpdate.log"
    $LogFile = Join-Path $LogDir $LogFileName

    #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
    $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\Password\HP_BIOS_PW.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)")
    Start-Process $Updater_EXE -ArgumentList "-s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log -p$($BIOS_PW)" -Wait
    }
    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)")
    Start-Process $Updater_EXE -ArgumentList "-s -r -b -l$($SaveToRoot)\HPBIOSUpdate.log" -Wait
    }

    #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
    }

  7. Getting this error when trying it, saying it has the most current version on a HP g4 800 but there is a newer version if I check in the bios

    HP Client Management Script Library not loaded
    Downloading from https://ftp.hp.com/pub/caps-softpaq/cmit/release/cmsl/hp-cmsl-latest.exe
    Currently installed BIOS: version
    Checking product code 8464 for BIOS updates
    BIOS already current
    Invoke-WebRequest : The underlying connection was closed: An unexpected error occurred on a send.
    At C:\windows\TEMP\AltirisScript6D683CC00AFCD0065.ps1:81 char:1
    + Invoke-WebRequest -Uri $HP_CMSL_URL -OutFile "$($DownloadDir)\HP_CMSL ...
    + ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    + CategoryInfo : InvalidOperation: (System.Net.HttpWebRequest:HttpWebRequest) [Invoke-WebRequest], WebExc
    eption
    + FullyQualifiedErrorId : WebCmdletWebResponseException,Microsoft.PowerShell.Commands.InvokeWebRequestCommand

    Get-HPBiosVersion : The term 'Get-HPBiosVersion' is not recognized as the name of a cmdlet, function, script file, or
    operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
    again.
    At C:\windows\TEMP\AltirisScript6D683CC00AFCD0065.ps1:90 char:16
    + $CurrentBIOS = Get-HPBiosVersion
    + ~~~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-HPBiosVersion:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    Get-SoftpaqList : The term 'Get-SoftpaqList' is not recognized as the name of a cmdlet, function, script file, or
    operable program. Check the spelling of the name, or if a path was included, verify that the path is correct and try
    again.
    At C:\windows\TEMP\AltirisScript6D683CC00AFCD0065.ps1:95 char:9
    + $BIOS = Get-SoftpaqList -Platform $ProductCode -Os $OS -Category $Cat ...
    + ~~~~~~~~~~~~~~~
    + CategoryInfo : ObjectNotFound: (Get-SoftpaqList:String) [], CommandNotFoundException
    + FullyQualifiedErrorId : CommandNotFoundException

    It does kick off an download the correct files

    • Looks like it's not installing the CMSL, as it can't find the PowerShell Module Commandlets. When ti tried to download the HP_CMSL, it failed.

Leave a Comment

This site uses Akismet to reduce spam. Learn how your comment data is processed.