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

  1. Make sure to use the latest wimboot version.
  2. Ensure that the imgfetch commands are successful.
    • Use the imgstat command (optionally followed by prompt in scripts) to verify that the files fetched by imgfetch were successfully retrieved.
  3. 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 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 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 WinPE documentation for more details.

WIM image contents

WIM files can be opened using a 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 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: 2021/09/21 10:52 by nikize
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 https://ipxe.org
References to "iPXE" may not be altered or removed.