Uncategorized

Managing BIOS/UEFI Settings from Configuration Manager Part 4

February 17, 2021

This is a multipart post:
Part 1: The code underneath
Part 2: Using as Configuration Items
Part 3: Using as Applications
Part 4: Using in a task sequence – You are here

This topic has no doubt been covered many times before. My work on it started when I stumbled upon Damien Van Robaeys’ post a couple weeks ago. I wanted to take Damien’s work and apply it to deploying with Configuration Manager.

Using our UEFI Application in Task Sequences

I mentioned in Part 2 that we’d circle back to passwords. Changing settings on systems that have a UEFI password requires providing that password. When using scripts to change settings, that means the script needs the password. It would be easy to put the password in the script as plain text, not secure at all, but easy. Since we care about security, we are not going to include the password in the script. Instead, we are going to use the task sequence engine to protect the password.

We start by creating a masked task sequence variable to hold our password. As a masked variable, the value is not logged in configuration manager log(s), cannot be accessed via the task sequence debugger, or even the TS editor.

We follow-up by adding two lines to each of our application’s scripts.

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$password=$TS.Value('UEFIPassword')

The first line allows the script to interact with the task sequence, the second pulls the value stored in the variable into a script variable.

Our final scripts are below.
Dell


Function Confirm-DellUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Category,
    [Parameter(Position = 1,mandatory = $true)]$Setting,
    [Parameter(Position = 2,mandatory = $true)]$Value
    ) 
    (get-item "Dellsmbios:\$($Category)\$($Setting)").CurrentValue -eq $Value
}

Function Set-DellUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Category,
    [Parameter(Position = 1,mandatory = $true)]$Setting,
    [Parameter(Position = 2,mandatory = $true)]$Value,
    [Parameter(Position = 3)]$Password
    )
    $PWReq = (Get-Item -Path DellSmbios:\Security\IsAdminPasswordSet).currentvalue -eq $TRUE
    if($PWReq -and ($password -eq $NULL -or $password -eq "")){Write-error "Password is set but no password was provided"}
    elseif($PWReq -and !($password -eq $NULL -or $password -eq "")){
        Set-Item -Path "DellSmbios:\$($Category)\$($Setting)" $Value -password $password
    }
    else{
        Set-Item -Path "DellSmbios:\$($Category)\$($Setting)" $Value
    }
}

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$password=$TS.Value('UEFIPassword')

get-command -module DellBIOSProvider | out-null

if(!(Confirm-DellUEFISetting BootSequence BootList "UEFI Boot")){Set-DellUEFISetting BootSequence BootList UEFI $password}
if(!(Confirm-DellUEFISetting AdvancedBootOptions LegacyOrom Disabled)){Set-DellUEFISetting AdvancedBootOptions LegacyOrom Disabled $password}
if(!(Confirm-DellUEFISetting SecureBoot SecureBoot Enabled)){Set-DellUEFISetting SecureBoot SecureBoot Enabled $password}
if(!(Confirm-DellUEFISetting TpmSecurity TpmSecurity Enabled)){Set-DellUEFISetting TpmSecurity	TpmSecurity Enabled $password}
if(!(Confirm-DellUEFISetting VirtualizationSupport Virtualization Enabled)){Set-DellUEFISetting VirtualizationSupport Virtualization Enabled $password}
if(!(Confirm-DellUEFISetting VirtualizationSupport VtForDirectIo Enabled)){Set-DellUEFISetting VirtualizationSupport VtForDirectIo Enabled $password}
if(!(Confirm-DellUEFISetting VirtualizationSupport TrustExecution Enabled)){Set-DellUEFISetting VirtualizationSupport TrustExecution Enabled $password}

if(!(get-ciminstance Win32_DiskPartition -Filter 'Type = "GPT: System"') -and (Confirm-DellUEFISetting BootSequence BootList "UEFI Boot")){
    Start-Process -FilePath "$ENV:WINDIR\System32\mbr2gpt.exe" -ArgumentList "/convert /allowfullos" -wait
}

HP

Function Confirm-HPUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Setting,
    [Parameter(Position = 1,mandatory = $true)]$Value
    ) 
    (get-ciminstance -classname hp_biosEnumeration -namespace root/hp/instrumentedBIOS | Where-Object{$_.Name -eq "$($Setting)"} | select-object -ExpandProperty currentValue) -eq $Value
}

Function Set-HPUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Setting,
    [Parameter(Position = 1,mandatory = $true)]$Value,
    [Parameter(Position = 2)]$Password
    )
    $codes = @{
    0 = "Success"
    1 = "Not Supported"
    2 = "Unspecified Error"
    3 = "Timeout"
    4 = "Failed"
    5 = "Invalid Parameter"
    6 = "Access Denied"
    }
    $PWReq = (Get-CIMInstance -Namespace root/hp/instrumentedBIOS -ClassName HP_BIOSSettingInterface) -eq 1
    if($PWReq -and ($password -eq $NULL -or $password -eq "")){Write-error "Password is set but no password was provided"}
    else{
        if($password){$formattedpassword = '<utf-16/>' + $Password} else{$formattedpassword = ""}
        $ReturnValue = (Invoke-CimMethod -InputObject (Get-CimInstance -classname HP_BIOSSettingInterface -namespace root/hp/instrumentedBIOS) -MethodName setbiossetting -Arguments @{ Name = $Setting; Value = $value; Password = $formattedpassword }).Return
        if($ReturnValue -ne 0){Write-error "Setting failed to apply. $($Codes.item($ReturnValue))"}
    }
}

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$password=$TS.Value('UEFIPassword')

