4

I am trying to understand the Windows boot process. I got as far as the EFI boot manager loading the Windows Boot Manager. But then it must access the BCD in order to proceed further with loading the OS or chainloading the next boot manager. How exactly does it find the BCD?

For example, in my system there are two BCDs on a GPT disk: one on the ESP, another on the System Reserved partition, which got cloned from the old MBR disk. Does the Boot Manager look on the ESP simply because the drive is GPT? Does it look in the “current” folder (is there such a thing at all at this stage, given no OS loaded yet)? Or is a more complicated algorithm involved?

A curious fact: if I remove the System Reserved partition, the Boot Manager won't start, complaining that the BCD is missing. And yet, if I make some changes to both BCDs (e. g. set different timeouts), then the ESP BCD settings are used, as expected.

  • BCD from a MBR HDD won’t be used by a Windows booted while in UEFI installed on a GPT HDD. – Ramhound Mar 22 '18 at 22:46
  • @Ramhound, one would think so. But my system refuses to boot without that ex-active partition, complaining that BCD is missing. I'm trying to figure out why, among all things. – Sergei Tachenov Mar 23 '18 at 04:45
  • So it’s missing, at that point, create a partition and create it. Tons of questions on how to do that. – Ramhound Mar 23 '18 at 04:48
  • @Ramhound, recreating a partition isn't a problem, I have a full backup. I did that right away. The problem is to figure out *why* it's needed at all. – Sergei Tachenov Mar 23 '18 at 04:51

2 Answers2

3

The Boot Manager looks for the BCD on the ESP because that's the only partition known at this stage and the firmware can probably only read FAT partitions. The path to the BCD (/EFI/Microsoft/Boot/BCD) on the ESP is probably hardcoded. UEFI was designed from the start to support the coexistence of software from different vendors, and /EFI/Microsoft is Microsoft's "playground" on the ESP.

Johan Myréen
  • 525
  • 1
  • 3
  • 6
  • The firmware, yes, but surely the Boot Manager can read NTFS. Otherwise it wouldn't be able to load Windows. Moreover, if I delete System Reserved (NTFS) partition, the Boot Manager refuses to work, complaining that the BCD is missing. And yet, it certainly does use the ESP BCD. Figures. – Sergei Tachenov Mar 23 '18 at 05:29
  • You are correct in that the Boot Manager can read NTFS, for the reason you stated. Still, it makes sense for the BCD to be stored on the ESP together with the Boot Manager, since the BCD is what directs what the Boot Manager should do next, potentially based on input from the user. The firmware starts (directed by variables in non-volatile RAM) `bootx64.efi`, which starts `bootmgr.efi`, which reads the BCD, and typically loads `winload.exe`, which is on the C: drive. In theory, `bootx64.efi` could be loaded the from NTFS, but then `bootx64.efi` would have to know how to read NTFS. – Johan Myréen Mar 23 '18 at 07:40
  • Yeah, makes perfect sense. What doesn't is that my system won't boot without the NTFS boot partition (System Reserved). – Sergei Tachenov Mar 23 '18 at 07:43
3

I can answer how it locates it on an MBR disk with Windows 7.

The BIOS IPL table contains the disk number to boot from and passes it to the vector in the entry which will be the code shared by all BAIDs. This code loads the first sector from the disk using INT 13h to 0x7c00 checks for a valid MBR and then passes control. The MBR contains a stub that moves itself away from 0x7c00 and loads the active partition's (which corresponds to volume A: on my OS) first sector i.e. the VBR to 0x7c00 and jumps to the first byte of this first sector, which is the VBR. I'd guess that it passes the disk number to the VBR to be used with the BIOS real mode services.

