none
Applying the Win Recovery environment to a UEFI system - How is everyone doing it? RRS feed

  • Question

  • We've run into some trouble setting up Surface 3s with MDT 2013. Apparently there is a bug in the ZTIWinRE.wsf script, which causes it to copy winre.wim to the EFI system partition rather than the Recovery partition.

    https://social.technet.microsoft.com/Forums/en-US/22cb4d44-4215-483e-8bdc-b13d9d27725b/what-partition-does-mdt-2012-place-winre-on?forum=mdt#5e33d5d7-5ee4-432f-af65-710f08e99f72

    In addition to it being a nuisance, you are unable to enable bitlocker without a properly configured recovery partition.

    Which makes me wonder: am I the only person in the world trying to image Surfaces and enable Bitlocker? I can't imagine that that is the case. So how is everyone else doing it?

    After discovering that ZTIWinRE wasnt working, I scratched around for a few days and came up with this (below). I set conditions on ZTIWinRE to only run if IsUEFI=False, and this script ZTIWinRE_UEFI.wsf if IsUEFI=True. I had a hard time making any sense out of the ZTIDiskUtility.vbs functions, so theres probably an easier way to do it.

    <job id="ZTIWinRE_UEFI">
    	<script language="VBScript" src="ZTIUtility.vbs"/>
    	<script language="VBScript" src="ZTIDiskUtility.vbs"/>
    	<script language="VBScript">
    ' //----------------------------------------------------------------------------
    ' //
    ' // File: ZTIWinRE_MDT_UEFI
    ' //
    ' // Purpose: Sets Recovery Environment
    ' //
    ' // Usage: cscript ZTIWinRE_UEFI
    ' //
    ' //----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// Global constant and variable declarations
    '//----------------------------------------------------------------------------
    
    'Option Explicit
    
    Dim iRetVal
    Dim sArchitecture, colVolumes, objVolume
    Dim strREDriveLetter, strSource, strDestFolder, strDestFile
    
    '//----------------------------------------------------------------------------
    '// End declarations
    '//----------------------------------------------------------------------------
    
    '//----------------------------------------------------------------------------
    '// Main routine
    '//----------------------------------------------------------------------------
    
    iRetVal = ZTIProcess
    ProcessResults iRetVal
    'On Error Goto 0
    
    '//---------------------------------------------------------------------------
    '//
    '// Function: ZTIProcess()
    '// Return: Success - 0
    '// Failure - non-zero
    '//
    '// Purpose: Perform main ZTI processing
    '// 
    '//---------------------------------------------------------------------------
    
    Function ZTIProcess() 
    
    	 If UCase(oEnvironment.Item("PrepareWinRE")) <> "YES" then
    	 	oLogging.CreateEntry "WinRE is not enabled, Skip.", LogTypeInfo
    	 	Main = SUCCESS
    	 	Exit Function
    	 End If
    	
    	oLogging.CreateEntry "---------------- Initialization ----------------", LogTypeInfo
    	
    	oLogging.CreateEntry "Build = " & oEnvironment.Item("OSCurrentVersion"), LogTypeInfo
    	
    	If Left(oEnvironment.Item("OSCurrentVersion"),3) < "6.1" then
    		oLogging.CreateEntry "WinRE is not supported on Vista or Older. Skip.", LogTypeInfo
    		Main = SUCCESS
    		Exit Function			
    	End If
    		
    	sArchitecture= oEnvironment.Item("ImageProcessor")
    	If sArchitecture = "" then
    		sArchitecture = oEnvironment.Item("Architecture")
    		oLogging.CreateEntry "ImageProcessor not set, will boot into Windows PE architecture " & sArchitecture, LogTypeInfo
    	Else
    		oLogging.CreateEntry "Will boot into Windows PE architecture " & sArchitecture & " to match OS being deployed.", LogTypeInfo
    	End If
    	
    	If UCase(oEnvironment.Item("IsUEFI")) = "TRUE" Then
    		oLogging.CreateEntry "IsUEFI = TRUE", LogTypeInfo
    
    		strREDriveLetter = GetExistingRecoveryDrive
    		strDestFolder = strREDriveLetter & "\Recovery\WinRE"
    		
    		oUtility.RunWithConsoleLogging "cmd /c MkDir " & strDestFolder
    		oUtility.RunWithConsoleLogging "attrib -r -h -s " & strDestFolder & "\*.*"
    	Else
    		strDestFolder = "C:\Recovery\WinRE"
    	End If
    	
    	strSource = oEnvironment.Item("DeployRoot") & "\Boot\LiteTouchPE_" & sArchitecture & ".wim"
    	
    	strDestFile = "WinRE.wim"
    	
    	oLogging.CreateEntry "Installing " & strSource & " on " & sArchitecture, LogTypeInfo
    	oLogging.CreateEntry "Installing to " & strDestFolder & "\" & strDestFile, LogTypeInfo
    	
    	If oFSO.FileExists(strDestFolder & "\" & strDestFile) Then
    		oLogging.CreateEntry strDestFolder & "\" & strDestFile & " already exists", LogTypeInfo
    	Else
    		oLogging.CreateEntry "oFSO.CopyFile " & strSource & "," & strDestFolder & "\" & strDestFile & ", True", LogTypeInfo
    		oFSO.CopyFile strSource , strDestFolder & "\" & strDestFile, True
    	End If
    	
    	oUtility.RunWithConsoleLogging "C:\Windows\System32\ReAgentc.exe /disable"
    	oUtility.RunWithConsoleLogging "C:\Windows\System32\ReAgentc.exe /setreimage /path " & strDestFolder & " /target C:\Windows"
    	oUtility.RunWithConsoleLogging "C:\Windows\System32\ReAgentc.exe /enable"
    	
    
    		Set colVolumes = objWMI.ExecQuery ("Select name, description from Win32_Volume")
    		 
    		For Each objVolume in colVolumes
    		oLogging.CreateEntry objVolume.Name, objVolume.Description
    		Next
    
    	oLogging.CreateEntry "---------------- End Run ----------------", LogTypeInfo
    	
    End Function
    
    Function GetExistingRecoveryDrive
    
    	Dim iRetVal, oPartition, sQuery, sDriveLetter
    	
    	sDriveLetter = ""
    	sQuery = "SELECT * from Win32_LogicalDisk WHERE DriveType = 3"
    	
    	For Each oPartition in objWMI.ExecQUery(sQuery)
    		If InStr (oPartition.VolumeName,"Windows RE") <> 0 Then
    			sDriveLetter = oPartition.DeviceId
    			Exit For
    
    		End If
    		
    	Next
    	oLogging.CreateEntry "assigning value " & sDriveLetter & " to Function GetExistingRecoveryDrive", LogTypeInfo
    	
    	GetExistingRecoveryDrive = sDriveLetter
    
    End Function
    	</script>
    </job>



    • Edited by JoeZeppy Tuesday, October 28, 2014 7:22 PM error
    • Changed type JoeZeppy Thursday, October 30, 2014 1:06 PM
    • Changed type JoeZeppy Thursday, October 30, 2014 1:07 PM
    Tuesday, October 28, 2014 7:18 PM

Answers

  • In addition to it being a nuisance, you are unable to enable bitlocker without a properly configured recovery partition.

    Which makes me wonder: am I the only person in the world trying to image Surfaces and enable Bitlocker?

    Hold on there ... Recovery partitions are not, in of themselves, a requirement for Bitlocker on uEFI machines like Surface.

    Of course the optimal configuration for uEFI windows + WinRE + Recovery image is:

    But Windows can easily use this:

    http://technet.microsoft.com/en-us/library/dd744301(v=ws.10).aspx

    Where the System partition is 499MB (don't ask), and the Windows Partition is BitLockered. This works fine in MDT right now.


    Keith Garner - Principal Consultant [owner] - http://DeploymentLive.com

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Tuesday, October 28, 2014 10:56 PM
    Moderator
  • Optimal configuration in the fancy picture above is what I setup.  On Surface Pro 3's actually :)   A few things to note:

    1) I could not create the table seen as optimal configuration in MDT.  I think this is something that will eventually come to MDT.  If all of your units have the same HDD and do not have multiple spec-outs, you can use MDT and create fixed size partitions, but you can't use the diskpart shrink  function to get that recovery image on the end of an OSDISK taking up the rest of the drive.  

    Instead, I opted to use the diskpart txt file from http://technet.microsoft.com/en-us/library/hh825686.aspx .  I deployed then to drive variable named OSDISK and made sure that the OS partition was named the same in my diskpart txt file.

    IMPORTANT : The section in the diskpart txt -

    set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac" gpt attributes=0x8000000000000001

    That ID is what allows the Winre Tools partition to talk to the Windows Recovery partition outside of the deployed OS and allows access once authorized through bitlocker.

    2) I did not use ztiwinre at all, though I have a decent bit of Powershell knowledge to help me with creation and engagement of the recovery image.  Really all that was necessary knowledge to write it in Powershell was the reagentc commands.  You can see those commands being called in ztiwinre.  The process for mass deployment is have a named recovery drive that you copy the winre.wim to, a named partition that you copy the recovery image to, then engage the winre image and set the recovery image path.  Reagentc has offline image commands, so it's pretty easy to add it as an OS deployment step during a PE deployment.  

    So anyways yes it's definitely possible to configure Surface Pro 3's with bitlocker in the first configuration :)  It's pretty cool when it's working, it will prompt for bitlocker unlock when in WinRE.  Something to consider is that you do need a local administrator account that will give you authority over any recovery operations (does not need to be named administrator, just needs admin access).  When we deployed it, we had to create a new account specifically for it.  I tried to toy with enabling it on WinRE boot and disabling it after but with bitlocker you can't do much in that area.  If you have further questions otherwise let me know and I'll try to help on WinRE.

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Tuesday, October 28, 2014 11:41 PM
  • Yea honestly I found it worked best when following the diskpart.txt that came from the link above.  Really the steps to deploying winre aren't that complicated, it's just everything must be done in order. Those steps are -

    1. Create partition table with proper GUIDs above.

    2. Copy WinRE.wim to %YourWinREToolsPartition%\Recovery\WindowsRE.

    3. Copy your created customrefresh.wim -- Google instructions on creating this, I usually have MDT create this and shoot it back to the filer when it's done for deployment later.

    4. Engage the WinRE image in WinPE with the command Reagentc /setreimage /path T:\Recovery\WindowsRE /target %YourOSPartition%\Windows

    5. Engage recovery image on first boot with the command recimg /setcurrent %YourRecoveryPartition%\recimgdir  -- I added this in the Specialize > Windows Deployment > RunSynchronous unattend section.

    6. Hide drives.

    At this point you should have a machine with a deployed WinRE engaged and pointed at the customrefresh you created.  You can also place custom reset images as well -- for my environment I actually configured a reset to factory image and refresh to base state. (Refresh = reload critical directories back to a captured state saving user data, Reset = hard re-image of the machine from created .wim file).  While I don't expect you to create a custom process from this info, I was hoping it would at least give you some insight into how the recovery system actually works so it doesn't seem as difficult.  Let me know if this helps.

    Ryan

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Wednesday, October 29, 2014 2:17 PM

