Differences

This shows you the differences between two versions of the page.

Link to this comparison view

appnote:wimboot_architecture [2015/01/02 14:07] (current)
svenx Article created.
Line 1: Line 1:
 +====== wimboot architecture ======
 +''​[[:​wimboot]]''​ is a boot loader that is roughly analogous to Windows'​ ''​pxeboot''​ network boot program. It lets you fetch all the relevant files over HTTP or any other supported protocol, and hands over execution to ''​bootmgr.exe'',​ the Windows boot manager. This page details the ''​wimboot''​ architecture,​ an overview of ''​bootmgr.exe''​ operation, and troubleshooting tips.
  
 +===== How wimboot works =====
 +
 +When ''​wimboot''​ is executed, it sets up a boot-loader environment before handing over execution to ''​bootmgr.exe'',​ the Windows boot manager, which continues to boot Windows according to the supplied boot configuration data (BCD).
 +
 +==== Command line processing ====
 +
 +When ''​wimboot''​ runs, it first processes the command line parameters supplied to it. The following parameters can be used to change its behaviour:
 +  * ''​rawbcd'':​ Disable rewriting ''​.exe''​ to ''​.efi''​ in the BCD file.
 +  * ''​gui'':​ Display graphical boot messages.
 +  * ''​pause[=quiet]'':​ Show info and wait for keypress.
 +  * ''​index=n'':​ Use WIM image index //n//.
 +  * ''​initrdfile'':​ Ignored. For syslinux compatibility.
 +
 +==== CPIO archive extraction ====
 +
 +Much like the Linux kernel, ''​wimboot''​ will extract the CPIO archive supplied to it by iPXE. The CPIO archive can be constructed with iPXE via the ''​[[:​cmd:​imgfetch]]''​ command, and each invocation should be on the form
 +
 +    imgfetch --name <​somename>​ <uri> <​somename>​
 +
 +This will fetch the file given by ''<​uri>''​ and make it available with the virtual filename ''<​somename>''​ in the CPIO archive supplied to ''​wimboot''​. Multiple ''​[[:​cmd:​imgfetch]]''​ commands can be used, one after another. The seemingly redundant ''<​somename>''​ statements are used to provide compatibility with both UEFI mode (''​%%--name <​name>​%%''​) and legacy BIOS mode (''<​name>''​ as the first argument) at the same time.
 +
 +**NOTE:** The virtual filename ''<​somename>''​ must be a flat filename without subdirectory components.
 +
 +==== The wimboot virtual filesystem ====
 +
 +The files from the CPIO archive are made available in a virtual filesystem provided up by ''​wimboot''​. Here's an example of how this works in practice:
 +
 +    imgfetch --name BCD http://​.../​test.bcd BCD
 +    imgfetch --name boot.sdi http://​.../​boot.sdi boot.sdi
 +    imgfetch --name boot.wim http://​.../​install.wim boot.wim
 +
 +This fetches the three files, which will all -- when ''​wimboot''​ executes -- be made available at //multiple locations// in a virtual filesystem. The locations are as follows:
 +  * ''​\''​
 +  * ''​\Boot''​
 +  * ''​\Boot\Fonts''​
 +  * ''​\Boot\Resources''​
 +  * ''​\Sources''​
 +  * ''​\EFI''​
 +  * ''​\EFI\Boot''​
 +  * ''​\EFI\Microsoft''​
 +  * ''​\EFI\Microsoft\Boot''​
 +
 +So for any given file, say ''​test.bcd'',​ it will be made available with the filename ''​BCD''​ at all the locations given above:
 +  * ''​\BCD''​
 +  * ''​\Boot\BCD''​
 +  * ''​\Boot\Fonts\BCD''​
 +  * ''​\Boot\Resources\BCD''​
 +  * ''​\Sources\BCD''​
 +  * ''​\EFI\BCD''​
 +  * ''​\EFI\Boot\BCD''​
 +  * ''​\EFI\Microsoft\BCD''​
 +  * ''​\EFI\Microsoft\Boot\BCD''​
 +
 +In practice, this enables ''​bootmgr.exe''​ to read ''​\Boot\BCD''​ and related files, even if they were seemingly placed only in the root directory by the ''​[[:​cmd:​imgfetch]]''​ command. This can avoid having to modify BCD files.
 +
 +Once it's set up, the virtual filesystem is then mapped to a disk drive so that ''​bootmgr.exe''​ can identify and read files from it.
 +
 +**NOTE:** The BCD file name must be simply ''​BCD''​ so that it can be found by ''​bootmgr.exe'';​ it searches only for the specific path ''​\Boot\BCD''​.
 +
 +**NOTE:** The ''​boot.sdi''​ and ''​boot.wim''​ paths must match the paths referred to in the BCD file. In other words, the BCD could refer to either ''​boot.wim'',​ ''​\Boot\boot.wim'',​ ''​\Sources\boot.wim''​ or any of the other recognized subdirs; they would all work. On the other hand, if the BCD refers to a path not covered by the virtual filesystem, like ''​\Image\boot.wim'',​ it would fail.
 +
 +==== Extracting bootmgr.exe ====
 +
 +As ''​wimboot''​ reads each file from the CPIO archive, the file's //virtual filename// is matched against a list of special names to see if it needs special treatment:
 +  * ''​bootmgr.exe'':​ Set this as the file to execute at the end of the boot-loader initialization.
 +  * ''​bootmgr'':​ Try to extract ''​bootmgr.exe''​ from this compressed bootmgr file, unless a ''​bootmgr.exe''​ was already supplied.
 +  * ''​*.wim'':​ Try to extract ''​bootmgr.exe''​ from the static path ''​\Windows\Boot\PXE\bootmgr.exe''​ within the supplied WIM image, unless a ''​bootmgr.exe''​ was already supplied.
 +
 +**NOTE:** The ability to extract ''​bootmgr.exe''​ from the WIM image was added to ''​wimboot''​ v2.2.0. It is a very convenient feature that lets you skip having to explicitly supply the ''​bootmgr.exe''​ file explicitly.
 +
 +**NOTE:** If no ''​bootmgr.exe''​ is found, ''​wimboot''​ exits.
 +
 +==== Running bootmgr.exe ====
 +
 +At the final stage of ''​wimboot''​ execution, it reads ''​bootmgr.exe''​ into memory and hands over execution to it.
 +
 +==== EFI platform differences ====
 +
 +On EFI platforms, a few details are changed:
 +  * ''​wimboot''​ can extract ''​bootmgfw.efi''​ from the supplied WIM image, using the path ''​\Windows\Boot\EFI\bootmgfw.efi''​.
 +  * ''​wimboot''​ automatically patches the BCD file to change any occurrence of ''​.exe''​ to ''​.efi''​. This behaviour can be disabled by the ''​rawbcd''​ argument to ''​wimboot''​.
 +
 +===== How bootmgr.exe works =====
 +
 +When ''​bootmgr.exe''​ executes, it has the first-stage environment already set up for it, containing the virtual filesystem set up by ''​wimboot''​. As it runs, it performs the following steps.
 +
 +Refer to the Microsoft //​[[http://​technet.microsoft.com/​en-us/​library/​cc771845|How Booting into a Boot Image Works]]// documentation for some additional details.
 +
 +==== Reading the BCD file ====
 +
 +''​bootmgr.exe''​ first interacts with the virtual filesystem by trying
 +to read the BCD ([[http://​technet.microsoft.com/​en-us/​library/​cc770770|Boot Configuration Data store]]) file from the hardcoded path ''​\Boot\BCD''​.
 +
 +The BCD file can come from a variety of sources, or it can be created from scratch or modified using the ''​bcdedit.exe''​ tool in Windows. See the troubleshooting section for more information.
 +
 +Refer to the Microsoft //​[[http://​technet.microsoft.com/​en-us/​library/​ee221031|Boot Process and BCDEdit]]// documentation for some additional details.
 +
 +==== Reading additional files ====
 +
 +Once the BCD is read, ''​bootmgr.exe''​ will try to read the files referred to by the BCD from the virtual filesystem, such as the stub ramdisk SDI (System Deployment Image) path, e.g. ''​\Boot\boot.sdi'',​ and the main WIM [[http://​technet.microsoft.com/​en-us/​library/​cc732289|Windows Imaging Format]]) image, e.g. ''​\Boot\boot.wim''​.
 +
 +**NOTE:** The SDI image is typically always provided by various Windows versions and deployment tools as ''​boot.sdi'',​ which is a template ramdisk with no content. It does not change significantly and does not need any change or customizations applied to it.
 +
 +**NOTE:** The WIM image is the main image, either extracted from the Windows installation medium, or containing custom content created by the user or some automated image creation/​capture process.
 +
 +==== Mounting the ramdisk ====
 +
 +Once the relevant files are read from the virtual filesystem, ''​bootmgr.exe''​ mounts the blank template SDI ramdisk and appends the WIM image to it.
 +
 +==== Executing winload.exe ====
 +
 +With the SDI+WIM ramdisk mounted and ready, ''​bootmgr.exe''​ hands over execution to the ramdisk as if it were an actual disk. The loading routines will eventually hand over execution to ''​\Windows\system32\winload.exe''​.
 +
 +===== Troubleshooting =====
 +
 +Several things can go wrong in the boot process, and the ''​bootmgr.exe''​ error handling and output is quite vague and ambiguous, making it hard to understand what the exact problem might be.
 +
 +==== Example errors ====
 +
 +Some common error messages are listed below:
 +
 +  * When ''​bootmgr.exe''​ cannot find or read the BCD file:
 +
 +    File: \Boot\BCD
 +    Status: 0xc000000f
 +    Info: An error occurred while attempting to read the boot configuration data.
 +
 +  * When ''​bootmgr.exe''​ cannot find or read the SDI file:
 +
 +    Status: 0xc000000f
 +    Info: The boot selection failed because a required device is inaccessible.
 +
 +  * When ''​bootmgr.exe''​ cannot find or read the WIM image:
 +
 +    Status: 0xc000000f
 +    Info: A required device isn't connected or can't be accessed.
 +
 +==== Finding the culprit ====
 +
 +The usual culprit is incorrect data in the BCD file, which causes ''​bootmgr.exe''​ to stall without knowing how to proceed. Incorrect data can typically be:
 +
 +  * referring to the wrong file name; or
 +  * referring to files outside the directories provided by the ''​wimboot''​ virtual file systems, such as ''​\'',​ ''​\Boot'',​ ''​\Sources'',​ etc.
 +
 +By following the ''​wimboot''/''​bootmgr.exe''​ execution chain, troubleshooting is made a bit easier:
 +  - Make sure to use the latest ''​wimboot''​ version.
 +  - Ensure that the ''​[[:​cmd:​imgfetch]]''​ commands are successful.
 +    * Use the ''​[[:​cmd:​imgstat]]''​ command (optionally followed by ''​[[:​cmd:​prompt]]''​ in scripts) to verify that the files fetched by ''​[[:​cmd:​imgfetch]]''​ were successfully retrieved.
 +  - Use the ''​pause''​ argument to ''​wimboot''​ to pause execution just after ''​wimboot''​ has printed some useful information about its initialization:​
 +
 +    imgexec wimboot pause
 +
 +Below is an example output of ''​[[:​cmd:​imgstat]]''​ showing the files that were retrieved, their sizes and their arguments. The arguments will map to the filenames as made available in the virtual filesystem set up by ''​wimboot'':​
 +
 +    test.bcd : 12288 bytes "​BCD"​
 +    boot.sdi : 3170304 bytes "​boot.sdi"​
 +    install.wim : 404876823 bytes "​boot.wim"​
 +    wimboot : 34576 bytes [bzImage] [SELECTED] "​pause=quiet"​
 +
 +An example output of the ''​wimboot''​ pause screen:
 +
 +    wimboot v2.4.1 -- Windows Imaging Format bootloader -- http://​ipxe.org/​wimboot
 +    ​
 +    Command line: "​pause=quiet"​
 +    Using BCD via 0x67925074 len 0x3000
 +    Using boot.sdi via 0x67929078 len 0x306000
 +    Using boot.wim via 0x67c30078 len 0x1821ee17
 +    ...found WIM file boot.wim
 +    ...found file "​\Windows\Boot\PXE\bootmgr.exe"​
 +    Using bootmgr.exe via 0x2bc18 len 0x7fd80
 +    ...extracted bootmgr.exe
 +    Emulating drive 0x81
 +    Entering bootmgr.exe with parameters at 0x2a520
 +
 +As for ''​bootmgr.exe'',​ it will try to read the essential BCD from ''​\Boot\BCD''​. Once it succeeds, it will inspect the BCD and act accordingly. Ensure that the BCD contains valid data and refers to files and paths that are reachable within the ''​wimboot''​ virtual filesystem.
 +
 +==== BCD contents ====
 +
 +Ensure that the BCD file contains valid configuration. To do this, you need to examine it with the Windows-only ''​bcdedit.exe''​ program. Alternatively,​ the [[http://​libguestfs.org/​hivex.3.html|hivex registry hive libraries]] and associated language bindings can be used on other platforms, but the BCD hive structure and data encoding makes it very cumbersome.
 +
 +Here's an example, using ''​bcdedit.exe''​ to dump the BCD contents:
 +
 +    > bcdedit /enum all /store test.bcd
 +    ​
 +    Windows Boot Manager
 +    --------------------
 +    identifier ​       {bootmgr}
 +    description ​      ​Windows 7 Boot Manager
 +    displayorder ​     {9b0a74...}
 +    timeout ​          30
 +    ​
 +    Windows Boot Loader
 +    -------------------
 +    identifier ​       {9b0a74...}
 +    device ​           ramdisk=[boot]\Boot\boot.wim,​{ramdiskoptions}
 +    description ​      ​Windows 7 Installation
 +    osdevice ​         ramdisk=[boot]\Boot\boot.wim,​{ramdiskoptions}
 +    systemroot ​       \Windows
 +    detecthal ​        Yes
 +    winpe             Yes
 +    ​
 +    Setup Ramdisk Options
 +    ---------------------
 +    identifier ​       {ramdiskoptions}
 +    description ​      ​Ramdisk Options
 +    ramdisksdidevice ​ boot
 +    ramdisksdipath ​   \Boot\boot.sdi
 +
 +You might find that the BCD file contains references to files that have paths that will not ever match ''​wimboot'''​s search list (''​\'',​ ''​\Boot'',​ ''​\Sources'',​ etc). If this is the case, you may want to either edit or recreate the BCD file.
 +
 +Here's an example of creating a BCD file from scratch:
 +
 +    set BCDSTORE=BCD
 +    bcdedit /​createstore %BCDSTORE%
 +    bcdedit /store %BCDSTORE% /create {ramdiskoptions} /d "​Ramdisk Options"​
 +    bcdedit /store %BCDSTORE% /set {ramdiskoptions} ramdisksdidevice Boot
 +    bcdedit /store %BCDSTORE% /set {ramdiskoptions} ramdisksdipath \Boot\boot.sdi
 +    for /f "​Tokens=3"​ %%x in ('​bcdedit /store %BCDSTORE% /create /d "​Windows 7 Installation"​ /​application osloader'​) do set GUID=%%x
 +    bcdedit /store %BCDSTORE% /set %GUID% systemroot \Windows
 +    bcdedit /store %BCDSTORE% /set %GUID% detecthal Yes
 +    bcdedit /store %BCDSTORE% /set %GUID% winpe Yes
 +    bcdedit /store %BCDSTORE% /set %GUID% osdevice ramdisk=[boot]\Boot\boot.wim,​{ramdiskoptions}
 +    bcdedit /store %BCDSTORE% /set %GUID% device ramdisk=[boot]\Boot\boot.wim,​{ramdiskoptions}
 +    bcdedit /store %BCDSTORE% /create {bootmgr} /d "​Windows 7 Boot Manager"​
 +    bcdedit /store %BCDSTORE% /set {bootmgr} timeout 30
 +    bcdedit /store %BCDSTORE% /set {bootmgr} displayorder %GUID%
 +    bcdedit /enum all /store %BCDSTORE%
 +
 +The BCD is a complex beast with lots of options, which makes it hard to know which details are required for the specific type of boot (ADK, AIK, WDS, etc). Refer to the iPXE [[:​howto:​winpe|WinPE]] documentation for more details.
 +
 +==== WIM image contents ====
 +
 +WIM files can be opened using a [[http://​en.wikipedia.org/​wiki/​Windows_Imaging_Format#​Tools|variety of tools]]. Should you need to verify the contents of the WIM image without access to Windows, use the example application ''​applywim''​ supplied with [[http://​wimlib.sourceforge.net/​|wimlib]]. This can be useful for verifying that ''​bootmgr.exe''​ is indeed located in the ''​\Windows\Boot\PXE\''​ directory.
appnote/wimboot_architecture.txt ยท Last modified: 2015/01/02 14:07 by svenx
Recent changes RSS feed CC Attribution-Share Alike 4.0 International Driven by DokuWiki
All uses of this content must include an attribution to the iPXE project and the URL http://ipxe.org
References to "iPXE" may not be altered or removed.