Geoff Chappell - Software Analyst
Windows has long provided for its loader to detect that the previous Windows session did not start satisfactorily and to offer the Advanced Options menu automatically, especially to suggest choosing the Last Known Good Configuration. At least since Windows XP, this work is done by maintaining a boot status in a file. For Windows Vista, the first steps for booting Windows have been revised substantially and there are now two types of Boot Status Data (BSD) log file, one for the Boot Manager and one for each installation of Windows. The one for the Boot Manager is new for Windows Vista, but for both there is scarcely any documentation from Microsoft.
When booting a machine on which Windows Vista is installed, the first loader to execute is BOOTMGR, here called the Boot Manager. This binary reads the Boot Configuration Data (BCD) store to discover which Windows versions are installed and with which startup options. If there’s a choice, then it is presented as the Windows Boot Manager menu.
The Boot Manager has its own BSD log file. This is ordinarily named “bootstat.dat” in the “\boot” directory of the system partition. This is a natural location for a record of events from before it is known which Windows system will start (or even which Windows systems are available). However, the location is configurable in the BCD store:
BCD Element | Format | Value |
---|---|---|
0x11000043 | device | the device that contains the BSD file |
0x12000044 | string | a pathname to the BSD file |
0x16000045 | boolean | if true, BSD entries from previous sessions are preserved; if false, the BSD file is reset on each session |
The relevant BCD elements have no friendly names for use with BCDEDIT and must be worked with as custom types. For example, the typical configuration can be specified explicitly with the BCDEDIT commands
bcdedit /set {bootmgr} custom:0x11000043 partition=C: bcdedit /set {bootmgr} custom:0x12000044 \boot\bootstat.dat bcdedit /set {bootmgr} custom:0x16000045 off
The file is acceptable to BOOTMGR only if it is exactly 64KB. The first 0x10 bytes are a header:
Offset | Size | Value |
---|---|---|
0x00 | dword | always 2, apparently a version number |
0x04 | dword | always 0x10, apparently the size of the header |
0x08 | dword | always 0x00010000, apparently the size of the file |
0x0C | dword | size of valid data, in bytes |
The valid data includes the file header and any number of logged entries that follow.
Each entry consists of an entry header followed immediately by entry data:
Offset | Size | Value |
---|---|---|
0x00 | dword | time stamp, in seconds |
0x04 | dword | always zero, significance unknown |
0x08 | 0x10 bytes | GUID of event source; but empty if event source is BOOTMGR |
0x18 | dword | size of entry, in bytes |
0x1C | dword | severity code |
0x20 | dword | always 2, apparently a version number |
0x24 | dword | event identifier |
0x28 | varies | entry data; size depends on event identifier |
The time stamp in this header is calculated from BIOS interrupt 0x1A function 0x00, to be a number of seconds since the start of the day on which the machine started. On a PC/AT machine booted from a hard disk, the event source is necessarily BOOTMGR and so the GUID in this header is empty.
The severity code is 0x01 for events that are apparently informational and 0x03 for events that are errors. Known values of the event identifier are:
Identifier | Event | Data |
---|---|---|
0x01 | log file initialised | see below |
0x11 | boot application launched | see below |
0x12 | boot application returned | see below |
0x13 | failed to load boot application | NT status code, followed by pathname of boot application |
0x14 | BCD failure | NT status code, followed by pathname of BCD store |
0x15 | no valid boot application entries in BCD store | NT status code, followed by pathname of BCD store |
0x16 | general failure | NT status code |
For many of the events, the accompanying data is an NT status code followed immediately by a pathname. The NT status code is 4 bytes. The pathname is a null-terminated Unicode string. For general failure, there is just the 4-byte status code.
The entry data for the initialisation event has the form:
Offset | Size | Value |
---|---|---|
0x00 | 0x10 bytes | time as structure (see below) |
0x10 | dword | always 1, significance unknown |
0x14 | dword | always 0, significance unknown |
The first 0x10 bytes record the time from BIOS interrupt 0x1A functions 0x02 and 0x04:
Offset | Size | Value |
---|---|---|
0x00 | word | year |
0x02 | word | month |
0x04 | word | day |
0x06 | word | hour |
0x08 | word | minute |
0x0A | word | second |
0x0C | word | always 0, significance unknown |
0x0E | word | always 7, significance unknown |
Note that this time has the forensic value of establishing when the computer was most recently booted, but with the time in plain sight without having to start the computer and risk changing anything.
Each entry on the Windows Boot Manager menu corresponds to a boot application. The entry data for launching a boot application has the form:
Offset | Size | Value |
---|---|---|
0x00 | 0x10 bytes | GUID of boot application |
0x10 | dword | type of start |
0x14 | varies | pathname of boot application, as null-terminated Unicode string |
The type of start is 0 normally, including for a custom boot sequence, but may be 1 or 2 when launching boot applications in a recovery sequence.
When a boot application returns, whether because of success, failure or cancellation (e.g., at its Advanced Boot Options or Edit Boot Options menu), the entry data is
Offset | Size | Value |
---|---|---|
0x00 | 0x10 bytes | GUID of boot application |
0x10 | dword | always 0, significance unknown |
A separate BSD file is maintained by each Windows system that starts. Details are presently beyond the scope of this article.