All replies

  • In addition to it being a nuisance, you are unable to enable bitlocker without a properly configured recovery partition.

    Which makes me wonder: am I the only person in the world trying to image Surfaces and enable Bitlocker?

    Hold on there ... Recovery partitions are not, in of themselves, a requirement for Bitlocker on uEFI machines like Surface.

    Of course the optimal configuration for uEFI windows + WinRE + Recovery image is:

    But Windows can easily use this:

    http://technet.microsoft.com/en-us/library/dd744301(v=ws.10).aspx

    Where the System partition is 499MB (don't ask), and the Windows Partition is BitLockered. This works fine in MDT right now.


    Keith Garner - Principal Consultant [owner] - http://DeploymentLive.com

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Tuesday, October 28, 2014 10:56 PM
    Moderator
  • Optimal configuration in the fancy picture above is what I setup.  On Surface Pro 3's actually :)   A few things to note:

    1) I could not create the table seen as optimal configuration in MDT.  I think this is something that will eventually come to MDT.  If all of your units have the same HDD and do not have multiple spec-outs, you can use MDT and create fixed size partitions, but you can't use the diskpart shrink  function to get that recovery image on the end of an OSDISK taking up the rest of the drive.  

    Instead, I opted to use the diskpart txt file from http://technet.microsoft.com/en-us/library/hh825686.aspx .  I deployed then to drive variable named OSDISK and made sure that the OS partition was named the same in my diskpart txt file.

    IMPORTANT : The section in the diskpart txt -

    set id="de94bba4-06d1-4d40-a16a-bfd50179d6ac" gpt attributes=0x8000000000000001

    That ID is what allows the Winre Tools partition to talk to the Windows Recovery partition outside of the deployed OS and allows access once authorized through bitlocker.

    2) I did not use ztiwinre at all, though I have a decent bit of Powershell knowledge to help me with creation and engagement of the recovery image.  Really all that was necessary knowledge to write it in Powershell was the reagentc commands.  You can see those commands being called in ztiwinre.  The process for mass deployment is have a named recovery drive that you copy the winre.wim to, a named partition that you copy the recovery image to, then engage the winre image and set the recovery image path.  Reagentc has offline image commands, so it's pretty easy to add it as an OS deployment step during a PE deployment.  

    So anyways yes it's definitely possible to configure Surface Pro 3's with bitlocker in the first configuration :)  It's pretty cool when it's working, it will prompt for bitlocker unlock when in WinRE.  Something to consider is that you do need a local administrator account that will give you authority over any recovery operations (does not need to be named administrator, just needs admin access).  When we deployed it, we had to create a new account specifically for it.  I tried to toy with enabling it on WinRE boot and disabling it after but with bitlocker you can't do much in that area.  If you have further questions otherwise let me know and I'll try to help on WinRE.

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Tuesday, October 28, 2014 11:41 PM
  • In all my queries searching combinations of the terms "UEFI, GPT, MDT, WinRE, and recovery", I was unable to come up with that information. I did make an attempt at trying to use the WinRE.wim on the EFI partition where ZTIWinRE puts it, and ReagentC.exe gave some strange error about it not being a valid format, something about running the diskpart "retain" command, which I didnt understand. So I assumed that it had to be on the recovery partition, especially since it has a GUID that is specifically named "recovery".

    PARTITION_MSFT_RECOVERY_GUID de94bba4-06d1-4d40-a16a-bfd50179d6ac

    Many people, yourself included, state that you shouldn't try to create your own formatting steps in MDT, but just let ZTIDiskPart do its thing. So I was trying to work within the framework of what was already there. When it just didn't work, I figured it was something I was doing wrong.

    I'm pretty good at basic VBScript, but the things in ZTIDiskUtility are kind of over my head, so I had a hard time trying to trace what ZTIWinRE was doing.  I'm new to the whole concept of GPT disks, and its a pretty complex subject. Running ReAgentC manually in Windows PE gave me a lot of errors I didnt quite understand, for a bit, I wasnt even convinced it actually worked in Windows PE.

    I'm still a bit lost as to what I should do. Mr Brooks below seems to say that it works better if its on the Recovery partition? I dont have a good grasp of all the subtleties in choosing one method over the other, and what I have works, so I'm thinking I should just stick with it...

    Wednesday, October 29, 2014 1:57 PM
  • I'm not worried about the 5th recovery image partition at this point, I was just trying to get the WinRE.Wim where it was supposed to be.

    So do you have one script that runs as one task to do all this, or is it multiple steps in the task sequence?

    Wednesday, October 29, 2014 2:00 PM
  • Yea honestly I found it worked best when following the diskpart.txt that came from the link above.  Really the steps to deploying winre aren't that complicated, it's just everything must be done in order. Those steps are -

    1. Create partition table with proper GUIDs above.

    2. Copy WinRE.wim to %YourWinREToolsPartition%\Recovery\WindowsRE.

    3. Copy your created customrefresh.wim -- Google instructions on creating this, I usually have MDT create this and shoot it back to the filer when it's done for deployment later.

    4. Engage the WinRE image in WinPE with the command Reagentc /setreimage /path T:\Recovery\WindowsRE /target %YourOSPartition%\Windows

    5. Engage recovery image on first boot with the command recimg /setcurrent %YourRecoveryPartition%\recimgdir  -- I added this in the Specialize > Windows Deployment > RunSynchronous unattend section.

    6. Hide drives.

    At this point you should have a machine with a deployed WinRE engaged and pointed at the customrefresh you created.  You can also place custom reset images as well -- for my environment I actually configured a reset to factory image and refresh to base state. (Refresh = reload critical directories back to a captured state saving user data, Reset = hard re-image of the machine from created .wim file).  While I don't expect you to create a custom process from this info, I was hoping it would at least give you some insight into how the recovery system actually works so it doesn't seem as difficult.  Let me know if this helps.

    Ryan

    • Marked as answer by JoeZeppy Thursday, October 30, 2014 1:07 PM
    Wednesday, October 29, 2014 2:17 PM
  • The way WinRE.wim works is that it needs to be in a named drive in the directory \Recovery\WindowsRE\.  When you run the reagentc /setreimage command, it actually does a few steps to engage the image.  You can validate this as the directory and WinRE.wim file change structure after command. 

    As for how I did it, well I wrote it about 6 months back now in Powershell in multiple scripts, the most powerful function I had in PS was the ability to get drive letters based on drive variable.  This made finding the drive letters trivial and file copies could be done to drive letter variables of $recoverydrive, $osdisk and $winretools.  You could also then run the reagentc commands with $osdisk\windows as well.

    These were the variables I used in case you're interested -

    $mydir = split-path -parent $myinvocation.mycommand.path
    $winredrive = get-wmiobject win32_volume -filter "Label='Tools'" | select-object -expandProperty "DriveLetter"
    $resetdrive = get-wmiobject win32_volume -filter "Label='Reset'" | select-object -expandProperty "DriveLetter"
    $osdrive = get-wmiobject win32_volume -filter "Label='OSDisk'" | select-object -expandProperty "DriveLetter"

    With the partitions labeled properly, I never had to hunt for them and passing files and commands to each partition was a piece of cake then.  I was actually thinking of rewriting this all into one script with parameter switches, if I do I'll try to write the steps on my blog in a tutorial.  It's really hard to find information on this subject, most of what I found was through my own testing and failing over and over. 

    Wednesday, October 29, 2014 2:45 PM
  • I think I got confused on that what the recovery parition is for. Everything I read about the "Recovery partition" kind of assumes you are going to re-image your PC from a hidden back up, which we don't plan to do, at least not right now, so I kind of glossed over that part of what I was reading to get to the mechanics of how to build it.

    For an on disk restore or refresh you need to have a separate environment from your system partition and your Windows partition, because the restore needs to be able to overwrite them both, correct?

    With my limited knowledge of the GPT structure, and only starting to use Bitlocker, which we're only deploying to Surfaces, which are only UEFI, and seeing that ReagentC is speaking directly to a disk offset instead of a drive letter, I jumbled all that data up and assumed that a recovery partition was a GPT thing, and it was the only way you could boot to WinRE in the UEFI world.

    Is this more of an on-disk restore thing? How does it work for a BIOS PC, with or with out a separate system partitition? Right now our BIOS pcs only have one partition, but eventually we will be replacing McAfee Safeboot with Bitlocker, so shortly we'll be looking at a system partition there too.

    Again, I'm more concerned with enabling Bitlocker than restoring an image, we have SCCM for re-images.

    Wednesday, October 29, 2014 2:59 PM
  • I've never tried it in a NTFS scenario yet honestly.  Adding bitlocker partition though is as easy as configuring the "extra partition" in the format and partition disk step in MDT.
    Wednesday, October 29, 2014 3:09 PM
  • MDT by default will correctly mark the WinRE partition with the section above in the ZTIDIskPArt.wsf script:

    If bCreateBootPartition Then
    		
    	sBootDrive = GetLastAvailableDriveLetter
    	bHasBootPartition = true
    			
    	If isuEFI then
    
    		oLogging.CreateEntry "Create an uEFI/GPT Boot Partition set. "  & sBootDrive, LogTypeInfo
    
    		oUtility.RunCommandWrite oExec, "CREATE PARTITION PRIMARY Size=" & cstr(WINRE_DRIVE_SIZE)
    		oUtility.RunCommandWrite oExec, "FORMAT QUICK FS=NTFS LABEL=""Windows RE tools"""
    		oUtility.RunCommandWrite oExec, "ASSIGN LETTER=" & left( GetLastAvailableDriveLetter, 1)
    		oUtility.RunCommandWrite oExec, "set id=""de94bba4-06d1-4d40-a16a-bfd50179d6ac"""
    		oUtility.RunCommandWrite oExec, "gpt attributes=0x8000000000000001"
    		oUtility.RunCommandWrite oExec, "DETAIL PARTITION"
    		oUtility.RunCommandWrite oExec, "DETAIL VOLUME"

    Of course if you design your own custom partitioning scheme, all bets are off and you have to do this manually.

    The problem with Windows Recovery+WinRE in MDT isn't ZTIDiskPart.wsf it's ZTIWinRE.wsf, which does not understand uEFI correctly.


    Keith Garner - Principal Consultant [owner] - http://DeploymentLive.com


    Wednesday, October 29, 2014 6:26 PM
    Moderator
  • So in reading ZTIWinre, that's what triggered me to write it myself. ZTIWinre.wsf really just handles the reagentc /setreimage and hiding of the recovery drive.  It looks like ztidiskpart handles the correct GUID for the WinRE partition, but any configured extra reset/refresh partitions need to be manually created with the same guid.

    Wednesday, October 29, 2014 7:31 PM
  • I think we're all on the same page, ZTIDiskpart is fine, ZTIWinRE is the problem. I just cant fix it, because I dont understand what its doing between line 100 and 112, where it is making calls to ZTIDiskUtility and returning the oDiskPart object. That and not understanding GPT really had me confused.

    I dont want to wedge something in where it doesn't go or comment out something important and cause some unknown problem six months from now, and have no idea what happened. I don't like poking at things I dont understand.  This is why I gave up and wrote my own, what I orignally posted.

    So if IsUEFI=True, I run mine, if its False, I run the stock script. That seems complicated, and I was looking for suggestions on what other people were doing. I appreciate all the help you've given me so far.

    Wednesday, October 29, 2014 8:30 PM
  • Keith

    I too am trying to image Surface Pro 3 and enable Bitlocker and we're running across the same issues.

    I've seen a couple of post from yourself suggesting you understand how to resolve this issue but I've not seen anything detailing what the problem is with ZTIWinRE.wsf.

    What do you recommend as the best way to 'fix' ZTIWinRE.wsf or workaround this?

    I can manually fix this by copying the WinRE environment from the OS Partition to the Recovery Partition, but this is not going to be feasible going forward as we are going to want to deploy by SCCM and automate everything. Is this problem still relevant in SCCM - we are using MDT currently to deploy, but will be deploying from SCCM for trial shortly.

    Thursday, November 13, 2014 9:20 AM
  • I just discovered a new wrinkle. I'm attempting to build an OEM_Preload image for Surfaces shipped direct to users. My custom ZTIWinRE_UEFI script cant find the drive letter for the recovery tools partition when running the media build from the hard drive. :( 
    Saturday, November 15, 2014 6:17 PM