The VBR of the active partition then loads the IPL (nothing to do with previously mentioned IPL acronym) from sectors 1–15 of the partition into memory which it locates using HiddenSectors in the VBR BPB (HiddenSectors tells it its sector number (sector 0 of the partition) relative to the start of the disk). The VBR knows where the BPB is relative to itself so it can pass a handle to it to the IPL code (it's already been loaded into memory because it's part of sector 0, which is what the MBR loaded). It also passes the disk number I should imagine. The IPL code now knows how many sectors per cluster there are and the cluster of the MFT as the information is in the BPB, so it can look for the BCD on the partition that the BPB belongs to using primitive NTFS driver code within the IPL. So it just looks in the root directory on the MFT in the BPB given to it, which of course is the BPB of the current partition. This is why the system reserved partition needs to be active because otherwise the windows MBR won't know which partition is the system reserved partition so therefore it won't know what VBR to load. The MBR+system rsvd partition VBR+IPL+Bootmgr is the primary bootloader and winload is the secondary. If you install GRUB it will overwrite the MBR with its own stub to load its own primary bootloader and does not care which partition is active. To get back the MBR that loads the active partition's VBR, use bootrec /fixmbr. bootsect /nt60 SYS or bootrec /fixboot is what fixes the VBR and IPL on the system partition. bootsect /nt60 SYS /mbr also fixes the mbr.

The IPL locates bootmgr, (presumably first via the BCD otherwise I don't know what the point in the bootmgr entry in the BCD would be), loads the startup.com portion from the start of bootmgr into real mode address space, in my case it loads it to 0x20000 aka. 2000:0000 and passes control to it. Startup.com is a DOS COM file beginning with an E9 jump and not a 'DOS stub' (there's one of those at the start of bootmgr.exe).

The real mode program (Startup.com) switches from 16 bit real mode to 16 bit and then 32 bit protected mode with paging disabled. Startup.com then presumably reads the BCD (via its own NTFS logic, or it uses the IPL's, or the BCD gets passed to it in memory) and loads bootmgr.exe from offset 0x7BF3 in bootmgr, to 0x400000 on my system, and decompress it using lznt1. It then passes control to bootmgr!BmMain, not the 'DOS stub', which receives a PBOOT_APPLICATION_PARAMETER_BLOCK containing an offset to a BL_APPLICATION_ENTRY, which contains a BL_BCD_OPTION which is the first in a chain of BCD options for the application entry (bootmgr, winload etc.). For MBR, the BCD application entries contain the disk and partition offset in the 'device' option, and not the drive letters (because bootmgr is used by multiple windows installs and their respective winload.exes, so a drive letter means nothing). It seems winload and the OS can also be on different partitions.

Bootmgr will enable paging and switch to 64 bit long mode before loading and passing control to the selected entry, using the volume and path of winload.exe in the BCD entry to parse the MFT. At this time, it knows what partition a volume symbolic link like C: corresponds to. I believe that when you do bcdedit, you will see the drive letter from the perspective of whatever OS you are currently using -- the BCD just stores the MBR signature + offset of the partition in the entry and this is displayed or edited using a drive letter in the context of the current OS symbolic links (built from mountmgr database) for convenience.

It loads the winload.exe for the OS entry to 0x2ef000 on my system and passes control to winload!OslMain. Bootmgr.exe is its own kernel with its own debug engine and drivers. Winload is its own kernel with its own debug engine and drivers. Both of these can only handle debugging on COM port 1. Winload is responsible for loading the main kernel ntosrkrnl.exe, which has its own debug engine and drivers. Note, x64 always supports MP and there is no PAE (so not ntkrnlpamp.exe), so they are called hal.dll and ntoskrnl.exe instead of halmapic.dll and ntkrnlmp.exe, although it is essentially ntkrnlmp.exe. You can use the .pdb name that was downloaded for the binary before the !, so if it is ntkrnlmp.pdb, which it will be for Windows 7 ntoskrnl.exe, you can use ntkrnlmp! instead of nt! in windows kernel debuggers.

Lewis Kelsey
  • 582
  • 3
  • 14