Improving the TPM OSD Experience

Here’s the scenario: a machine just came back in from the field and it needs a reload. You kick off OSD, check your email for a few seconds, look back up, and you see a message that OSD has failed.

You’ve seen this before. You check the logs to be sure, but you already know what it is. The TPM needs to be cleared.

The TS fails because the TPM is already owned

The fix is easy enough–the machine is rebooted, the TPM is cleared, and OSD kicks off again–this time completing successfully. Unfortunately this is a time-consuming process. Let’s automate it!

 

The Goal

I want to build a solution that tells the OSD technician that the TPM isn’t cleared, and that everything’s going to be taken care of for them. It should be a non-event (or as close as possible) for them.

 

The Players

This solution uses a couple components:

  • UI++ (Already in use to collect information about how the machine should be configured, I also use it to determine the TPM ownership status)
  • Invoke-TpmPhysicalPresenceRequest.ps1 (The script which performs the TPM operations)

 

The Magic

UI++ Logic

I have this bit of code at the end of my UI++ XML file:

<!-- Runs some final preflight checks for modern OS -->
<Action Type="Preflight" Title="Preflight Checks" ShowBack="True">
<Check Text="Booted in UEFI" CheckCondition='"%XSystemUEFI%" = "True"'/>
<Check Text="Secure Boot Enabled" CheckCondition='"%XSystemSecureBoot%" = "True"'/>
<Check Text="TPM is available and activated" CheckCondition='%XTPMAvailable% AND %XTPMActivated% = True' Description="TPM must be enabled and activated." ErrorDescription="Enable and Activate TPM in the BIOS"/>
</Action>
<Action Type="TSVar" Name="XCMTpmNotice" Condition='"%XTPMOwned%" = "True"'>This TPM is owned and will be cleared. The computer will reboot and you may need to restart OSD.</Action>
<!-- Pre-Install reassurance dialog. -->
<Action Type="Info" Name="XCMFinalizePage" Title="Ready to Build!" ShowBack="True" Size="Tall">
<![CDATA[We've collected everything we need to know to build this machine. Here's a summary of pending configuration changes:<br><b>Target OU:</b> %OSDDomainOUName%<br><b>Timezone:</b> %OSDTimeZone%<br><b>Locale:</b> %OSDUserLocale%<br><br><b>%XCMTpmNotice%</b>]]>
</Action>

This code runs a final preflight check validating that UEFI and Secure Boot are enabled. It also checks to make sure the TPM is available and activated.

I used to have a TPM ownership check here, but it’s been moved to the TSVar line. If I detect that the TPM is owned the variable XCMTpmNotice is populated with a little message. (This message adds the note about “you may need to restart OSD” because I had one older machine that cleared the TPM fine but didn’t resume OSD as expected. All my other machines worked OK. Perhaps it was just a fluke, but I leave it in here as a just-in-case.)

Finally, I have a “Ready to Build!” page that covers some quick details about the pending installation. If the TPM needs to be cleared, we’ll show our message at the end.

 

Task Sequence Logic

In our task sequence, we need just a couple steps (and a group) –

The completed task sequence

  • Shortly after your UI++ step, add a new group (I named mine “TPM Preparation”). Add a condition that the group/step will run if Task Sequence Variable XTPMOwned equals True
    • UI++ creates this variable for us, so you don’t need an MDT “Gather” step for this 🙂
  • In your new group, add a Run PowerShell Script step (I named mine “TPM Physical Presence Request”).
    • The Script Name is Invoke-TpmPhysicalPresenceRequest.ps1 and the Parameters I use are -RequestedTpmOperation EnableAndActivateAndClear
    • There are many different operations you can perform here. The whole list can be found at the Windows Dev Center.
    • Set the PowerShell execution policy to Bypass.
  • Finally, add a Restart Computer step. It should run the boot image assigned to the task sequence after restart. I notify the user for 5 seconds with a message saying “A TPM presence operation has completed. The computer must now reboot.” just so technicians know why the computer is rebooting.

 

The End Result

Lights, Camera, Action! Now that we have all the pieces in place, here’s how OSD will flow:

  • If the TPM is not owned: nothing changes!
  • If the TPM is owned:
    • A message is added to the end of our UI++ prompt letting technicians know a reboot is coming soon
    • Our script runs, requesting that the physical presence of the TPM is changed (a log file is written out as well, and is shipped off if you collect logs at the end of OSD)
    • The computer reboots to complete the TPM request
    • OSD resumes from where it left off, and the machine builds successfully!

 

Now you’re automating for awesome!

-Jacob

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.