An Examination of the
NTFS Volume Boot Record
Of
Microsoft® Windows 2000
(NT5.0) and Windows
XP (NT5.1)
[ It's also found in SPCMDCON.SYS and
other System files; see
Introduction below. ]
Web Presentation and Text are Copyright©2004, 2007, 2009, 2012
and 2015 by Daniel B. Sedory
NOT to be reproduced in any form without Permission of the Author !
Note: It's always best to confirm whatever you read on the Net with your
own experiments. During the long span of Windows XP, Microsoft changed the code for these Boot Record sectors once before:
http://support.microsoft.com/kb/320397
(Windows may not start
and you may receive an "NTLDR is missing" error message if Windows is not up-to-date and there are too many files in the root folder) in which you'll find out why
Microsoft had to change the Boot Record code for Windows 2000 with Service Pack 4 (SP4) and Windows XP with Service Pack 2 (SP2).
Note: Installing Windows XP SP2 or Windows 2000 SP4, will not correct this issue on existing volumes. To update the boot code on existing volumes,
you must either obtain and run the utility "bcupdate2.exe" (MD5 hash value is: "2e2ed06d9ae54c8d959a534a83284705") from Microsoft, or
manually change the boot code using an updated copy. The service pack updates will only write the new boot code for new volumes; they cannot correct
old volumes.
You can contact us
here if you have a specific question about this page.
Introduction
This page examines the NTFS Boot Record for Windows 2000 (NT5)
and Windows XP (NT5.1). Although Windows 2000 and XP can both use the MS-FAT32 File System, we'd advise anyone interested in serious
computing to run these operating systems in NTFS formatted partitions (rather than FAT32*) for a number of
reasons; which include better performance, less wasted space and greater security. One or more FAT32 partitions can also reside on the same disk if
required. For example, if a disk drive includes an OS that cannot write to an NTFS partition, then it might be able to write to a FAT32 partition which
could act as a communications buffer for sharing data among Windows™ and some other operating system.
__________________
*There's one odd quirk about maintaining FAT partitions under either Windows 2000 or XP
you should know about: If you delete a file directly (without sending it to the Recycle Bin; using SHIFT+DEL keys for
example), it can be very difficult, if even possible, to recover that file! For some odd reason, these OSs zero-out
the 'high bits' (upper 16 bits) of any FAT file's starting cluster number! This affects any file deleted
directly which is located beyond a starting cluster of 65,535.
[When NTFS was first unveiled, Linux users couldn't access data in NTFS partitions.
There was, however, a great deal of development launched within the Linux community (and commercial interests) that would eventually allow Linux users to
have both read (first) and write (later on) access to NTFS partitions. Programmers had already initiated projects that would allow Windows™ users
access to data stored in Extended file systems. An example of the latter is the free Windows™ utility explore2fs by
John Newbigin, for acquiring files directly from ext2 or ext3 partitions:
http://www.chrysocome.net/explore2fs. But if you try to copy files from Linux to
Windows, you'll most likely end up with them all having the current date/time! Then there were a number of Linux distributions which allowed users to
read files directly from NTFS partitions, but creating reliable writes (those which do not cause any issues when subsequently
accessing edited or newly created files from a Windows™ OS) was more difficult to accomplish. Kernel drivers from the linux-ntfs project
were in the forefront years ago in attempting to provide a reliable solution. (Their website was damaged around August 2007 and never regained its
former position as a reference site for open-source developers; instead the domain name now jumps directly to their commercial site, 'Tuxera'. Note:
If you find a copy of the site's announcement of a "recently released" ntfsprogs 2.0.0 (with full read/write support), that was made
in 2007. You can check some of its earlier contents using these:
WayBackMachine archive pages.) You may wish to review
their research on NTFS here: ntfsdoc.pdf. But exercise caution when making use of the information. For example, in Chapter 1, section 4.2.1, it states:
"Hidden at the end of the volume, is a copy of the boot sector (cluster 0)." If you take this to mean the copied sector resides within the volume,
that would be incorrect. As we'll point out below, the NTFS "Backup Boot Sector" isn't really part of the NTFS Volume; it's
actually stored in a sector immediately following the last sector of the Volume, which makes an NTFS Volume's partition size 1 sector larger than its Volume
size!
Did ntfsprogs 2.0.0 provide the support for writing to NTFS partitions we were hoping for? For the most part, yes! Under FC10 (Fedora Core 10), we created
and were able to write to an NTFS disk with good results; unlike previous experiences we'd had using earlier tools under various Linux distros. We used
GParted 0.4.3 (with Libparted 1.8.8) to create and format a new NTFS partition; it used the
command mkntfs -Q -v (that's mkntfs 2.0.0 with libntfs 10:0:0 from the linux-ntfs
project's ntfsprogs) to do so. Currently we are testing an Ubuntu 10.04 LTS install . . . .
But there do not appear to be any reliable (and simple) methods of writing files
under Linux to an NTFS partition (without needing to run CHKDSK on it afterwards!), nor any free programs for
writing to Linux partitions from within Windows; none that we're aware of anyway --
beware some "demo" downloads offered by commercial companies which are in fact just "read only". We are still hoping this dismal
situation will finally change.]
[Note: You can find copies of the Boot Record code which we are examining here, in
many different Windows System files; see Where's the Code? for more information on the names
and locations of these files.]
All of the NTFS Boot Area Code:
Although Microsoft's NTFS Boot Record has been described as being only a single
sector (we did so here at TheStarman's Realm for many years!), the truth is that it would never be able to boot up a Win 2000/XP OS without the next
six sectors (and more for Win 7 and later) that comprise most of an NTFS partition's Boot Code. So an NTFS partition's Boot
Record should be considered as all 16 sectors of what the MFT (Master File Table) itself calls the $Boot file. And in fact, before most users
switched to the NT file system, they already knew of a VBR (Volume 'Boot Record') that was comprised of more than a single sector in the FAT32 file system.
Thus, the Bootstrap Code which follows the 'Boot Sector' is a necessity for booting an OS from an NT file system. Microsoft states
here that the OS itself: allocates the first 16 sectors for the boot
sector and the bootstrap code1. So we can't help but wonder
if there are any programmers who've worked on a way to enhance this bootstrap code by adding more features to it.
The NTFS Boot "Record" is 16 sectors long!
|
Our examination will mostly be limited to just the code in the first sector. Once we began examining the code, we found that the boot sector actually loads all 15 of the remaining bootstrap or NTLDR Loader sectors into Memory; even though the last eight sectors are nothing but zero-bytes!
Take this link to see: The NTFS Boot Record as viewed in a Disk Editor. [ Opens in a new window, so you can refer to it later! ] Includes color-highlighting of the code, BPB, Error Messages, etc.
The NTFS Boot Record is loaded into the usual Memory location of 0000:7C00 by the MBR code (see the Windows 2000/XP MBR page for more info). Locations 7C0Bh through 7C53h are filled with the NTFS BPB (Bios Parameter Block), and the next 303 bytes (7C54h through 7D82h) contain this sector's executable code (the main program and various subroutines) which eventually load the N.T.L.D.R. (or Bootstrap) or Loader sectors into Memory (do not confuse these sectors with the ntldr program file itself which is found in the root directory of Win NT/2000/XP/2003 OS partitions).
__________________
1 The
Microsoft Windows 2000 Professional Resource Kit,
Troubleshooting,
Disk Concepts and
Troubleshooting, and the section "Disk Sectors Critical to Startup" under the heading
"NTFS Boot Sector" above Table 32.12, you'll find:
"The bootstrap code for an NTFS volume is longer than the 426 bytes, as shown in Table 32.12. When you format an NTFS volume,
the format program allocates the first 16 sectors for the boot sector and the bootstrap code." [Note: You may wish to compare the data
presented in the RK links above and the Windows XP Professional Resource Kit.]
[Note: Be aware that many of the Hex numbers in Microsoft's tables and even the text on this page (and others) do not use what we'd call normal Hex representation! They use the symbol "0x" in a nonstandard manner, saying for example, that: "0x3F000000" is "little-endian" for decimal 63. Although they do describe this usage (you have to look hard for it), it's still incorrect according to all programming languages (such as C or C++) that use "0x"; including Microsoft's own compilers! Preceding any value with "0x" should always mean a normal Hexadecimal number.
For example, if you search for "0x" on this page, the first instance is: "0x55AA" in the main section "Disk Sectors Critical to Startup" in the first paragraph under "Master Boot Record" where this value is called a "signature word or end of sector marker." Yet the very next paragraph, states a disk signature may occur at offset "0x01B8"; which is inconsistent with the first instance of "0x"! If that offset was stored anywhere on a hard disk, it appears Microsoft would have written "0xB801" instead. In "Table 32.2 Partition Table Fields" in the row labeled "0x01C6" under the "Byte Offset" column, you'll find: "0x3F000000" under the "Sample Value" column along with the explanation: "The offset from the beginning of the disk to the beginning of the volume, counting by sectors." It isn't until you finally read the notes under this table, that its author(s) state: "Numbers larger than one byte are stored in little endian format, or reverse-byte ordering. .... For example, the sample value for the Relative Sectors field in the previous table, 0x3F000000, is a little endian representation of 0x0000003F." After reading that, your very next thought should be: How are we supposed to know when it does or doesn't mean that? The symbol "0x" by itself does not indicate that. Furthermore, a portion of the note which wasn't quoted above, read: "Little endian format is a method of storing a number so that the least significant byte appears first..." and with that we certainly agree, but then their statement adds: "...in the hexadecimal number notation." In the "number notation"? This last phrase is just plain wrong! It had already been agreed that when you pre-pend "0x" (or append an "h") these symbols indicate hexadecimal rather than decimal-based numbers. Apparently, some Microsoft author(s) decided to make things a bit easier for themselves by using it differently, rather than considering how this might confuse their readers. The term "Little-endian" should only apply to the actual byte-order on a storage medium or in Memory. Rather than confuse people, these authors should drop the "0x" hex indicator, and simply write a string of bytes with or without spaces between them, then let us know that's how the bytes would appear in a disk editor.
Although this insanely inconsistent usage seems to have begun only in this publishing portion of Microsoft's world, we have now found other authors copying it; usually when discussing a Boot Record's signature Word 0xAA55 (this is the only correct way to state that using "0x"). It appears the Microsoft authors writing these pages used the symbol "0x" in whatever way suited them at the moment; such as how a particular type of CPU represents a Hex number for a given length of bytes in one sentence, but then in the very next sentence, an offset for locating some byte(s) on a disk is written as a normal Hex number. Imagine the confusion if a stock analyst wrote in a tiny footnote: 'In this report, $100.00 of shares are really worth only $000.01 (1 penny); unless I decide otherwise!' then listed his inflated data that way? Microsoft texts should not be written like Alice in Wonderland. We're supposed to be dealing with helpful facts, and Microsoft's statement about some special little-endian use of 0x only makes the material more confusing for students trying to understand it! "0x" should only pre-pend pure Hex numbers (as understood by humans); independent of their storage medium's endianness! After all, we are human beings; there's no intel chip inside my brain! But even if there were, it still wouldn't know for sure when "0x" meant a "little-endian number" and when it didn't without an indicator of some kind. We don't believe this is an unreasonable expectation. We do see how this odd usage might make things easier for Microsoft® authors to document their file systems, but it shouldn't be at the expense of producing confusion by changing the meaning of an established standard.
So, to avoid any further confusion, all our Hex Bytes, Words, Double Words, etc. in the tables below are shown as plain Hex values (without any pre-pended symbols) in the columns marked "Hex Numbers"; they will be the same Hex numbers no matter which processor you use or how the number is stored in Memory or on a hard disk, unless we need to make their byte-order clear.
NOTE: Due to the confusion such pages have caused for new students in x86 Assembly
classes, we've created a new page dealing with the correct way to refer to the Boot Record Signature as a hexadecimal Word on a PC: AA55H.html. ]
Although it actually makes sense in this case (after
examining the code for the NTFS Boot Record), to call the first sector the boot sector and
the rest of it the bootstrap code, this isn't true of all operating systems. For example, the first sector of the MSWIN4.1 Boot Record's three sectors, cannot be thought of as having a separate function from the code
in its third sector (so the phrase boot sector does not apply to the MSWIN4.1 Boot Record).
The NTFS Boot Record's Backup SectorThe Win 2000/XP OSs make a "backup" of each NTFS volume's
Boot Record which they store in the very last sector of its partition! Brian Carrier, the developer of The Sleuth Kit ( TSK) appeared to have discovered this for himself when writing about the 'backup copy' of the boot sector on page 220 of his work, File System Forensic Analysis (2005; Addison Wesley). But instead of stating as we did here, that the Volume is 1 sector less than the size of its Partition, it seems to us he mistakenly chalked this up to something he called 'the NTFS file system size' being smaller than the NTFS Volume: "My survey of Windows NT 4.0, 2000, and XP volumes had the backup copy in the last sector. I found that the total number of sectors in the file system was less than the total number of sectors in the volume, so the backup copy of the boot sector did not have to be allocated to a specific file." As usual, you must be careful when researching for technical facts; we cannot guarantee everything will always be correct at The Starman's Realm either. |
"Hex Dump" of a Sample NTFS BPB:
0 1 2 3 4 5 6 7 8 9 A B C D E F 000B 00 02 08 00 00 ..... 0010 00 00 00 00 00 F8 00 00 3F 00 FF 00 3F 00 00 00 ........?...?... 0020 00 00 00 00 80 00 80 00 AE 39 D7 00 00 00 00 00 .........9...... 0030 04 00 00 00 00 00 00 00 8D EF 00 00 00 00 00 00 ................ 0040 F6 00 00 00 01 00 00 00 FC 5D E1 A4 99 E1 A4 B4 .........]...... 0050 00 00 00 00 ..... |
The following table describes what the values in the "Hex Dump" above mean. Offsets
for each field are taken from the beginning (00h) of the Boot Record (which is located at Absolute Sector 63 for the first partition on most hard disks).
Microsoft® came up with an entirely new Extended BPB for its NTFS File System. Although it does contain some fields that
are used for the same items as previous versions, beginning with offset 28h those are completely cast aside in favor of the much larger
(LONG LONG Word) fields that are needed by NTFS!
The green colored fields contain data that may vary from one computer
to the next, whereas, the data in the red and gray fields should
never vary between NTFS Systems. The data in the yellow colored fields might possibly be different under some
circumstances, but normally should remain the same as shown below:
Offset | Length | Hex Numbers |
Decimal Equiv. or Meaning |
Description |
---|---|---|---|---|
0Bh | Word | 0200 | 512 | Sector Size (in bytes) |
Reference | " If maximum compatibility is desired, only the value 512 should be used. There is a lot of FAT code in the world that is basically "hard wired" to 512 bytes per sector and doesn't bother to check this field to make sure it is 512. [So]...values [other than 512] are not recommended." | |||
0Dh | Byte | 08 | 8 | Sectors per Cluster; so Cluster size here = 4 KiB |
Reference | " Number of sectors per allocation unit. This value must be a power of 2
that is greater than 0. Values of 1, 2, 4, 8 are quite common." |
|||
0Eh | Byte | 00 | 0 | Reserved Byte; We've never seen anything but zero here for NTFS (has anyone's BPB On Disk ever had anything else here?). |
NOTE: Under Windows 7 / 8, After loading into
Memory, 7C0Eh is set to the DRIVE NUMBER (usually 80h) by the MBR here, then used by
both the VBR (here and following) and the BOOTMGR Loader code (when reusing the VBR code as well
as: here) when reading sectors from the Boot Drive. However, under Windows XP/2000: After loading into Memory, this location (7C0Eh) is used to store how many sectors of the Boot Record are to be read into Memory; it begins with a value of 16 (decimal) and counts down to zero. (See line: 7C6C below.) |
||||
0Fh | Byte/(Word) | 00 | 0 | Reserved Byte/(Word); We've never seen anything but zero here for NTFS (has anyone's BPB On Disk ever had anything else here?). |
NOTE: Under Windows 7 / 8, After loading into
Memory, 7C0Fh - 7C10h (so WORD) are used by the VBR to first calculate and then store (see lines 7CAF and 7CB2): Bytes per Sector divided by 16; which is then used in an interesting way to read the remaining 15 sectors of the VBR Area into Memory at lines 7CBB through 7CD4 and the Subroutine at 7C0:011D. The stored value of Bytes per Sector divided by 16 (which is often 20h, since 512 / 16 = 32) is also used in a similar way by the Win 7 BOOTMGR Loader code at 7D59. |
||||
10h | Byte | 00 | N/A | Must always be zero for NTFS volumes (originally the number of FATs for a FAT partition). |
11h | 2 Bytes | 0000 | N/A | Must always be zero for NTFS volumes (originally the Max. Root Directory Entries under FAT12/16). |
13h | 2 Bytes | 0000 | N/A | Most often set to zero, but not used by NTFS (orig. used for the FAT12/16 small sectors count; must be zero for FAT32). |
15h | Byte | F8 | "Fixed Disk" | Media Descriptor ID. ( Win 2000/XP do not use it, but other code might so it's set to F8). |
16h | 2 Bytes | 0000 | N/A | Must be set to zero for NTFS volumes (originally for FAT12/16 "Sectors per FAT" value). |
18h | Word | 003F | 63 | Sectors per Track |
1Ah | Word | 00FF | 255 | Number of Heads (Sides) |
1Ch | Double Word | 0000003F | 63 | Number
of "Hidden Sectors" (Cyl=0 Head=0) |
Under Vista and 7 | 00000800 | 2048 | (Cyl=0 Head=20h Sect=21h) | |
Reference | Note: Under Windows™ Vista and Windows™
7, the number of "Hidden" or Reserved Sectors for the first partition has been increased to 2048 (0x800) rather than 63 (0x3F). Is it safe to change this value for booting a
Windows OS? & Can Win 2000/XP boot from an Extended partition? |
|||
20h | 4 Bytes | 00000000 | N/A | Most often set to zero, but not used by NTFS (originally used for the Total Number of Sectors in a FAT32 volume). |
After loading into Memory ( and carrying out the instructions in the subroutine at offsets 7C7B and following ), offset 7C20h is used to store the Total Number of Sectors on the Disk Drive we're trying to boot from; see line: 7CA5 for reference. This value is used later by the NTFS Bootstrap (or NTLDR Loader) code in Memory location D0D4. [Only true for disk drives (or image files) smaller than about 8.42 GB.] | ||||
24h | 4 Bytes | 80008000 | First
byte: 80h is the drive number ! |
An NTFS OS always fills these bytes with: "80008000" |
According to most documentation, this area is not supposed to be used by NTFS, but after examining the code in the Boot Record, it seems clear that the first byte of these four bytes is used to set the drive number! (See offsets: 7C7B and 7CAF). | ||||
28h | Long Long Word (8 Bytes) |
00000000 00D739AE |
14,105,006 | Total Sectors ( in the Volume ) Read following note! |
As we mentioned above, this value will always be 1 sector
less than the total number of sectors in the volume's partition table entry, because the NTFS "Backup Boot Sector" is not considered part of the NTFS Volume. |
||||
30h | Long Long Word (8 Bytes) |
00000000 00000004 00000000 000C0000 |
4 (Win 2000) 786,432 (for XP*) |
Starting Cluster Number for the $MFT File in this partition (starting Logical Sector is this value times the Sectors per Cluster value. E.g., 4 x 8 = 32 ) |
*All Windows XP and later Windows operating systems
place the $MFT file at LCN 0x0C0000 (786,432). See our Introduction to NTFS, Layouts, Era 2. |
||||
38h | Long Long Word (8 Bytes) |
00000000 0000EF8D |
61,325* | Starting Cluster Number for the $MFTMirr File in the center of this partition. |
*All Windows 7 and later operating systems place
the $MFTMirr file immediately after the Volume Boot Record. At LCN 0x02 (Logical Sector 16 for 4 KiB clusters). See our Introduction to NTFS, Layouts, Era 3, for more on this change. |
||||
40h | Signed (+/-) Byte |
F6 | -10
=> 1024 bytes |
Clusters
(or bytes) per File Record Segment (FRS). |
The Number of Clusters for each MFT record, which can be a negative number when the cluster size (8 sectors in this case) is larger than the MFT File Record size! The value F6 hex (which appears as 246 decimal in many utility programs) is in fact a negative 10 (-10 decimal). However, you obviously can not have a negative number of clusters! So, a negative number here is instead an indicator that the record length for any MFT File Record is: 2 to the power of the absolute value of this negative number; which of course, results in a positive number. For our example values above, that would be: 2 ^ (|-10|) = 2 ^ 10 = 1024 bytes! This number agrees perfectly with the MFT Record sizes we've seen on real disks. Microsoft® finally documented this in their Windows XP Professional Resource Kit, Table 28-17, stating: "If this number is positive (up to 0x7F), it represents Clusters per MFT record. If the number is negative (0x80 to 0xFF), the size of the File Record is 2 raised to the absolute value of this number." Prior to this, we had already reached the similar outcome as expressed in note (c) on page 49 of the Linux-NTFS Project's ntfsdoc.pdf file. |
||||
41h | 3 Bytes | 000000 | N/A | Most often set to zero, but unused by NTFS. |
44h | Signed (+/-) Byte |
01 | 1 | Clusters per Index Buffer. |
Thus, the size of each Index Buffer; used to allocate space for NTFS structures such as Directories. |
||||
45h | 3 Bytes | 000000 | N/A | Most often set to zero, but unused by NTFS. |
48h | Long Long Word (8 Bytes) |
B4A4E199 A4E15DFC |
- | NTFS Volume Serial Number. |
NOTE: When you use the DIR command and others inside of a CMD/DOS-box
under Windows 2000/XP, it will show a Volume Serial Number composed of only the last four bytes of this Long Long Word! Example: It is interesting to note how the (3rd and 4th) and (6th and
7th) bytes repeat here! |
||||
50h | Double Word |
00000000 | 0 | Not Used by NTFS |
We've never seen anything except all zero bytes in this field, but some call this field a 'Checksum'. |
_______________
* Detailed Notes Reference:
Microsoft Extensible Firmware Initiative / FAT32 File System Specification
FAT: General Overview of On-Disk Format
Version 1.03, December 6, 2000. [This PDF Document's Information gives the
title as: "FAT: General Overview of On-Disk Format" and "Microsoft" is listed as the Author with the Subject as: "FAT on disk format". The date is given
as: 12/11/2000 9:51:19AM, Created by Microsoft Word 9.0 with a file size of: 168,960 bytes.]
This data was checked against the Information found in both:
The Microsoft Windows XP Professional Resource Kit, Troubleshooting Disks and File Systems, section "Disk
Sectors Critical to Startup" heading "NTFS Boot Sector" Table 28-17 "BPB and Extended BPB Fields on NTFS
Volumes" and the Boot Record display field names from Power Quest's Partition Info program for
Windows NT/2000/XP (PartInNT.exe; 09/16/2002 2:04AM 859,136 bytes MD5 sum: 1f74ca66c42ff49f114b8c471d3ef88a). See below for an
example screenshot.
As stated above, it's been our experience that both the Windows 2000 and Windows XP Boot Record (a single sector) plus the Bootstrap Code consists of seven sectors beginning with the one we're examining in detail on this page. But the code itself shows that all 16 sectors of the NTFS Boot Record "Area" are loaded into Memory. In NTFS file system terminology, the first 16 sectors of an NTFS partition are known as the $Boot (which occupies Clusters 0 through 1 on most systems; those with 8-sector/4 KB clusters).
The Second sector always begins with the 16 Hex bytes:
05 00 4E 00 54 00 4C 00 44 00 52 00 04 00 24 00 N . T . L . D . R . $ . |
which is mostly Unicode for the 5 characters: NTLDR; the preceding "05
00" means the following Unicode string is 5 characters long. These are followed by "04 00" and Unicode for a $ sign. The next line
begins with: "49 00 33 00 30 00" (we have observed these same 10 hex bytes; which taken together are seen in ASCII as: "..$.I.3.0.", in some NTFS Metadata File Records).
The Third through Sixth sectors don't really have any outstanding features, and the Seventh sector ends
with 138 zero bytes (300 in the original code prior to Windows XP SP2). On a newly formatted NTFS volume, the $Boot is immediately followed
by the index to the $MFT (Master File Table) which usually contains a number of sectors full of FF bytes (often part of $Bitmap) before you can find something which is humanly intelligible! Most NTFS
volumes will also contain some Metadata (system files) in the middle of the partition; such as, $MFTMirr (a backup copy of the first four $MFT records) and $LogFile (which is the NTFS
journal and can be many megabytes in size). NOTE: On volumes that have had many files added and deleted, and especially those which have
come close to running out of space, the Master File Table may have been relocated.
Here's a disassembled copy of the code (; with comments) after being loaded into memory by the MBR at 0000:7C00 (An asterisk '*' in front of any Assembly Instruction listed below means that the instruction can not be disassembled correctly by MS-DEBUG):
7C00 EB52 JMP 7C54 ; Jump over BPB (Bios Parameter ; Block) to code at 0x7C54. 7C02 90 NOP ; 7C03 thru 7C0A 'NTFS ' 8-byte OEM ID or System Name. ; ; 7C0B thru 7C53 Bios Parameter Block (BPB) See above for a detailed ; explanation of each parameter field in the BPB. ; (The data here is from a different partition than the ; one we used for the Sample "Hex Dump" above!) 7C03 4E 54 46 53 20 20 20 20 00 02 04 00 00 NTFS ..... 7C10 00 00 00 00 00 F8 00 00 3F 00 FF 00 3F 00 00 00 ........?...?... 7C20 00 00 00 00 80 00 80 00 F3 90 3B 00 00 00 00 00 ..........;..... 7C30 BF F6 04 00 00 00 00 00 1E 72 07 00 00 00 00 00 .........r...... 7C40 F6 00 00 00 02 00 00 00 DB 05 66 38 2B 66 38 1A ..........f8+f8. 7C50 00 00 00 00 .... 7C54 FA CLI ; Disable maskable Interrupts. 7C55 33C0 XOR AX,AX ; Zero out both the Accumulator 7C57 8ED0 MOV SS,AX ; and Stack Segment Registers. 7C59 BC007C MOV SP,7C00 ; Set Stack Pointer to 0000:7C00 7C5C FB STI ; Enable Interrupts again. ; NOTE: The next two instructions change the (DS) Data Segment register ; from 0000 to 07C0, so all the references below to Data offsets ; (such as [0024]) are still to the same bytes in the BPB above! 7C5D B8C007 MOV AX,07C0 ;|-> This is important to know! 7C60 8ED8 MOV DS,AX ;|Set DS to 7C0 hex (with Segment= ;| 07C0, an offset such as [0024] ;| is the same as 0000:7C24), then 7C62 E81600 CALL 7C7B ; "Get Drive Parameters" and try ; to determine Total Sectors!; The following code copies the Boot Sector (VBR) and all 15 sectors of the VBR "Bootstrap" Area which follows it into Linear Memory locations 0xD000 through 0xEFFF; including 9 full zero-filled sectors plus the padding at the end of the 7th sector, for a total of 4,746 zero bytes in Memory locations 0xDD76 through 0xEFFF; thus, the code and data bytes end at Memory location 0xDD75.
7C65 B8000D MOV AX,0D00 ;| 7C68 8EC0 MOV ES,AX ;|Set Extra Segment to D00 hex. 7C6A 33DB XOR BX,BX ; Zero-out the Base Register. 7C6C C6060E0010 MOV BYTE PTR [000E],10 ; 16 decimal -> 0000:7C0E ; 7C71 E85300 CALL 7CC7 ; Read all Boot Sectors into Memory ; beginning at 0D00:0000 (see below); Exit Point of the Boot Sector code. Execution resumes in the NTLDR Bootstrap code section now located in Memory; beginning at Linear address 0xD26A.
7C74 68000D * push 0D00 ; Segment where Code Sectors were ; stored by subroutine above. 7C77 686A02 * push 026A ; (Offset in new Code Segment.) 7C7A CB RETF ; Use FAR RETURN instruction to ; jump to 0D00:026A (or 0000:D26A) ; which is where execution resumes ; with the NTLDR Loader Section!
7C7B 8A162400 MOV DL,[0024] ; -> 80h (which is the First HDD) ; See BPB chart for Offset 24h. 7C7F B408 MOV AH,08 ; Function 08h of INT 13 7C81 CD13 INT 13 ; "Get Drive Parameters" ; After executing INT 13 Function 08h: ; AH = 00h and CF is cleared (set to 0) if successful. ; +-------------------------------------------------------+ ; | CH = Low 8 bits of Maximum Cylinder Number | ; |CL (bits 7-6) = High 2 bits of " " " | ; +-------------------------------------------------------+ ; CL (bits 5-0) = Maximum Sector Number. ; DH = Maximum Head Number. ; DL = Number of drives on the system. 7C83 7305 JNB 7C8A ; Jump if successful, CF=0 (NoCarry) 7C85 B9FFFF MOV CX,FFFF ; Otherwise: Set CX = FFFFh and 7C88 8AF1 MOV DH,CL ; DH = FFh which will ; result in a count of 00FC0000h or ; 16,515,072 sectors being placed into ; [0000:7C20] and following. 7C8A 660FB6C6 * movzx eax,dh ; Move with Zero Extend DH -> EAX 7C8E 40 INC AX ; Maximum Head number + 1 = Total Heads ; (Desktop drives > 8 GB are almost always ; FE h + 1 = FF h; or 255 Heads). 7C8F 660FB6D1 * movzx edx,cl ; CL = Maximum Sector number (bits 5-0) 7C93 80E23F AND DL,3F ; To pick up only bits 5 through 0 ; (Desktop drives > 8 GB almost always ; have 3F h = 63 Sectors per Head). 7C96 F7E2 MUL AX,DX ; and multiply by the number of Heads: ; EAX now equals (Sectors x Heads) -> ; 3F h x FF h = 3EC1 h = (63 x 255) ; (so often 16,065 for Desktop drives). 7C98 86CD XCHG CL,CH ; Put the low bits of Maximum Cylinder ; Number at the end of the CX register, 7C9A C0ED06 * shr ch,06 ; and shift bits 7-6 of CL next to them ; so that CX now equals Max Cyl number! 7C9D 41 INC CX ; CX + 1 = Total Cylinders ; (Desktop drives > 8 GB are almost always ; 3FF h + 1 = 400 h; or 1024 Cylinders). 7C9E 660FB7C9 * movzx ecx,cx ; Move with Zero Extend CX -> ECX 7CA2 66F7E1 * mul eax,ecx ; so we multiply all three together: ; EAX = [Sectors * Heads] * Cylinders ; = Total Number of Sectors; but this ; should only be true for drives having ; 1024 or less cylinders! 7CA5 66A32000 * mov [0020],eax ; Store Total Number of Sectors for ; Disk in [0000:7C20] (4-byte Word). 7CA9 C3 RET ; NOTE: A 4-byte Word for Total Sectors allows for almost 2048 Binary GB! ; ( FFFFFFFFh = 4,294,967,295 sectors = 2,199,023,255,040 bytes! ) ; However, this subroutine can return a Maximum of only about 8.45 GB; if ; there's an error in determining the Sector Count; i.e., if the INT 13h ; "Get Drive Parameters" fails, this subroutine will return a count of: ; 63 * 256 * 1024 = 16,515,072 sectors (8455716864 bytes); which is not ; really possible using only CHS notation and standard BIOS functions. ; (See our Disk Terms page for a reality note about a 'bug' in MS-DOS!) ; [ 63 sectors * 255 heads * 1024 cylinders (2 + 8 = 10 bits -> 3FFh) = ; 16,450,560 sectors = 8,422,686,720 bytes (or only about 7.8 Binary GB)]. ; NOTE: When we tested the code above using an 8.0 GiB Bochs image file, ; which is > FC0000h sectors; in fact, FFFFC0 (16,777,152) sectors, the ; Bochs BIOS function returned the expected result of: 16,450,560 (or: ; 0xFB0400) sectors; actual CAPACITY must be determined by other means.
7CAA B441 MOV AH,41 ; Function 41h of INT 13: 7CAC BBAA55 MOV BX,55AA ; (with BX = 55AAh) is a check for ; the "Installation of the INT 13 ; BIOS Extensions" in Memory. 7CAF 8A162400 MOV DL,[0024] ; -> 80h (for First drive). 7CB3 CD13 INT 13 7CB5 720F JB 7CC6 ; Return 7CB7 81FB55AA CMP BX,AA55 7CBB 7509 JNZ 7CC6 ; Return 7CBD F6C101 TEST CL,01 7CC0 7404 JZ 7CC6 ; Return 7CC2 FE061400 INC BYTE PTR [0014] ; Used at location 7CEB 7CC6 C3 RET
7CC7 6660 * pushad ; Push all "Double" Registers onto the ; stack: EAX, ECX, EDX, EBX, original ; ESP, EBP, ESI, and EDI. 7CC9 1E PUSH DS 7CCA 06 PUSH ES 7CCB 66A11000 * mov eax,[0010] ; Starts as 0, but increments at 7D4F ; ( Begins as zero on DISK for NTFS! ) 7CCF 6603061C00 * add eax,[001C] ; Number of "Hidden Sectors" 7CD4 663B062000 * cmp eax,[0020] ; Apparent Total Sectors on Disk. 7CD9 0F823A00 * jb 7D17 ; Boot Sector must be within first ; 1024 Cylinders of Disk Drive! 7CDD 1E PUSH DS 7CDE 666A00 * push 00000000 7CE1 6650 * push eax 7CE3 06 PUSH ES 7CE4 53 PUSH BX 7CE5 6668100001 * push 00010010 00 7CEB 803E140000 CMP BYTE PTR [0014],00 7CF0 0F850C00 * jnz 7D00 7CF4 E8B3FF CALL 7CAA ; Check for Extended INT 13 code. 7CF7 803E140000 CMP BYTE PTR [0014],00 7CFC 0F846100 * jz 7D61 ; Extensions are not installed. ; -> "A disk read error..." etc. 7D00 B442 MOV AH,42 ; Function 42h of INT 13: ; " Extended Read " 7D02 8A162400 MOV DL,[0024] ; -> "80h" (first hard drive). 7D06 16 PUSH SS 7D07 1F POP DS 7D08 8BF4 MOV SI,SP 7D0A CD13 INT 13 7D0C 6658 * pop eax 7D0E 5B POP BX 7D0F 07 POP ES 7D10 6658 * pop eax 7D12 6658 * pop eax 7D14 1F POP DS 7D15 EB2D JMP 7D44 7D17 6633D2 * xor edx,edx 7D1A 660FB70E18 * movzx ecx,word [0018] ; [7C18] = Sectors per Track 00 7D20 66F7F1 * div ecx 7D23 FEC2 INC DL 7D25 8ACA MOV CL,DL 7D27 668BD0 * mov edx,eax 7D2A 66C1EA10 * shr edx,10 7D2E F7361A00 * div word [001A] ; [7C1A] = Number of Heads 7D32 86D6 XCHG DL,DH 7D34 8A162400 MOV DL,[0024] ; [7C24] = Hard Drive Number 7D38 8AE8 MOV CH,AL 7D3A C0E406 * shl ah,06 7D3D 0ACC OR CL,AH 7D3F B80102 MOV AX,0201 ; Function 02h of INT 13: 7D42 CD13 INT 13 ; "Read Sector into Memory" 7D44 0F821900 * jb 7D61 ; -> "A disk read error..." etc. 7D48 8CC0 MOV AX,ES ; (Prep for math next instruction:) 7D4A 052000 ADD AX,0020 ; Add another 20h to the Segment in 7D4D 8EC0 MOV ES,AX ; ES; effectively adding 200h ; (512 bytes) to Linear address. 7D4F 66FF061000 * inc dword [0010] ; Increment offset to Sector location. 7D54 FF0E0E00 DEC WORD PTR [000E] ; Decrement the Count of how ; many Sectors are left to read. 7D58 0F856FFF * jnz 7CCB 7D5C 07 POP ES 7D5D 1F POP DS 7D5E 6661 * popad 7D60 C3 RET
7D61 A0F801 MOV AL,[01F8] ; Contains 83h (Pointer value for ; all Languages to Message Area.) ; -> "A disk read error occurred" 7D64 E80900 CALL 7D70 ; DISPLAY MESSAGE 7D67 A0FB01 MOV AL,[01FB] ; Contains C9h (for English string). ; -> "Press Ctrl+Alt+Del to restart" 7D6A E80300 CALL 7D70 ; DISPLAY MESSAGE 7D6D FB STI 7D6E EBFE JMP 7D6E ; Endless Loop -> Lock-up System, ; so a reboot is necessary! 7D70 B401 MOV AH,01 ; An alternate method to add 100h to ; the AX register for the Message 7D72 8BF0 MOV SI,AX ; Offsets in AL -> Error Messages. 7D74 AC LODSB ; Load Error Message strings 1 byte ; at a time and INC SI pointer. 7D75 3C00 CMP AL,00 ; Look for Zero-byte terminator in ; the Error Message strings. 7D77 7409 JZ 7D82 ; Return (done) 7D79 B40E MOV AH,0E ; Function 0Eh of INT 10: ; "Teletype Output" (One Character) 7D7B BB0700 MOV BX,0007 ; (BH=Page Zero; BL=Normal display) 7D7E CD10 INT 10 7D80 EBF2 JMP 7D74 ; Do it all over again . . . 7D82 C3 RET
Location of Error Messages and
Message Offsets
in Memory
0 1 2 3 4 5 6 7 8 9 A B C D E F 7D83 0D 0A 41 20 64 69 73 6B 20 72 65 61 64 ..A disk read 7D90 20 65 72 72 6F 72 20 6F 63 63 75 72 72 65 64 00 error occurred. 7DA0 0D 0A 4E 54 4C 44 52 20 69 73 20 6D 69 73 73 69 ..NTLDR is missi 7DB0 6E 67 00 0D 0A 4E 54 4C 44 52 20 69 73 20 63 6F ng...NTLDR is co 7DC0 6D 70 72 65 73 73 65 64 00 0D 0A 50 72 65 73 73 mpressed...Press 7DD0 20 43 74 72 6C 2B 41 6C 74 2B 44 65 6C 20 74 6F Ctrl+Alt+Del to 7DE0 20 72 65 73 74 61 72 74 0D 0A 00 00 00 00 00 00 restart........ 7DF0 00 00 00 00 00 00 00 00 83 A0 B3 C9 00 00 55 AA ..............U. |
If you're unable to find a copy of Power Quest's Partition Info tool (see further below; since Symantec stopped distributing it!), or even if you are, we'd also recommend obtaining the latest free DEMO version of WinHex (version 18.1 at this time). Run it as Administrator in Windows 7 or later. Extract all files to a temporary folder in your Downloads area, then run the setup program (defaults to C:\Program Files (x86)\WinHex as the install directory) Open your C: Logical drive, and with the cursor at the very first byte, open "View" menu and choose "Template Manager". Then select the "Boot Sector NTFS" item and click on "Apply!" You should see a pop-up similar to this one (it will take some time getting used to where its 'Templates' and other tools are located in the menus):
See our Free Tools page for a link to PQ's Partition Info Tools (Power Quest's Partition Information viewer will list all the fields in an NTFS Bios Parameter Block). The following is a display similar to what you'll see using PQ's Partition Info program for NT (after clicking on the "Boot Record" button):
Entries 1, 2 and 23 are in the first sector of the Boot Record, but are not part of the BPB or Extended BPB. All of the red colored boxes show entries which must be zero in order for this to be an NTFS Boot Record. Note the eight-byte Serial Number in the pink box. Although documentation from Microsoft indicates that the data in the 'white' boxes (5, 8, 14 and 15) is unused by NTFS systems, we've seen only zero bytes in boxes 5, 8 and 14, and the '80 00 80 00' entry in box 15. Please refer to our detailed notes above on the BPB entries; especially for boxes 15 and 19.
First Published: June 6, 2007 (2007.06.06).
Updated: 29 JAN 2009 (29.01.2009); 1 FEB 2009 (01.02.2009); 1 MAR 2009 (01.03.2009); 8 MAR 2009 (08.03.2009); 16 AUG 2009
(16.08.2009); 6 MAR 2010 (06.03.2010); 26 AUG 2012 (26.08.2012); 2 SEP 2012 (02.09.2012); 20 FEB 2015 (20.02.2015); 7 JUL 2015 (07.07.2015); 10 JUL 2015
(10.07.2015); 12 JUL 2015 (12.07.2015); 19 JUL 2015 (19.07.2015) - Corrected some misktakes; 30 AUG 2015 (30.08.2015); 10 SEP 2015 (10.09.2015);
16 SEP 2015 (16.09.2015) - more notes related to use of BPB copies in Memory by the Windows 7 VBR and BOOTMGR Loader code; 5 MAR 2018 (05.03.2018).
Last Update: April 5, 2018 (05.04.2018).
You can write to us using this: contact page (opens in a new window).
MBR and Boot Records Index
The Starman's Realm Index Page