Boot image selection in ConfigMgr

Boot image selection in ConfigMgr

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):

  1. Find all task sequence deployments targeted at the system being PXE booted (lines 36-44)
  2. 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)
  3. 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.

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.

    @ItemKey        int,
    @UnknownItemKey int,
    @SMBIOSGUID     nvarchar(38),
    @MACAddress     nvarchar(38),
    @DPName         nvarchar(255)
    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',
               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',
               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



  1. If I understand correctly, there’s no way to force PXE to use the boot image specific to the architecture of the machine? I use an x86 boot image on my Windows 7 task sequence so I can do Dell BIOS updates (which won’t work on an x64 boot image due to no WOW subsystem). However, if I deploy a task sequence that uses an x64 boot image, the Windows 7 TS has to copy down the x86 boot image and then reboot to it. Very annoying.

    • Good question. Incorrect conclusion though. That’s something I missed pointing out in the post originally — that’s corrected now with the additional note above (marked with “Update”). Please read it as it should cover your comment.

  2. I’ve been trying to PXE boot a Surface Pro 3 with little success. I have WDS and Deployment Workbench setup on my server, DHCP options 66 & 67 set, everything works for BIOS machines. I’m wondering, do I have to have the full blow Configuration Manager suite install or will it work with what I have setup?

    • Surface Pro 3’s are of course UEFI based which means your WDS needs to be hosted on Server 2008 R2 or above. Additionally, there are lots of other weird issues with the firmware versions of Surface Pro 3s. There are lots of blogs posts out that go through many of the issues including those from Niall at which I would suggest you check out.

  3. What determines the OfferID number? You listed “Highest first”. What makes the OfferID higher or lower? Is is based on the order in which the task sequences were deployed? Thanks, and great post!!!

    • The OfferID is synonymous with advertisement/deployment ID. This is just a unique ID sequentially assigned to the deployments. Thus, the newer the deployment, the higher the ID.

  4. I know this topic hasn’t been visited for a year…but we are finally implementing PXE boot in our environment. One question that I have is if we are using SCCM to manage our PXE environment, how can we go about testing new boot images without making them available to our full production environment? From what I understand, the PXE environment only uses the newest deployment ID. Is there a way to designate a different deployment without affecting the one that is deployed to all DPs? We are currently using SCCM 1702 (yeah, I know we need to catch up). Thanks.

    • > “From what I understand, the PXE environment only uses the newest deployment ID.”

      Kind of. Please read above. This criterion is only used for the initial boot image delivered if there is ambiguity as to which boot image to use. If this doesn’t match the boot image assigned to a TS, then the system will download the correct boot image, stage it for booting, and then reboot the system.

      If you need to test a new boot image you can do one of two things.
      – Use an older, test task sequence that was previously deployed and simply swap out its boot image.
      – Deploy a new, test task sequence with the new boot image assigned and then immeidately re-deploy a task sequence with the proudction boot image assigned to it. This deployment doesn’t have to be a “real” deployment in that you can deploy it to an empty collection.

      You can initially combine these to create a long-term process:

      1. Create test sequence. What the test task sequence does is irrelevant really as that’s completely independent of the boot image.
      2. Assign a boot image to this test task sequence.
      3. Deploy this test task sequence to a “dummy” or an empty collection.
      4. Create a new deployment on the production task sequence with the production boot image assigned and delete the existing deployment.

      Then, in the future, you can just swap out the boot image on the test task sequence to test the boot image. Initially, the system will boot to the production boot image but as noted, when the test TS begins it’ll see that the boot image that the system booted to does not match the boot image assigned to the task sequence, download this assigned boot image, and reboot the system into this assigned boot image.

  5. Hi! Thanks for the great article and a little of reverse engineering 🙂

    Small note on OfferIDs: if we have a hierarchy with CAS, then a deployment made from site ZZZ always overrules one from site AAA, even if AAA deployment is newer than ZZZ.

    • Thank you for the input — it adds value to the post for those unlucky enough to be running a CAS (or those that chose incorrectly to use a CAS and thus get what they deserve: pain).