A little corner of the Empire on the web.

09 April, 2019

SCCM Detection Rules for Dell BIOS Updates

I've been doing a bit of work lately on deploying Dell BIOS updates using SCCM. This is using SCCM's Application Model to deploy the updates out to live machines, and also using those to update BIOS firmware during OSD Task Sequences. I've been a through a few versions of SCCM app detection rules for these jobs. The problem is that WMI's SMBIOSBIOSVersion is a text field, so it's returned as and then treated as a string type. There's also nothing that standardises how manufacturers fill in that text field, so they can use whatever versioning scheme they want, with whatever text they want around it. So different manufacturers do it different ways and they often change it between models.

Dell (at least for their Optiplex and Latitude business products) seem to use two different BIOS version number schemes at the moment, they seem to use one on older models, and the other for newer models, and they each have their own challenges. The first scheme uses an "A" followed by a two digit integer, counting up from zero, eg "A00" followed by "A01" then "A02" with "A09", "A10", "A11" being later in the series. The second scheme is a three part version number separated by dots (full stops, periods whatever your region calls them), eg "1.0.0", then "1.1.0" and later releases may be "1.6.2", "1.9.3", "1.11.2".

Taking them one by one, the problem with the "A00" scheme is that it's a mix of letters and numbers, so you can't do a purely numeric comparison to get the larger number, but at least a string greaterThanEqualTo (-ge) comparison of them does work, and you can always remove the leading "A" and then just do a numerical comparison.

Unfortunately the "1.0.0" type scheme works perfectly with a string greaterThanEqualTo (-ge) comparison right up to point where any of the numbers in it become double digits, so '1.2.0' -ge '1.0.5' returns True, whereas '1.12.0' -ge '1.3.5' unexpectedly returns False. This is because it's comparing each digit in the number one by one, so the first digit "1" is the same in both, then the dot is the same in both, then "1" is less than "3", so the greater than test fails, even though 12 is bigger than 3 it only looks at the digits individually.

The end result of this is that I'm now using the following PowerShell script in a script detection rule for Dell's BIOS updates. You just put the version number of the BIOS version that you're deploying in the variable in the first line then it parses it all correctly from that.

$NewBiosVer = '1.13.0'
$CurrentBIOSVer = (Get-WmiObject -Class Win32_BIOS).SMBIOSBIOSVersion
#Check if this is old-style Dell BIOS versioning "Ann" or new-style "n.n.n"
If ($NewBIOSVer.StartsWith('A') -and $CurrentBIOSVer.StartsWith('A')) {
    If ($CurrentBIOSVer -ge $NewBIOSVer) {
        #To indicate software is found, return something in STDOUT
        Write-Host "BIOS Version $CurrentBIOSVer found"
    } else {
        #To indicate software not found, don't return anything to STDOUT or STDERR
    }
} ElseIf (($NewBiosVer -match "^[\d\.]+$") -and ($CurrentBIOSVer -match "^[\d\.]+$")) {
    #Check if we've got a problem with two digit decimals (where 1.9 is less than 1.10 in version numbers, but not numerically)
    $NewBiosVerArray = $NewBiosVer.Split('.')
    $CurrentBIOSVerArray = $CurrentBIOSVer.Split('.')
    If ([int]$CurrentBIOSVerArray[0] -ge [int]$NewBiosVerArray[0]) {
        If ([int]$CurrentBIOSVerArray[1] -ge [int]$NewBiosVerArray[1]) {
            #To indicate software is found, return something in STDOUT
            Write-Host "BIOS Version $CurrentBIOSVer found"
        }
        Else {
            #To indicate software not found, don't return anything to STDOUT or STDERR
        }
    } else {
        #To indicate software not found, don't return anything to STDOUT or STDERR
    }
} Else {
    #Doesn't fit either BIOS version format???
    #To indicate software not found, don't return anything to STDOUT or STDERR
}

For the task sequence step's run conditions I'm doing two WQL queries, one for the device's model, and the second a simple check that the BIOS version is not the one that the update's looking for (so that machines on our nominated version skip the step) and then the Application's detection rules check fully whether the currently installed version is older or newer than the one we're installing (using the above script).

No comments:

Post a Comment