Boot image selection during PXE in System Center 2012 Configuration Manager (ConfigMgr) is something that comes up from time to time in the forums as well as every-day discussions. This can be quite confusing to explain or comprehend in normal language even though it’s truly not that difficult once you get it.
The logic for boot image selection is actually contained in relatively small stored procedure named NBS_GetPXEBootAction and (mostly) copied at the bottom of this post for reference. Here’s a concise summary of this stored procedure (although a few minor nuances are left out):
- Find all task sequence deployments targeted at the system being PXE booted (lines 36-44)
- Filter out the following:
- Task Sequence deployments for task sequences with no boot images (lines 43-44).
- Task Sequence deployments with boot images not on the DP being PXE booted from (lines 47-48)
- Required Task Sequence deployments that have run on the target system before (line 55)
- Order the Task Sequence deployments by
- Required or available (required first)
- OfferID (highest first)
The boot image associated with the task sequence deployment ordered first by this stored procedure is then sent to the client. And there you have the boot image selection process for ConfigMgr.
- This stored procedure doesn’t look up a device in the database to determine if it’s known or unknown, that’s handled by two other stored procedures called before this one: NBS_LookupDevice and MP_GetClientIDFromSmbiosID.
- Architecture of the PXE booted system or boot image is not accounted for so make sure you are properly targeting your task sequences to consider boot image architecture and UEFI.
- OfferID is synonymous with the DeploymentID of the task sequence and more recent deployments have higher IDs.
- OfferID ordering orders by task sequence deployment creation time and not task sequence creation time. Thus, more recently deployed task sequences are ordered before task sequences deployed in the past.
- If only one task sequence is applicable to a device, of course there’s only one possible boot image based upon the above. The only time the stored procedure is truly significant is if there is more than one task sequence targeted at a system. This creates possible ambiguity which is then effectively resolved by this stored procedure.
- To manipulate boot image selection, create a new task sequence deployment targeted at the system(s) where you need to change what boot image is used. This will create a deployment with a larger DeploymentID which will be ordered at the top of the list by the stored procedure.
- Update: The process described here isn’t about which boot image a task sequence will actually use; that is always dictated by the boot image assigned to the task sequence. This process is about which boot image will be delivered to a PXE booted client at PXE time. This may differ from the boot image ultimately used because ConfigMgr may not know which task sequence will actually be executed as this isn’t always set at PXE time. Basically, anytime there is more than one possible task sequence deployed to a system, ConfigMgr does not know which task sequence is going to be run so has to make a choice about which boot image to deliver for PXE boot purposes. After the task sequence is determined (usually based on user input and well after the PXE boot has happened), if the boot image associated with that task sequence is different from the one used to boot, then ConfigMgr will pre-stage that boot image to the system and reboot to it.
ALTER PROCEDURE [dbo].[NBS_GetPXEBootAction] @ItemKey int, @UnknownItemKey int, @SMBIOSGUID nvarchar(38), @MACAddress nvarchar(38), @DPName nvarchar(255) AS BEGIN SET NOCOUNT ON SELECT @MACAddress AS 'MACAddress', @SMBIOSGUID AS 'SMBIOS_GUID', xref.GUID AS 'SMS_UniqueIdentifier0', '' AS 'LastPXEAdvertisementID', '' AS 'LastPXEAdvertisementTime', sp.OfferID AS 'OfferID', po.PresentTime AS 'OfferIDTime', po.PkgID AS 'PkgID', tspkg.Version AS 'PackageVersion', cdp.URL AS 'PackagePath', tspkg.BootImageID AS 'BootImageID', CASE WHEN ((po.OfferFlags & 0x00000620) != 0) THEN 1 -- 0x620 = AP_ON_LOGON | AP_ON_LOGOFF | AP_ASAP WHEN (ISNULL(po.MandatorySched,'')!= '') THEN 1 ELSE 0 END AS 'Mandatory', CASE WHEN (EXISTS (select System_DISC.ItemKey from System_DISC where System_DISC.ItemKey = xref.MachineID AND ISNULL(System_DISC.Decommissioned0,0) != 0 AND ISNULL(System_DISC.Obsolete0,0) != 0 AND ISNULL(System_DISC.Unknown0,0) != 0)) THEN 0 WHEN (xref.MachineID = @ItemKey) THEN 1 ELSE 0 END AS 'Known' FROM MachineIdGroupXRef xref JOIN ResPolicyMap AS rpm ON xref.MachineID = rpm.MachineID JOIN SoftwarePolicy AS sp ON (rpm.PADBID = sp.PADBID AND rpm.IsTombstoned != 1) JOIN ProgramOffers AS po ON sp.OfferID = po.OfferID AND po.[Action] <> 3 JOIN vSMS_TaskSequencePackage AS tspkg ON (tspkg.PkgID = sp.PkgID AND (ISNULL(tspkg.BootImageID,'')!= '')) JOIN PkgPrograms as pp ON (tspkg.PkgID = pp.PkgID AND (pp.ProgramFlags & 4096) = 0 AND pp.[Action] <> 3) -- 4096 = disabled JOIN ContentDPMap AS cdp ON (cdp.ContentID = tspkg.BootImageID AND cdp.ServerName = @DPName) WHERE xref.MachineID IN (@ItemKey) AND ((CASE WHEN ((po.OfferFlags & 0x00000620) != 0) THEN 1 -- 0x620 = AP_ON_LOGON | AP_ON_LOGOFF | AP_ASAP WHEN (ISNULL(po.MandatorySched,'')!= '') THEN 1 ELSE 0 END) = 0 OR (NOT EXISTS (select * from LastPXEAdvertisement as lpa where lpa.MAC_Addresses = @MACAddress AND lpa.LastPXEAdvertisementID = sp.OfferID))) AND (po.OfferFlags & 0x00040000) != 0 -- 0x00040000 = AP_ENABLE_TS_FROM_CD_AND_PXE ORDER BY Known DESC, Mandatory DESC, OfferID DESC END