if(!(Confirm-HPUEFISetting "TPM Activation Policy" "No prompts")){Set-HPUEFISetting "TPM Activation Policy" "No prompts" $Password}
if(!(Confirm-HPUEFISetting "TPM Device" Available)){Set-HPUEFISetting "TPM Device" Available $Password}
if(!(Confirm-HPUEFISetting "TPM State" Enable)){Set-HPUEFISetting "TPM State" Enable $Password}

if(!(Confirm-HPUEFISetting "UEFI Boot Options" Enable)){Set-HPUEFISetting "UEFI Boot Options" Enable $Password}
if(!(Confirm-HPUEFISetting "Legacy Boot Options" Disable)){Set-HPUEFISetting "Legacy Boot Options" Disable $Password}
if(!(Confirm-HPUEFISetting "Configure Legacy Support and Secure Boot" "Legacy Support Disable and Secure Boot Enable")){Set-HPUEFISetting "Configure Legacy Support and Secure Boot" "Legacy Support Disable and Secure Boot Enable" $Password}

if(!(Confirm-HPUEFISetting "Virtualization Technology (VTx)" Enable)){Set-HPUEFISetting "Virtualization Technology (VTx)" Enable $Password}
if(!(Confirm-HPUEFISetting "Virtualization Technology for Directed I/O (VTd)" Enable)){Set-HPUEFISetting "Virtualization Technology for Directed I/O (VTd)" Enable $Password}

if(!(get-ciminstance Win32_DiskPartition -Filter 'Type = "GPT: System"') -and (Confirm-HPUEFISetting "UEFI Boot Options" Enable)){
    Start-Process -FilePath "$ENV:WINDIR\System32\mbr2gpt.exe" -ArgumentList "/convert /allowfullos" -wait
}

Lenovo

Function Confirm-LenovoUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Setting,
    [Parameter(Position = 1,mandatory = $true)]$Value
    ) 
    (get-ciminstance -classname Lenovo_BiosSetting -namespace root\wmi | Where-Object{$_.CurrentSetting -like "$($Setting),*"} | select-object -ExpandProperty CurrentSetting).split(',')[-1] -eq $Value
}

Function Set-LenovoUEFISetting{
    param(
    [Parameter(Position = 0,mandatory = $true)]$Setting,
    [Parameter(Position = 1,mandatory = $true)]$Value,
    [Parameter(Position = 2)]$Password
    )
    $PWReq = ((Get-CIMInstance -Namespace root\wmi -ClassName Lenovo_BiosPasswordSettings).PasswordState -in @(2,3,6,7))
    if($PWReq -and ($password -eq $NULL -or $password -eq "")){Write-error "Password is set but no password was provided"}
    elseif($PWReq -and $password){
        $R1 = (Invoke-CimMethod -InputObject (Get-CimInstance -classname Lenovo_SetBiosSetting -namespace root\wmi) -MethodName SetBiosSetting -Arguments @{ parameter = "$Setting,$value,$password,ascii,us" }).Return
        $R2 = (Invoke-CimMethod -InputObject (get-ciminstance -classname Lenovo_SaveBiosSettings -namespace root\wmi) -MethodName SaveBiosSettings  -Arguments @{ parameter = "$Password,ascii,us" }).Return
    }
    else{
        $R1 = (Invoke-CimMethod -InputObject (Get-CimInstance -classname Lenovo_SetBiosSetting -namespace root\wmi) -MethodName SetBiosSetting -Arguments @{ parameter = "$($Setting),$($Value)" }).Return
        $R2 = (Invoke-CimMethod -InputObject (get-ciminstance -classname Lenovo_SaveBiosSettings -namespace root\wmi) -MethodName SaveBiosSettings).Return
    }
    if(($R1 -ne "SUCCESS") -or ($R2 -ne "SUCCESS")){Write-error "Setting failed to apply."}
}

$TS = New-Object -ComObject Microsoft.SMS.TSEnvironment
$password=$TS.Value('UEFIPassword')

if(!(Confirm-LenovoUEFISetting SecureBoot Enable)){Set-LenovoUEFISetting SecureBoot Enable $password}
if(!(Confirm-LenovoUEFISetting SecurityChip Enable)){Set-LenovoUEFISetting SecurityChip Enable $password}
if(!(Confirm-LenovoUEFISetting VirtualizationTechnology Enable)){Set-LenovoUEFISetting VirtualizationTechnology Enable $password}
if(!(Confirm-LenovoUEFISetting VTdFeature Enable)){Set-LenovoUEFISetting "VTdFeature" "Enable" $password}
if(!(Confirm-LenovoUEFISetting TXTFeature Enable)){Set-LenovoUEFISetting TXTFeature Enable $password}

if(!(get-ciminstance Win32_DiskPartition -Filter 'Type = "GPT: System"') -and (Confirm-LenovoUEFISetting SecureBoot Enable)){
    Start-Process -FilePath "$ENV:WINDIR\System32\mbr2gpt.exe" -ArgumentList "/convert /allowfullos" -wait
}

I added the DCPP and its pre-req to the task sequence, conditioned to only install on Dell systems.

The remaining piece is controlling the reboot. We can handle that in two separate ways. We can leave the application set to complete the reboot, or we can disable that setting on each deployment type and add the reboot to the task sequence itself. In this example I am using the task sequence method as it is different than the method I used as an example in part 3.

There you have it, you can now interact with your Dell, HP, and Lenovo UEFI settings via Configuration Manager.