An Examination of the
Windows™ 7 or 8
MBR ( Master Boot Record )
[Also embedded in vdsutil.dll,
winsetup.dll and various other
System files; see Introduction ]
Web Presentation and Text are Copyright©2011 by Daniel B. Sedory
NOT to be reproduced in any form without Permission of the Author !
This page examines the Windows 7 MBR code. (We had this page near completion, but lost it during our last move in May, 2010. Now even the Windows 7 RC versions have expired! This page is still a work in progress, but you'll find interesting facts about the code and a clear layout of each assembly instruction as with all our previous MBR/VBR pages.) Whenever you install Windows 7 to a hard disk, even one with an existing MBR, its first sector may be overwritten with the Windows 7 MBR code. (Note: If necessary, it will also change the Volume Boot Record of an existing Active Windows boot OS; usually found in the first partition of a PC's first hard disk.) This code is also installed on blank hard drives when using Windows 7's Disk Management utility. NOTE: On our Windows 7 RC Install DVD, all 512 bytes of this MBR (including the zero-bytes in the partition table) were found inboot\bootsect.exe, sources\upgdriver.dll and sources\winsetup.dll; see below for more files containing this code. Like all other MBRs presented in this series, this MBR code could still be used to boot any OS on an x86 PC if it meets the conditions listed here*. |
- A View of the Windows 7 MBR in a Disk Editor
- Summary of Code and Data Sections within the MBR
- Message Offset Bytes (for Error Messages)
- An Examination of the (Assembly) Code
- Data Strings
Other Microsoft MBR pages:
An Examination of the Standard MBR created by MS-DOS FDISK
The MBR created by Windows 95B/98/98SE and ME's FDISK
The MBR created by Windows 2000/XP/2003 Installs or Disk Management Utility
The MBR created by Windows Vista Installs or Disk Management Utility
And Microsoft OS Volume Boot Records:
An Examination of the Windows 95B/98/98SE/Me OS Boot Record (MSWIN4.1)
An Examination of the Windows 2000/XP OS Boot Record (NTFS)
An Examination of the Windows Vista OS Volume Boot Record
An Examination of the Windows 7 OS Volume Boot Record
Confused? Send me an email if you have a specific question about the MBR or any Boot Records...
IMPORTANT: One of the first things that any PC user should do after setting up a new hard disk (or creating a new partition with a utility such as Partition Magic) is to make a copy of its MBR; especially if you have more than one partition on the disk! Why? If you accidentally overwrite this sector, or are infected by a Boot sector virus, you may never be able to access some or even all of your disk again! Even the most expensive HD utility might not correctly restore the Partition Table of a multi-partitioned hard disk! Some advice: Save the Partition Table data on floppy disks or write it down on paper(!); it does no good to have the data you need to access your HD on the un-accessible HD itself! There are many ways you can do this... See our MBR Tools Page. Any good Disk Editor will allow you to manually enter data you've written down under an easy to use Partition Table View, or you can use a utility program, such as "MbrFix" (for Win NT/2K, XP, 2003, PE, Vista & 7; even 64-bit versions!) to save the binary data to a file on say a thumb drive, and later on restore the MBR from that saved file. |
____________
* | NOTE: Even though we're examining code created by a Microsoft Operating System, this MBR can also be used to start the boot process for any operating system's Boot Record on an x86-CPU based (PC) computer as long as that OS is: 1) on the Primary Master hard drive, 2) set to be the only Active partition and 3) it has a boot loader in the first sector of that partition. Most Linux OS distributions can install LILO or GRUB as a Boot Record rather than in the MBR and following sectors, so even the oldest MBR by Microsoft could still be used to boot Linux; as long as its boot code was at or under the 1024 cylinder limit that is. Furthermore, the CPU itself must be an 80286 or later in order to use the Win7 MBR code, since some of the opcodes (see Code below) will only run on an 80286 or later CPU. Windows 7 can also boot multiple OSs using its console (Command Prompt) program BCDEDIT (Boot Configuration Data Editor; "Sets properties in boot database to control boot loading") and BOOTMGR files, so for systems with multiple OSs, this would be a far more practical approach than changing the Active partition in the MBR each time you want to boot up a different OS. If you intend to install a Linux OS, it would probably be best to do so after installing Win7, then use the GRUB boot manager as the first boot code to load the others from. By the way, BCDEDIT (like any program that affects system files) must first have the Command Prompt window opened in Administrator mode (you right-click on the icon or program name and choose to open it as Administrator). Running BCDEDIT without any switches will display a few facts about BOOTMGR and the Windows Boot Loader (another program first created for Vista); which is the Windows 7 OS Loader: \Windows\system32\winload.exe. |
Introduction
Like Vista, if you install Windows 7 on a hard disk with no existing partitions, the first partition will start at Absolute Sector 2048 (counting from zero; Sector 0 is where the MBR is located). This is an offset of exactly 1 Binary Megabyte (2048 * 512 = 1,048,576 bytes) into the disk. In hexadecimal, this is an offset of 100,000 hex (100000h = 1 MiB). The main reason Microsoft gave for doing this is found in their article, KB-923332; with the number of sectors given only in hex: 0x800 = 2048 and 0x3F = 63.
[Basically, since the starting offset for many disks, including the majority of Windows XP OS installs, was 63 (an odd number), they chose a starting offset that should give an even number of sectors for any large-sector drive manufacturers produce. It would cause performance issues on large-sector drives if there were a "misalignment" between the size of a physical sector and the partition(s). Western Digital and other drive manufacturers have been producing such hard disks for over a year now; calling them Advanced Format drives, with physical sectors 8 times the size of a 512-byte sector (8 * 512 = 4096 bytes). But even with new disks using 4 KiB-sizedsectors, the Win7 offset of 1 MiB still gives an equivalent offset of 256 such sectors (1048576/4096 or 2048/8). If Microsoft had picked an offset of any even number of sectors divisible by the size of a new large-sector, wouldn't that have solved any "misalignment" issue? So why not simply pick an offset of 32, 64 or even 128 KiB? Did Microsoft really want to be sure you could continue to use your Win7 OS on drives with even much larger sector sizes? Whatever their thoughts on the issue may have been, technicians working with Win7 OS disks (on either current or future models) now have a much larger sized reserved space (1,048,576 bytes vs. 32,256 bytes) they must deal with. (Note: Do not confuse this generally unused reserved space with the new Windows 7 "System Reserved" partition described below.)]
However, unlike Vista, Microsoft added a further complication for those who must deal with software designed to make image copies of Windows 7 hard disks: For each standard install of Windows 7, the install DVD defaults to creating two partitions! (NOTE: This is not true if you use an Upgrade DVD where Win 7 must be installed onto a disk with an existing Windows partition; whether you choose to keep your data or overwrite the whole partition, its files will only be installed into the OS partition.)
It's also important to note: Some 'name brand' computer manufacturers insist on adding their own special partition(s), such as Dell's type 0xDE partition, either before or after the OS partition(s); or both! (For example, a partition for restoring the entire OS partition to the state it was in when shipped from the factory, may also be included.)
Note again: For the standard Windows 7 install, to a disk that has no existing partitions, the first partition will always be set to a size of only 100 MiB and labeled "System Reserved". Users may also be confused by the fact that although this partition is set as the Active (bootable) partition, it's often hidden from them due to having no drive letter assigned to it; in which case, you need to use Disk Management or some other utility to see it. Otherwise, if it is assigned a drive letter, it will be volume E:, since the DVD drive has traditionally been assigned to D:. So here's a case where under Microsoft Windows, a simple clean OS install has the drive letter C: assigned to the second partition on the disk; not the first.
So be aware of this when examining the MBR of a Win7 OS disk. The typical (default) Windows 7 OS partition table (with its 100 MiB boot partition as the first entry) will appear similar to this:
=========================================================================== | B | FS TYPE | START | END | | | | F | (hex) | C H S | C H S | RELATIVE | TOTAL | =========================================================================== | * | 07 | 0 32 33 | 12 223 19 | 2048 | 204800 | | | 07 | 12 223 20 |1023 254 63 | 206848 | nnnnnnnn | | | 00 | 0 0 0 | 0 0 0 | 0 | 0 | | | 00 | 0 0 0 | 0 0 0 | 0 | 0 | =========================================================================== Figure 1. |
where "nnnnnnnn" simply represents the disk's actual capacity in sectors for the main OS partition. The "RELATIVE" offset of the first partition is 2048 sectors; instead of the usual 63. For technicians, it may take some time getting used to seeing both a Starting CHS triple of 0,32,33 (instead 0,1,1) and an Ending CHS triple of 12,223,19 (for disks with 255 heads) rather than the 1023,254,63 we had become so familiar with seeing on many user's computers. The whole first entry above will appear as follows in a disk editor (showing the actual hex bytes rather than decimal values in the table above): "80 20 21 00 07 DF 13 0C 00 08 00 00 00 20 03 00" (see below), where the Head and Sector values are 20h and 21h (in Cylinder 00h) for the Starting Sector. And DFh, 13h and 0Ch for the Head, Sector and Cylinder values of the Ending Sector.
NOTE: For a Laptop/Notebook PC, the BIOS may use a different pseudo-CHS geometry translation for its 'Head' value. For example, if a Windows 7 PC's BIOS decides its hard disk should have only 240 Heads (instead of 255), the values you will find in your Partition Table's first entry should be: "80 20 21 00 07 A3 13 0D 00 08 00 00 00 20 03 00" for an Ending CHS Triple of 13,163,19 which still results in a total of 204800 (32,000 hex) sectors (a capacity of 100 MiB) for the first partition.
Windows 7 has the same useful feature related to boot records and booting which first appeared under Vista: Its Disk Management utility has the ability to both shrink and expand partitions; similar to what Partition Magic could do for previous Windows versions. We may present a detailed page about this in the future, but note: All studies so far, have led us to the conclusion that no matter how much empty space you have remaining within a partition, this utility will allow you to shrink it to only about 50% (just half way)! Example: You used all the free space of a 320 GB disk drive when installing your Windows 7 OS. So, this utility will only allow you to shrink the main OS partition to about 160 GB.
This page examines the MBR code most likely to be found in a Microsoft® Windows 7 OS installation. Win7's various editions, such as Home Premium or Ultimate, all contain the same exact MBR code. When partitioning a disk without an MBR sector, this code will be written to Cylinder 0, Head 0, Sector 1 of the Hard Drive by various OS routines, such as Win7's Disk Management utility. But even in the case of a drive that already has a functioning Windows MBR, the Win7 install DVD will overwrite the existing MBR code of the boot disk as part of the process. [As with XP and Vista, Win7 itself will write data to an existing MBR sector (e.g., of a slave drive connected to the system), when necessary (compare Disk Signature comments for the Windows XP MBR).]
For our Windows 7 install, all the bytes of Win7's MBR code were also contained inside the following files (listed by location, alphabetically; with offset to first byte of the code). In each case, there will be a full 512 bytes that comprise the MBR code (the location for the NT Disk Signature and the 64-byte Partition Table are all zero-filled, the last two bytes being 55h followed by AAh):
1. C:\Windows\System32\RelPost.exe [Offset: 12CD0h]
("Windows Diagnosis and Recovery"; File version: "6.1.7600.16385 (win7_rtm.090713-1255)"; 182,784 bytes; Modification Date: "07/14/2009 1:14 AM"). There's also a second copy here: C:\Windows\winsxs\x86_microsoft-windows-reliability-postboot_31bf3856ad364e35_6.1.7600.16385_none_4d97265566a66f7e\RelPost.exe.
2. C:\Windows\System32\vdsutil.dll [Offset: 22CA8h]
("Virtual Disk Service Utility Library"; File version: "6.1.7600.16385 (win7_rtm.090713-1255)"; 151,040 bytes; Modification Date: "07/14/2009 1:16 AM"). There's also a second copy here: C:\Windows\winsxs\Backup\x86_microsoft-windows-virtualdiskservice_
31bf3856ad364e35_6.1.7600.16385_none_6ac128c35c0231aa_vdsutil.dll_f2ef43cf.
3. C:\Windows\System32\vssapi.dll [Offset: E20D0h]
("Volume Shadow Copy Requestor/Writer Services API DLL"; File version: "6.1.7600.16385 (win7_rtm.090713-1255)"; 1,123,328 bytes; Modification Date: "07/14/2009 1:16 AM").
There's also a second copy here: C:\Windows\winsxs\Backup\x86_microsoft-windows-vssapi_31bf3856ad364e35_6.1.7600.16385_none_d4bd3473e31540bf_vssapi.dll_51f72c64.
4. C:\Windows\System32\VSSVC.exe [Offset: E1BA8h]
("Volume Shadow Copy Service"; File version: "6.1.7600.16385 (win7_rtm.090713-1255)"; 1,025,536 bytes; Modification Date: "07/14/2009 1:15 AM").
There's also a second copy here: C:\Windows\winsxs\x86_microsoft-windows-vssservice_31bf3856ad364e35_6.1.7600.16385_none_5aa3249a792b0938\VSSVC.exe
5. C:\Windows\System32\oobe\winsetup.dll [Offset: 184220h]
("Windows System Setup"; File version: "6.1.7600.16385 (win7_rtm.090713-1255)"; 1,794,048 bytes; Modification Date: "07/14/2009 1:16 AM").
There's also a second copy here: C:\Windows\winsxs\x86_microsoft-windows-setup-component_31bf3856ad364e35_6.1.7600.16385_none_3202d4720e95de08\winsetup.dll.
Using the file "C:\Windows\System32\vdsutil.dll" of "151,040 bytes" with a Modification Date of "Tuesday, July 14, 2009 01:16:17 AM" as an example, the MBR in this file was found at offsets 22CA8h through 22EA7h (of which only 80 of its 512 bytes are shown here):
Figure 2. Showing the bytes "63 7B 9A"which are part of the Win7 MBR's code.
The following is a disk editor view of how the bytes of this MBR are stored on a hard disk's first sector; that's Absolute (or Physical) Sector 0, or CHS 0,0,1. (See Examination of the Code below to find out where this data ends up in Memory when it's executed.)
Absolute Sector 0 (Cylinder 0, Head 0, Sector 1)
0 1 2 3 4 5 6 7 8 9 A B C D E F
0000 33 C0 8E D0 BC 00 7C 8E C0 8E D8 BE 00 7C BF 00 3.....|......|..
0010 06 B9 00 02 FC F3 A4 50 68 1C 06 CB FB B9 04 00 .......Ph.......
0020 BD BE 07 80 7E 00 00 7C 0B 0F 85 0E 01 83 C5 10 ....~..|........
0030 E2 F1 CD 18 88 56 00 55 C6 46 11 05 C6 46 10 00 .....V.U.F...F..
0040 B4 41 BB AA 55 CD 13 5D 72 0F 81 FB 55 AA 75 09 .A..U..]r...U.u.
0050 F7 C1 01 00 74 03 FE 46 10 66 60 80 7E 10 00 74 ....t..F.f`.~..t
0060 26 66 68 00 00 00 00 66 FF 76 08 68 00 00 68 00 &fh....f.v.h..h.
0070 7C 68 01 00 68 10 00 B4 42 8A 56 00 8B F4 CD 13 |h..h...B.V.....
0080 9F 83 C4 10 9E EB 14 B8 01 02 BB 00 7C 8A 56 00 ............|.V.
0090 8A 76 01 8A 4E 02 8A 6E 03 CD 13 66 61 73 1C FE .v..N..n...fas..
00A0 4E 11 75 0C 80 7E 00 80 0F 84 8A 00 B2 80 EB 84 N.u..~..........
00B0 55 32 E4 8A 56 00 CD 13 5D EB 9E 81 3E FE 7D 55 U2..V...]...>.}U
00C0 AA 75 6E FF 76 00[E8 8D 00 75 17 FA B0 D1 E6 64 .un.v....u.....d
00D0 E8 83 00 B0 DF E6 60 E8 7C 00 B0 FF E6 64 E8 75 ......`.|....d.u
00E0 00 FB B8 00 BB CD 1A 66 23 C0 75 3B 66 81 FB 54 .......f#.u;f..T
00F0 43 50 41 75 32 81 F9 02 01 72 2C 66 68 07 BB 00 CPAu2....r,fh...
0100 00 66 68 00 02 00 00 66 68 08 00 00 00 66 53 66 .fh....fh....fSf
0110 53 66 55 66 68 00 00 00 00 66 68 00 7C 00 00 66 SfUfh....fh.|..f
0120 61 68 00 00 07 CD 1A]5A 32 F6 EA 00 7C 00 00 CD ah.....Z2...|...
0130 18 A0 B7 07 EB 08 A0 B6 07 EB 03 A0 B5 07 32 E4 ..............2.
0140 05 00 07 8B F0 AC 3C 00 74 09 BB 07 00 B4 0E CD ......<.t.......
0150 10 EB F2 F4 EB FD[2B C9 E4 64 EB 00 24 02 E0 F8 ......+..d..$...
0160 24 02 C3]49 6E 76 61 6C 69 64 20 70 61 72 74 69 $..Invalid parti
0170 74 69 6F 6E 20 74 61 62 6C 65 00 45 72 72 6F 72 tion table.Error
0180 20 6C 6F 61 64 69 6E 67 20 6F 70 65 72 61 74 69 loading operati
0190 6E 67 20 73 79 73 74 65 6D 00 4D 69 73 73 69 6E ng system.Missin
01A0 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst
01B0 65 6D 00 00 00 63 7B 9A D4 34 A0 2E 00 00 80 20 em...c{..4.....
01C0 21 00 07 DF 13 0C 00 08 00 00 00 20 03 00 00 DF !.......... ....
01D0 14 0C 07 FE FF FF 00 00 00 00 00 00 00 00 00 00 ................
01E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
01F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............U.
0 1 2 3 4 5 6 7 8 9 A B C D E F |
The first 355 bytes (000h through 162h) of this 512-byte sector are executable code and the next 80 bytes (163h through 1B2h) contain error messages. The last 66 bytes of the sector contain the 64-byte Partition Table (1BEh through 1FDh); data in the Table will depend upon the size, structure and file systems on the hard disk. [See our pages on Partition Tables, for notes on how to interpret the data in a particular disk's partition table.] The sector ends with the Word-sized signature ID of AA55h (sometimes called the MBR's Magic number). Note: On PCs using an Intel (or x86 compatible) CPU, hex Words are stored with the Low-byte first and the High-byte last.
The programmers of this MBR had to use almost every bit of space available, because all 110 bytes of the code shown between brackets in Figure 3 (offsets C6h through 126h andoffsets 156h through 162h) are either related to, or directly involved in, determining if the hardware supports TPM (Trusted Platform Module) version 1.2; which can then be used to provide extra functionality for the Microsoft Windows BitLocker™ Drive Encryption. The letters "TCPA" at offsets EFh through F2h are not coincidental; they stand for "Trusted Computing Platform Alliance" and are part of the code which tests for the existence of a TPM chip (see comments below).
The remaining 11 bytes (between the Error Messages and the Partition Table; 1B3h through 1BDh) begin with only two zero-bytes as padding; followed by the three bytes (63 7B 9A) at1B5h through 1B7h for a Win7 install with English messages (see below for all the details about this). If you stop the installation before any NT-type Operating Systems starts to boot-up, the next four bytes may remain as they were; usually zero-bytes. But once Windows has begun running, it will write a Disk Signature in the MBR. These four bytes from offsets 1B8h through 1BBh are called the Windows Disk Signature or NT Drive Serial Number. See here for details on Disk Signature use in the Windows Registry!
The three bytes at offsets 1B5h through 1B7h ("63 7B 9A") are used by Microsoft Windows for a very specific purpose; for English versions of Windows 7, you'll always see these same Hex values ("63 7B 9A") in the MBR. They're used by the MBR code to display Error Messages on your screen. But for those using Windows 7 in a different language, their MBRs may have different values in the second and third bytes depending upon how many characters are in each of the three messages. If you look in the code section below, starting at offset 0731h (instruction: "MOV AL,[07B7]"), you'll see these three bytes are used to reference the offset in Memory of the first byte of each Error Message that can be displayed on screen at boot up: 0763h, 077Bh and 079Ah. Since the code portion above the messages will always be the same, the first offset (0763h) will never change no matter what languages (and string lengths) are used.
Now that you know what the bytes at offsets 1B5h through 1B7h are used for, you could change these error messages to display whatever you wish (as long as they all fit into the space between offsets 163h and 1B4h) by counting their character lengths and using a disk editor on the MBR sector to make the appropriate changes.
After executing the POST (Power-On Self Test), the BIOS loads this sector into memory at 0000:7C00 (as it does any MBR) then transfers control to this code.
But this code must first copy itself into another area of Memory. This is necessary because the code must also load the Boot Sector of the Active Partition into the same area of Memory that it occupies just after being loaded! Unlike the Windows 2000/XP MBR, this code copies all 512 of its bytes to the new location, starting at: 0000:0600. Only the first three instructions are the same as the Windows 2000/XP MBR, so keep your eyes sharp if you're comparing the two.
An Examination of the Assembly Code
You can learn a great deal about the instructions used here by obtaining the x86 Opcode Windows Help file and Ralf Brown's Interrupt List from our Intro to Assembly page.
Here's a Listing of the disassembled code (; with comments) after first being loaded into Memory at 0000:7C00 by the BIOS (all Memory locations listed below are in Segment 0000:). If you see an asterisk (*) next to an instruction, it means that MS-DEBUG can not disassemble that code.
Note: If you compare this code to that of the Windows Vista MBR, you'll find there's only a slight variation due to changing two jump instructions from 32-bit to 16-bit at Memory locations 06A2 and 06C9; allowing for the insertion of a CLI instruction immediately after it, and an STI instruction at 06E1. Due to these changes various offset bytes also needed to be adjusted. (For those interested, the first byte difference from the Vista MBR code occurs at Memory location 062B, where the location to jump to changes from 073D to 073B. The next adjustment doesn't occur until 069E; just a few bytes before all of the same code bytes become shifted by 1 to 4 bytes when compared to Vista's MBR.)
7C00 33C0 XOR AX,AX ; Zero out the Accumulator and 7C02 8ED0 MOV SS,AX ; Stack Segment register. 7C04 BC007C MOV SP,7C00 ; Set Stack Pointer to 0000:7C00 7C07 8EC0 MOV ES,AX ; Since AX=0, zero-out Extra Segment, 7C09 8ED8 MOV DS,AX ; and zero-out Data Segment. 7C0B BE007C MOV SI,7C00 ; Source Index: Copy from here... 7C0E BF0006 MOV DI,0600 ; Destination Index: Copy to here: ; Code will begin at: 0000:0600 7C11 B90002 MOV CX,0200 ; Set up Counter (CX) to copy all ; (200h) 512 bytes of the code. 7C14 FC CLD ; Clear Direction Flag 7C15 F3 REP ;/ REPeat the following MOVSB ;| instruction for 'CX' times; 7C16 A4 MOVSB ;\ copying one byte at a time. ; Note: Some debuggers disassemble the last two instructions above as: ; REP MOVSB BYTE PTR ES:[DI], BYTE PTR DS:[SI] ; making clear the source [SI] and destination [DI] of the bytes being copied. ; CX will count down from 200h to zero while DI increases in step up to 800h. 7C17 50 PUSH AX ; Set up Segment(AX) and Offset(DI) 7C18 681C06 * PUSH 061C ; for jump to 0000:061C. 7C1B CB RETF ; Use RETF to do Jump into where we ; copied all the code: 0000:061C. ; Since the preceding routine not only copies the MBR code to a new location, but ; also jumps there to continue its execution, the following addresses have been ; changed to reflect the code's actual location in memory at the time of execution. ; This next section of code tries to find an ACTIVE (i.e., bootable) entry in the ; Partition Table. The first byte of an entry indicates if it's bootable (an 80h) ; or not(a 00h); any other values in these locations means the Table is invalid! ; If none of the four entries in the Table is active, the 'Invalid' error message ; is displayed. [Microsoft MBR code prior to 2000/XP used the SI register here ; rather than BP; which can be seen at offsets 0620, 0623 and 062D below.] 061C FB STI ; Enable Interrupts 061D B90400 MOV CX,0004 ; Maximum of four entries. 0620 BDBE07 MOV BP,07BE ; Location of first entry ; in the partition table ; (see Sample Table here). 0623 807E0000 CMP BYTE PTR [BP+00],00 ; CoMPare first byte of entry at ; SS:[BP+00] to Zero. Anything from ; 80h to FFh will be less than, which means: 0627 7C0B JL 0634 ; We found a possible boot entry, so we ; check on it in more detail at 0634h 0629 0F850E01 * JNZ 073B ; But if it's not zero (and greater than), ; then we have an Error! (Because we must ; have found a 01h through 79h byte.) So: ; -> "Invalid partition table" ; Otherwise, we found a zero; so we keep on 062D 83C510 ADD BP,+10 ; searching: Check the next entry ... ; (there are 10h = 16 bytes per entry) 0630 E2F1 LOOP 0623 ; Go back & check next Entry ... ; unless CL = 0 (we tried all four). 0632 CD18 INT 18 ; Checked all 4; NONE of them were bootable, ; so start ROM-BASIC (only available on some ; IBM machines!) Many BIOS simply display: ; "PRESS A KEY TO REBOOT" ; when an Interrupt 18h is executed.
Just like most of the MBR code we've studied here, if you were to load a copy of the Win7 MBR with an empty partition table (or one that has no Active Boot Flag for any of its entries) as a *.bin file into MS-DEBUG (e.g., debug mbr.bin), move all the code to offset 0x0600 (-m 100 2ff 600), set the IP to 0x061C (-rip then 61c) and run it (-g; Note: Although MS-DEBUG cannot step through the code at 0x0629 since it doesn't understand instructions beyond the 8086 through 8088 processors, when you enter 'g' it will simply pass all the code it encounters to Win XP/Vista/Win7's NTVDM program; under which you are actually running DEBUG, without trying to disassemble it), you would then see the following error message on your screen:
Note: Although this was possible under Windows 7 RC, the retail Windows 7 OS no longer includes
the MS-DEBUG program! We recommend installing VMWare Player and creating your own
Windows XP (or Windows 98 or even MS-DOS), virtual computer to run MS-DEBUG inside of.
Because NTVDM was never programmed to handle an 18h Interrupt any further than displaying this message. If you Ignore it, the NTVDM program might warn you one more time about accessing the hard disk, but it will eventually freeze or go off into oblivion if you Ignore it again; and you'll have to use Task Manager to close the DOS Prompt window gracefully.
0634 885600 MOV [BP+00],DL ; DL=0 first time we arrive here. ; So if we had 80h it becomes 0h. 0637 55 PUSH BP ; Save Base Pointer on Stack. 0638 C6461105 MOV BYTE PTR [BP+11],05 ; 063C C6461000 MOV BYTE PTR [BP+10],00 ; Used as a flag and/or counter ; for the INT13 Extensions being ; installed; see 0656 and 065B below. 0640 B441 MOV AH,41 ;/ 0642 BBAA55 MOV BX,55AA ;| 0645 CD13 INT 13 ;| INT13, Function 41h (with BX=55AAh): ;| Check for Int 13 Extensions in BIOS. ;| If CF flag cleared and [BX] changes to AA55h, they are installed; Major ;| version is in AH: 01h=1.x; 20h=2.0/EDD-1.0; 21h=2.1/EDD-1.1; 30h=EDD-3.0. ;| CX = API subset support bitmap. If bit 0 is set (CX = 1, 3, 5, etc.; 'odd'), ;| then extended disk access functions (AH=42h-44h,47h,48h) are supported. ;\ Only if no extended support is available, will it fail TEST at 0650. 0647 5D POP BP ; Get back original Base Pointer. 0648 720F JB 0659 ; Below? If so, CF=1 (not cleared) ; so no INT 13 Ext. & do jump! 064A 81FB55AA CMP BX,AA55 ; Did contents of BX change? If 064E 7509 JNZ 0659 ; not, jump to offset 0659. 0650 F7C10100 TEST CX,0001 ; Final test for INT 13 Extensions! ; If bit 0 not set, this will fail, 0654 7403 JZ 0659 ; then we jump over next line... 0656 FE4610 INC BYTE PTR [BP+10] ; or increase [BP+10h] by one. 0659 6660 * PUSHA ; Save all 16-bit Registers on ; the Stack. 065B 807E1000 CMP BYTE PTR [BP+10],00 ;/ CoMPare [BP+10h] to zero; 065F 7426 JZ 0687 ;\ if 0, can't use Extensions.
The following code is missing some comments, but all the instructions are here for you to study.
; The following code uses INT 13, Function 42h (Extended Read) 0661 666800000000 * PUSH 00000000 0667 66FF7608 * PUSH DWORD PTR [BP+08] 066B 680000 * PUSH 0000 066E 68007C * PUSH 7C00 0671 680100 * PUSH 0001 0674 681000 * PUSH 0010 0677 B442 MOV AH,42 0679 8A5600 MOV DL,[BP+00] 067C 8BF4 MOV SI,SP 067E CD13 INT 13 0680 9F LAHF ; Load Status flags into AH 0681 83C410 ADD SP,+10 0684 9E SAHF ; Save AH into flags register 0685 EB14 JMP 069B ; The MBR uses the standard INT 13 "Read Sectors" function here, because ; no INT 13 Extended functions were found in the BIOS code above (065F): 0687 B80102 MOV AX,0201 ; Function 02h, read only 1 sector. 068A BB007C MOV BX,7C00 ; Buffer for read starts at 7C00. 068D 8A5600 MOV DL,[BP+00] ; DL = Disk Drive 0690 8A7601 MOV DH,[BP+01] ; DH = Head number (never use FFh). 0693 8A4E02 MOV CL,[BP+02] ; Bits 0-5 of CL (max. value 3Fh) ; make up the Sector number. 0696 8A6E03 MOV CH,[BP+03] ; Bits 6-7 of CL become highest two ; bits (8-9) with bits 0-7 of CH to ; make Cylinder number (max. 3FFh). 0699 CD13 INT 13 ; INT13, Function 02h: READ SECTORS ; into Memory at ES:BX (0000:7C00). ; Whether Extensions are installed or not, both routines end up here: 069B 6661 * POPA ; Restore all 16-bit Registers from ; the Stack which we saved at 0659. 069D 731C JNB 06BB 069F FE4E11 DEC BYTE PTR [BP+11] ; Begins with 05h from 0638. 06A2 750C JNZ 06B0 ; If 0, tried all 4 entries! 06A4 807E0080 CMP BYTE PTR [BP+00],80 06A8 0F848A00 * JZ 0736 ; -> "Error loading ; operating system" 06AC B280 MOV DL,80 06AE EB82 JMP 0634 06B0 55 PUSH BP 06B1 32E4 XOR AH,AH 06B3 8A5600 MOV DL,[BP+00] 06B6 CD13 INT 13 06B8 5D POP BP 06B9 EB9E JMP 0659 06BB 813EFE7D55AA CMP WORD PTR [7DFE],AA55 06C1 756E JNZ 0731 ; If we don't see it, Error! ; -> "Missing operating system" 06C3 FF7600 PUSH WORD PTR [BP+00] ; Popped into DL again at 0727 ; (contains 80h if 1st drive). ; ===================================================================== ; All of the code from 06C6 through 0726 is related to discovering if ; TPM version 1.2 interface support is operational on the system, since ; it could be used by BitLocker for validating the integrity of a PC's ; early startup components before allowing the OS to boot. The spec for ; the TPM code below states "There MUST be no requirement placed on the ; A20 state on entry to these INT 1Ah functions." (p.83) We assume here ; Microsoft understood this to mean access to memory over 1 MiB must be ; made available before entering any of the TPM's INT 1Ah functions. ; The following code is actually a method for gaining access to Memory ; locations above 1 MiB (also known as enabling the A20 address line). ; ; Each address line allows the CPU to access ( 2 ^ n ) bytes of memory: ; A0 through A15 can give access to 2^16 = 64 KiB. The A20 line allows ; a jump from 2^20 (1 MiB) to 2^21 = 2 MiB in accessible memory. But ; our computers are constructed such that simply enabling the A20 line ; also allows access to any available memory over 1 MiB if both the CPU ; and code can handle it (once outside of "Real Mode"). Note: With only ; a few minor differences, this code at 06C6-06E1 and the Subroutine at ; 0756 ff. are the same as rather old sources we found on the Net. 06C6 E88D00 CALL 075606C9 7517 JNZ 06E2 06CB FA CLI ; Clear IF, so CPU ignores maskable interrupts. 06CC B0D1 MOV AL,D1 06CE E664 OUT 64,AL 06D0 E88300 CALL 0756 06D3 B0DF MOV AL,DF 06D5 E660 OUT 60,AL 06D7 E87C00 CALL 0756 06DA B0FF MOV AL,FF 06DC E664 OUT 64,AL 06DE E87500 CALL 075606E1 FB STI ; Set IF, so CPU can respond to maskable interrupts ; again, after the next instruction is executed. ; Comments below checked with the document, "TCG PC Client Specific ; Implementation Specification For Conventional BIOS" (Version 1.20 ; FINAL/Revision 1.00/July 13, 2005/For TPM Family 1.2; Level 2), § ; 12.5, pages 85 ff. TCG and "TCG BIOS DOS Test Tool" (MSDN). 06E2 B800BB MOV AX,BB00 ; With AH = BBh and AL = 00h 06E5 CD1A INT 1A ; Int 1A -> TCG_StatusCheck 06E7 6623C0 * AND EAX,EAX ;/ If EAX does not equal zero, 06EA 753B JNZ 0727 ;\ then no BIOS support for TCG. 06EC 6681FB544350+ * CMP EBX,41504354 ; EBX must also return .. ; the numerical equivalent ; of the ASCII character string "TCPA" ("54 43 50 41") as a further ; check. (Note: Since hex numbers are stored in reverse order on PC ; media or in Memory, a TPM BIOS would put 41504354h in EBX.) 06F3 7532 JNZ 0727 ; If not, exit TCG code. 06F5 81F90201 CMP CX,0102 ; Version 1.2 or higher ? 06F9 722C JB 0727 ; If not, exit TCG code. ; If TPM 1.2 found, perform a: "TCG_CompactHashLogExtendEvent". 06FB 666807BB0000 * PUSH 0000BB07 ; Setup for INT 1Ah AH = BB, ; AL = 07h command (p.94 f). 0701 666800020000 * PUSH 00000200 ; 0707 666808000000 * PUSH 00000008 ; 070D 6653 * PUSH EBX ; 070F 6653 * PUSH EBX ; 0711 6655 * PUSH EBP ; 0713 666800000000 * PUSH 00000000 ; 0719 6668007C0000 * PUSH 00007C00 ; 071F 6661 * POPAD ; 0721 680000 * PUSH 0000 ; 0724 07 POP ES ; 0725 CD1A INT 1A ; On return, "(EAX) = Return Code as defined in Section 12.3" and
; "(EDX) = Event number of the event that was logged". ; ===================================================================== 0727 5A POP DX ; From [BP+00] at 06C3; often 80h. 0728 32F6 XOR DH,DH ; (Only DL matters) 072A EA007C0000 JMP 0000:7C00 ; Jump to Volume Boot Record code ; loaded into Memory by this MBR. 072F CD18 INT 18 ; This instruction is prob. here to ; meet a specification of TPM v 1.2 ? ; Note: When the last character of any Error Message has been displayed, the ; instructions at offsets 0748, 0753 and 0754 lock computer's execution into ; a never ending loop! You must reboot the machine. INT 10, Function 0Eh ; (Teletype Output) is used to display each character of these error messages. 0731 A0B707 MOV AL,[07B7] ; [7B7] = 9A + 700 -> 79A h 0734 EB08 JMP 073E ; Displays: "Missing operating system" 0736 A0B607 MOV AL,[07B6] ; [7B6] = 7B + 700 -> 77B h 0739 EB03 JMP 073E ; Displays: "Error loading operating ; system" 073B A0B507 MOV AL,[07B5] ; [7B5] = 63 + 700 -> 763 h ; which will display: "Invalid ; partition table" 073E 32E4 XOR AH,AH ; Zero-out AH. 0740 050007 ADD AX,0700 ; Add 700h to offsets from above. 0743 8BF0 MOV SI,AX ; Offset of message -> Source Index Reg. 0745 AC LODSB ; Load character into AL from [SI]. 0746 3C00 CMP AL,00 ;/ Have we reached end of message ;| marker?(00) If so, then 0748 7409 JZ 0753 ; 074A BB0700 MOV BX,0007 ; Display page 0, normal white on black ; characters. 074D B40E MOV AH,0E ;/ Teletype Output.. displays only 074F CD10 INT 10 ;\ one character at a time. 0751 EBF2 JMP 0745 ; Go back for another character... 0753 F4 HLT 0754 EBFD JMP 0753 ; And just in case an NMI occurs, ; we jump right back to HLT again! ; ----------------------------------------------------------------------- ; SUBROUTINE - Part of A20 Line Enablement code (see 06C6 ff. above); ; This routine checks/waits for access to KB controller. ; ----------------------------------------------------------------------- 0756 2BC9 SUB CX,CX ; Sets CX = 0. 0758 E464 IN AL,64 ; Check port 64h. 075A EB00 JMP 075C ; Seems odd, but this is how it's done. 075C 2402 AND AL,02 ; Test for only 'Bit 1' *not* set. 075E E0F8 LOOPNE 0758 ; Continue to check (loop) until ; CX = 0 (and ZF=1); it's ready. 0760 2402 AND AL,02 0762 C3 RET
Location of Error Messages and
Message Offsets in Memory
3 4 5 6 7 8 9 A B C D E F 0763 49 6E 76 61 6C 69 64 20 70 61 72 74 69 Invalid parti 0770 74 69 6F 6E 20 74 61 62 6C 65 00 45 72 72 6F 72 tion Table.Error 0780 20 6C 6F 61 64 69 6E 67 20 6F 70 65 72 61 74 69 loading operati 0790 6E 67 20 73 79 73 74 65 6D 00 4D 69 73 73 69 6E ng system.Missin 07A0 67 20 6F 70 65 72 61 74 69 6E 67 20 73 79 73 74 g operating syst 07B0 65 6D 00 00 00 63 7B 9A em...c{. 0 1 2 3 4 5 6 7 8 9 A B C D E F
Location of Sample Disk Signature
and Partition Table in Memory
8 9 A B C D E F 07B8 D4 34 A0 2E 00 00 80 20 .4..... 07C0 21 00 07 DF 13 0C 00 08 00 00 00 20 03 00 00 DF !.......... .... 07D0 14 0C 07 FE FF FF 00 00 00 00 00 00 00 00 00 00 ................ 07E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 07F0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 55 AA ..............U. 0 1 2 3 4 5 6 7 8 9 A B C D E F
This is how it would be seen in a disk editor that can interpret Partition Table data:
Partition Active Starting Loc Ending Loc Relative Number of
Type Boot Cyl Head Sec Cyl Head Sec sectors sectors
------------- ------ ------------ ------------- -------- ---------
NTFS Yes 0 32 33 12 223 19 2048 204800 NTFS No 12 223 20 1023 254 63 206848 nnnnnnnnn
[Note: Cylinders and heads start counting at ZERO; sectors at 1. So, a CHS of
0,32,33 gives us 32 'full' heads of 63 sectors each, or 32 x 63 = 2016; the
33rd head including only up to sector 33, for a total of: 2016 + 33 = 2049, or
Absolute Sector 2048 as the sector where Win7 partitions begin on the disk;
with 2048 sectors preceding.
12,223,20 gives us 12 'full' cylinders of 255 x 63 = 16065 sectors each, or
12 x 16065 = 192780 sectors. The 13th cylinder being only 223 'full' heads or
14049; the 224th head including only up to sector 20, for a total of:
192780 + 14049 + 20 = 206849, or Absolute Sector 206848 as the sector where
this disk's second primary partition begins.]
Three views of PT Calc showing: 1) The CHS values for a Vista or Windows 7 OS install's first partition (at Absolute Sector 2048) for either a typical desktop or notebook disk, and 2) How disks which are assigned a different number of Heads in their BIOS (255 and 240 are shown) can have different CHS values for exactly the same sector (206848).
Note:
The sector must have a 'signature' of 0xAA55. It's located at the very end of the partition table (remember that low-bytes appear first and high-bytes last). The BIOS checks for the signature and if it's not there, you'll get an error message like "Drive not ready."
First Published: March 12, 2011 (12.03.11).
Updated: March 22, 2011 (22.03.2011), May 8, 2011 (08.05.2011), May 14, 2011 (14.05.2011), March 28, 2012 (28.03.2012).
Last Update: April 18, 2012. (18.04.2012)
You can write to me using this: online reply form. (It opens in a new window.)
The Starman's FREE TOOLS Page
MBR and Boot Records Index
The Starman's Realm Index Page