Learn how to PXE Boot both BIOS & UEFI machines with DHCP Policies and Custom Vendor Classes
One of the challenges that an IT deployment administrator may face in the field is the ability to boot both BIOS and UEFI machines from the same WDS environment. This is exactly the issue I faced when our organization decided to purchase a number of new Surface devices. These were the first set of devices that were configured to natively boot to UEFI. This leaves you to decide from an organization standpoint whether you wish to boot all your devices using UEFI or the legacy BIOS…or does it.
I am a strong believer that finding a workaround to a problem is not a fix to the problem. To that end modern devices such as the surface are meant to be booted using the native UEFI boot. However, many organizations may also still have legacy BIOS devices that do not support UEFI boot or just work better booting from BIOS. Whatever the reasoning behind this it is actually quite easy to setup DHCP to provide the BIOS or UEFI boot file depending on what is used.
The solution!
By using DHCP policies and custom vendor classes for the following DHCP Options:
Option 60
Option 66
Option 67
The below assumes that you have SCCM configured with a PXE enabled distribution point and a valid and configured DHCP server. You should therefore be at a configured state where you are able to PXE boot BIOS based devices.
Create Custom Vendor Classes for Use with your DHCP Policy
Think Custom Vendor Classes as Detection Method’s used to determine how devices are requesting a boot image from the DHCP server.
Open the DHCP Console and expand the IPv4 Node
Right-Click on ‘IPv4 Node’ and select ‘Define Vendor Classes’
Click ‘Add’
Create the UEFI 64-Bit Vendor class first by entering the following information
Enter the following information for the respective fields:
DisplayName: PXEClient (UEFI x64)
Description: PXEClient:Arch:00007
ASCII: PXEClient:Arch:00007
Click ‘OK’
Click ‘Add’
DisplayName: PXEClient (UEFI x86)
Description: PXEClient:Arch:00006
ASCII: PXEClient:Arch:00006
Click ‘OK’
Click ‘Add’
DisplayName: PXEClient (BIOS x86 & x64)
Description: PXEClient:Arch:00000
ASCII: PXEClient:Arch:00000
Click ‘OK’
Creating Custom DHCP Policies
UEFI 64-Bit DHCP Policy
Right-Click ‘Policies’ and click ‘New Policy’
Give the policy a friendly name that coincides with the your vendor class naming scheme:
PolicyName: PXEClient (UEFI x64)
Description: Delivers the correct bootfile for (UEFI x64)
Click ‘Next’
On the ‘Configure Conditions for the policy’ page click ‘add’
Select the ‘Value’ drop-down box and select the PXEClient (UEFI x64) vendor class that you created in previous steps
Ensure that you check the box ‘Append wildcard(*)’
Select ‘Add’
Select ‘Ok’
Click ‘Next’
If you want the policy to affect only a specific range within your scope configure it, otherwise select no and click ‘next’
On the Configure settings for the policy page ensure that ‘DHCP Standard Options’ is selected from the drop down box
Configure the following scope options:
060: PXEClient
066: IP Address of the SCCM or WDS Service
067: smsboot\x64\wdsmgfw.efi
Cick ‘Next’
On the Summary page click ‘Finish’
BIOS 32-Bit & 64-Bit DHCP Policy
Right-Click ‘Policies’ and click ‘New Policy’
Give the policy a friendly name that coincides with the your vendor class naming scheme:
PolicyName: PXEClient (BIOS x86 & x64)
Description: Delivers the correct bootfile for BIOS machines
Click ‘Next’
On the ‘Configure Conditions for the policy’ page click ‘add’
Select the ‘Value’ drop-down box and select the PXEClient (BIOS x86 & x64) vendor class that you created in previous steps
Ensure that you check the box ‘Append wildcard(*)’
Select ‘Add’
Select ‘Ok’
Click ‘Next’
If you want the policy to affect only a specific range within your scope configure it, otherwise select no and click ‘next’
On the Configure settings for the policy page ensure that ‘DHCP Standard Options’ is selected from the drop down box
Configure the following scope options:
060: PXEClient
066: IP Address of the SCCM or WDS Service
067: smsboot\x64\wdsnbp.com
Cick ‘Next’
On the Summary page click ‘Finish’
UEFI 32-Bit DHCP Policy
Right-Click ‘Policies’ and click ‘New Policy’
Give the policy a friendly name that coincides with the your vendor class naming scheme:
PolicyName: PXEClient (UEFI x86)
Description: Delivers the correct bootfile for (UEFI x86) machines
Click ‘Next’
On the ‘Configure Conditions for the policy’ page click ‘add’
Select the ‘Value’ drop-down box and select the PXEClient (UEFI x86) vendor class that you created in previous steps
Ensure that you check the box ‘Append wildcard(*)’
Select ‘Add’
Select ‘Ok’
Click ‘Next’
If you want the policy to affect only a specific range within your scope configure it, otherwise select no and click ‘next’
On the Configure settings for the policy page ensure that ‘DHCP Standard Options’ is selected from the drop down box
Configure the following scope options:
060: PXEClient
066: IP Address of the SCCM or WDS Service
067: smsboot\x86\wdsmgfw.efi
Cick ‘Next’
On the Summary page click ‘Finish’
Remove Default PXE Options
Ensure that you have removed the 067, 066, 060 options from the default scope options to ensure that the Policies take precedence otherwise you will end up with conflict
As long as you have configured everything correctly you should now have the ability to boot machines from BIOS or UEFI. Hopefully this helps alleviate some of the stress surrounding your PXE deployments. This has worked great on all of our distribution points since implementation and has allowed our deployments to be much more flexible.
Well... couldn't figure out how to set the inner "Option" on the policy, but everything else is here.
Remember to run this in an administrative powershell prompt on the DHCP server.
You need to restart the DHCPServer service after running this and set the PXEClient settings in the 3 policies. The BIOS policy is blank, the UEFI polcies are the default of "PXEClient".
The command to run is "Set-DHCPPXEOptions"
Enjoy!
<# .Synopsis Receives user input, gets the list of DHCP options, classes and policies, then sets them if they don't exist..DESCRIPTION Enter the option number, class name or policy name where approporiate..NOTES Author: Derek Bannard.EXAMPLE Import-Module .\DHCPPXEOptions.psm1 Loads the modules to perform the DHCP functions..EXAMPLE Get-DHCPOptions Lists missing options for use with Set-DHCPPXEOptions function..EXAMPLE Get-DHCPClasses Lists missing classes for use with Set-DHCPPXEOptions function..EXAMPLE Get-DHCPPolicies Lists missing policies for use with Set-DHCPPXEOptions function..EXAMPLE Set-DHCPPXEOptions Creates all missing options, classes and policies for BIOS/UEFI PXE co-existance.#><#=================================================Error Preferences=================================================#>$errpref = $ErrorActionPreference$ErrorActionPreference = "SilentlyContinue"<#=================================================Script Variables, comma separated=================================================#>[string[]]$DHCPOptions = 060,066,067[string[]]$DHCPClasses = "PXEClient:Arch:00000","PXEClient:Arch:00006","PXEClient:Arch:00007"[string[]]$DHCPPolicies = "PXEClient (BIOS x86 & x64)","UEFI 32-Bit DHCP Policy","UEFI 64-Bit DHCP Policy"[string[]]$rtnDHCPOptions = @()[string[]]$rtnDHCPClasses = @()[string[]]$rtnDHCPPolicies = @()<#=================================================Script Get Functions=================================================#>Function Get-DHCPOptions{ $arrayOptions = New-Object System.Collections.ArrayList ForEach ($DHCPOption in $DHCPOptions){ Try{ If((Get-DhcpServerv4OptionDefinition -OptionId $DHCPOption) -eq $null){ Write-Verbose "OptionId $DHCPOption is not present." $arrayOptions.Add($DHCPOption) | Out-Null } Else{ Write-Verbose "OptionId $DHCPOption is already present." } } Catch{ } } $global:rtnDHCPOptions = $arrayOptions}Function Get-DHCPClasses{ $arrayClasses = New-Object System.Collections.ArrayList ForEach ($DHCPClass in $DHCPClasses){ Try{ If((Get-DhcpServerv4Class -Type Vendor | Where {$_.AsciiData -eq $DHCPClass}) -eq $null){ Write-Verbose "OptionId $DHCPClass is not present." $arrayClasses.Add($DHCPClass) | Out-Null } Else{ Write-Verbose "OptionId $DHCPClass is already present." } } Catch{ } } $global:rtnDHCPClasses = $arrayClasses}Function Get-DHCPPolicies{ $arrayPolicies = New-Object System.Collections.ArrayList ForEach ($DHCPPolicy in $DHCPPolicies){ Try{ If((Get-DhcpServerv4Policy -Name $DHCPPolicy) -eq $null){ Write-Verbose "OptionId $DHCPPolicy is not present." $arrayPolicies.Add($DHCPPolicy) | Out-Null } Else{ Write-Verbose "OptionId $DHCPPolicy is already present." } } Catch{ } } $global:rtnDHCPPolicies = $arrayPolicies}<#=================================================Script Set Function=================================================#>Function Set-DHCPPXEOptions{ If($rtnDHCPOptions){ ForEach ($rtnDHCPOption in $rtnDHCPOptions){ If($rtnDHCPOption -eq "060"){ Try{ Write-Output "Adding OptionId 060..." Add-DhcpServerv4OptionDefinition -Name "PXEClient" -Description "PXE Support" -DefaultValue "PXEClient" -OptionId 060 -Type String } Catch{ } } ElseIf($rtnDHCPOption -eq "066"){ Try{ Write-Output "Adding OptionId 066..." Add-DhcpServerv4OptionDefinition -Name "Boot Server Host Name" -Description "TFTP boot server host name" -OptionId 066 -Type String } Catch{ } } ElseIf($rtnDHCPOption -eq "067"){ Try{ Write-Output "Adding OptionId 067..." Add-DhcpServerv4OptionDefinition -Name "Bootfile Name" -Description "Bootfile Name" -OptionId 067 -Type String } Catch{ } } Else{ Write-Output "Undefined options cannot be added!" } } } Else{ Write-Output "No Options are required to be added." } If($rtnDHCPClasses){ ForEach ($rtnDHCPClass in $rtnDHCPClasses){ If($rtnDHCPClass -eq "PXEClient:Arch:00000"){ Try{ Write-Output "Adding PXEClient (BIOS x86 & x64) Class..." Add-DhcpServerv4Class -Name "PXEClient (BIOS x86 & x64)" -Type Vendor -Data "0x505845436c69656e743a417263683a3030303030" -Description "PXEClient:Arch:00000" } Catch{ } } ElseIf($rtnDHCPClass -eq "PXEClient:Arch:00006"){ Try{ Write-Output "Adding UEFI 32-Bit DHCP Class..." Add-DhcpServerv4Class -Name "PXEClient (UEFI x86)" -Type Vendor -Data "0x505845436c69656e743a417263683a3030303036" -Description "PXEClient:Arch:00006" } Catch{ } } ElseIf($rtnDHCPClass -eq "PXEClient:Arch:00007"){ Try{ Write-Output "Adding UEFI 64-Bit DHCP Class..." Add-DhcpServerv4Class -Name "PXEClient (UEFI x64)" -Type Vendor -Data "0x505845436c69656e743a417263683a3030303037" -Description "PXEClient:Arch:00007" } Catch{ } } Else{ Write-Output "Undefined classes cannot be added!" } } } Else{ Write-Output "No Classes are required to be added." } If($rtnDHCPPolicies){ ForEach ($rtnDHCPPolicy in $rtnDHCPPolicies){ If($rtnDHCPPolicy -eq "PXEClient (BIOS x86 & x64)"){ Try{ Write-Output "Adding PXEClient (BIOS x86 & x64) Policy..." Add-DhcpServerv4Policy -Name "PXEClient (BIOS x86 & x64)" -Description "Delivers the correct bootfile for BIOS machines" -Condition OR -VendorClass EQ,"PXEClient (BIOS x86 & x64)*" -ProcessingOrder 1 -Enabled $True -Confirm:$False } Catch{ } } ElseIf($rtnDHCPPolicy -eq "UEFI 32-Bit DHCP Policy"){ Try{ Write-Output "Adding UEFI 32-Bit DHCP Policy..." Add-DhcpServerv4Policy -Name "UEFI 32-Bit DHCP Policy" -Description "Delivers the correct bootfile for (UEFI x86) machines" -Condition OR -VendorClass EQ,"PXEClient (UEFI x86)*" -ProcessingOrder 3 -Enabled $True -Confirm:$False } Catch{ } } ElseIf($rtnDHCPPolicy -eq "UEFI 64-Bit DHCP Policy"){ Try{ Write-Output "Adding UEFI 64-Bit DHCP Policy..." Add-DhcpServerv4Policy -Name "UEFI 64-Bit DHCP Policy" -Description "Delivers the correct bootfile for (UEFI x64) machines" -Condition OR -VendorClass EQ,"PXEClient (UEFI x64)*" -ProcessingOrder 2 -Enabled $True -Confirm:$False } Catch{ } } Else{ Write-Output "Undefined policies cannot be added!" } } } Else{ Write-Output "No Policies are required to be added." } #Restart-Service "DHCPServer"}Get-DHCPOptionsGet-DHCPClassesGet-DHCPPolicies
One more question:
I also deploy BIOS x86, but the policy covers (x86 & x64). I will set up two 'Define Vendor Classes' for x86 and x64? But ASCII, could I set as PXEClient:Arch:00000 for both?
I'm not sure how your infrastructure is configured however in our school division we deploy DHCP and WDS on the same VM and it works fine. We do use this script when configuring DHCP and WDS in a coexistence scenario, if my memory serves me i believe it sets the flags necessary for this scenario:
#ENSURE THE I: DRIVE IS COMPLETELY WIPED BEFORE RUNNING THE PROCEDING SCRIPTInstall-WindowsFeature WDSwdsutil /initialize-server /REMINST:I:\RemoteInstallStart-Sleep -Seconds 2Set-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Services\WDSServer\Providers\WDSPXE -Name UseDhcpPorts -Value 0Start-Sleep -Seconds 2WDSUTIL /Set-Server /UseDHCPPorts:No /DHCPOption60:YesStart-Sleep -Seconds 2Write-Host "The Server will now restart to finish configuring...Press <enter> to Continue!" -ForegroundColor GreenPauseShutdown -r -t 1
Comments (9)
Commented:
Remember to run this in an administrative powershell prompt on the DHCP server.
You need to restart the DHCPServer service after running this and set the PXEClient settings in the 3 policies. The BIOS policy is blank, the UEFI polcies are the default of "PXEClient".
The command to run is "Set-DHCPPXEOptions"
Enjoy!
Open in new window
Commented:
One more question:
I also deploy BIOS x86, but the policy covers (x86 & x64). I will set up two 'Define Vendor Classes' for x86 and x64? But ASCII, could I set as PXEClient:Arch:00000 for both?
Commented:
this wont work if WDS and DHCP are on same server
Author
Commented:There is no need to seperate these out into seperate vendor classes for x86 and x64 respectively as they both use the same architecture flag
That is why mine is combined in the article
Thanks
Author
Commented:I'm not sure how your infrastructure is configured however in our school division we deploy DHCP and WDS on the same VM and it works fine. We do use this script when configuring DHCP and WDS in a coexistence scenario, if my memory serves me i believe it sets the flags necessary for this scenario:
Open in new window
*EDIT: I should add that we only run the above if the built in Distribution Point install mechanism of the SCCM role installer fail us
View More