NOTE: Although the code used in this MBR is no mystery to anyone who has a search engine and a bit of Assembly knowledge (since it is all Open-source code), I decided that many would still like to see a listing and comments on the Assembly instructions from GRUB's MBR (or "stage1" as it's called) in an effort to help computer users understand what happens when their Master Boot Record is replaced by the boot code from GRUB. Also note that this code can be used as either MBR code in a hard drive's MBR sector, or as a Linux install's Volume Boot Sector! GRUB as a whole (all of its software working together) is actually a Boot Manager (in my opinion anyway; some technical reasons may exist for not labeling it as such, but it does so much more than just a common bootloader, I have to wonder if others ever take any time to study what can be done with it). It's capable of launching a variety of OS-types from its menu display; to which some distros such as Red Hat® have added their own splash screens. SuSE® (another Linux distribution company) has gone a step further, not only adding a splash screen patch, but some executable code which adds an animated progress-bar to their splash screen display.
GRUB often replaces the original MBR code when a Windows™ user tries out Linux for the first time. Long ago (in relation to how long computers have been around) GRUB was only the default loader for Red Hat and a few lesser known distros. But soon many others, such as SuSE 9.2 (SuSe has also used GRUB for some time now) and then the Ubuntu (since 2004; Debian-based) distro, also defaulted to using GRUB*. This page will show you where "stage1" gets loaded into Memory and how program execution is passed on to the rest of GRUB's executable code located elsewhere on the disk. You can also find documented sources by the authors of GRUB at most Linux archive sites. A good starting point would be: GRUB Legacy. Many Linux users prefer reading the GRUB Manual in PDF or HTML form rather than GRUB's 'info' pages; you can get all the documentation here (the single page HTML Manual is both portable and searchable across many platforms). In the source code, the source file for GRUB's Master Boot Record (or VBR Boot Sector) code is called: stage1.S. You may also find the file stage1.h quite helpful; it contains definitions of various bytes used in GRUB's BPB and data areas (see below). NOTE: The style or format of the assembly code instructions in these source files is often referred to as "AT&T" (rather than "Intel"). The "Intel" format is what most assemblers, such as Microsoft's MASM, use; whereas, the GNU Assembler uses the "AT&T" format.
* NOTE: Some Linux distros use a version of GRUB which has never been "patched" for splash screens; so you won't see any color image logos behind its menus or help screens.
And perhaps of equal importance to some: A number of distros seem to have no way of installing GRUB into the MBR without adding some of its "stage2" code immediately after it (overwriting many sectors of the first track). Neither the Red Hat (since at least 8.0; when using their "Anaconda" GUI install) nor SuSE installation programs (probably long before 9.1; which is one version we tested) will overwrite any sectors in the first track by default, except the MBR sector. (This is probably true for other Linux distro installation programs as well.) What really bothers us about many particular install programs though, is their lack of clarity (or are they simply propagating the same error over and over again?) by the manner in which the choices (for those that even give you a choice!) are presented to their users. For example, many distros that use a text-only install, and even for some distros with GUI install programs, when text-only is selected (or the user is forced into it, because there's not enough memory to run the GUI install), at some point in the process, they ask: "Where do you want to install the boot loader?" and the only options are often: 1) "Master Boot Record (MBR)" or 2) "First sector of boot partition." Does it make sense that choosing option #1) means about 8 KiB (16 sectors) of 'stage2' code will also be written to the first track? Yet choosing option #2) may or may not write any of GRUB's code to the MBR sector; so, if like me, you want to be sure a new install cannot overwrite any data you may have saved in the first track, you're stuck with manually having to install GRUB to the MBR sector after performing the installation!
Although this may be the default behavior of GRUB, a distribution's installation programmer(s) should be able to (and a number of major Linux distros have done so) offer you a choice that makes sense! So, be aware that just because a distro uses GRUB, they certainly do not all follow the same installation methods! To most people, this won't make any difference at all, but we consider it disturbing that some popular new Linux distros do not point out what their install programs will really do (i.e., write at least 16 sectors to the first track) rather than simply stating GRUB will be written to the MBR sector. As with all OS installs, it's up to the user to protect his existing data. [ So: Back-up the whole first track, if you are trying out any new Linux distros and you have some other boot manager or other kind of data saved there. ]
Note: There are many different versions of GRUB being used in the real world. The one we're examining here contains the stage1 code for both versions 0.92 and 0.93 (12/08/2002); still found in most Linux installations. Also versions 0.94 (some: 1/25/2004 others: 5/13/2004; for example, as used in SuSE Linux 9.1 and seen in the Khexedit pics below) and 0.95 (6/13/2004); you'll also find 0.97 and preliminary work on GRUB2 at this FTP site as well. A few more lines were added for 0.97 (5/7/2005) as discussed below.
The MBR code for all of these versions is basically the same as before (only one new instruction was added for 0.95 and a few more for 0.97), but the offsets for the "GRUB " and error message strings have all changed due to that! One should also note that Linux companies such as SuSE®, RedHat®, etc. may make changes of their own (SuSE® made a slight change in its 0.94 GRUB MBR code; see code comments below and OpenSuse may have others). The most recent GNU GRUB version, 0.97, is also discussed below; where only 9 bytes have been added in the same area.
Like the Volume boot records of DOS/Windows, the first three bytes of GRUB's MBR code are called the Jump Instruction, even though only the first two bytes form the actual JMP (jump) to the rest of the executable code; the third byte (90h) is just a NOP instruction ('No OPeration'; although it does nothing, it's often used to align other bytes and allow for changes in the code that won't alter the size of the file). So the execution jumps over the 59 bytes highlighted in pink which can be used as a BIOS Parameter Block (the data is explained here), as well as the next 12 bytes highlighted in yellow which contain data about GRUB (see below), to continue at offset 4Ah.
NOTE: When GRUB is used as an MBR sector, which is how we're examining it here, none of the bytes stored on the media in the BPB area are actually used by the code; so we've filled it with zero bytes.
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 EB 48 90 00 00 00 00 00 00 00 00 00 00 00 00 00 .H.............. 0010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 0030 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 02 ................ 0040 80 00 00 80 DF 0A 93 01 00 08 FA EA 50 7C 00 00 ............P|.. 0050 31 C0 8E D8 8E D0 BC 00 20 FB A0 40 7C 3C FF 74 1....... ..@|<.t 0060 02 88 C2 52 BE 76 7D E8 34 01 F6 C2 80 74 54 B4 ...R.v}.4....tT. 0070 41 BB AA 55 CD 13 5A 52 72 49 81 FB 55 AA 75 43 A..U..ZRrI..U.uC 0080 A0 41 7C 84 C0 75 05 83 E1 01 74 37 66 8B 4C 10 .A|..u....t7f.L. 0090 BE 05 7C C6 44 FF 01 66 8B 1E 44 7C C7 04 10 00 ..|.D..f..D|.... 00A0 C7 44 02 01 00 66 89 5C 08 C7 44 06 00 70 66 31 .D...f.\..D..pf1 00B0 C0 89 44 04 66 89 44 0C B4 42 CD 13 72 05 BB 00 ..D.f.D..B..r... 00C0 70 EB 7D B4 08 CD 13 73 0A F6 C2 80 0F 84 F3 00 p.}....s........ 00D0 E9 8D 00 BE 05 7C C6 44 FF 00 66 31 C0 88 F0 40 .....|.D..f1...@ 00E0 66 89 44 04 31 D2 88 CA C1 E2 02 88 E8 88 F4 40 f.D.1..........@ 00F0 89 44 08 31 C0 88 D0 C0 E8 02 66 89 04 66 A1 44 .D.1......f..f.D 0100 7C 66 31 D2 66 F7 34 88 54 0A 66 31 D2 66 F7 74 |f1.f.4.T.f1.f.t 0110 04 88 54 0B 89 44 0C 3B 44 08 7D 3C 8A 54 0D C0 ..T..D.;D.}<.T.. 0120 E2 06 8A 4C 0A FE C1 08 D1 8A 6C 0C 5A 8A 74 0B ...L......l.Z.t. 0130 BB 00 70 8E C3 31 DB B8 01 02 CD 13 72 2A 8C C3 ..p..1......r*.. 0140 8E 06 48 7C 60 1E B9 00 01 8E DB 31 F6 31 FF FC ..H|`......1.1.. 0150 F3 A5 1F 61 FF 26 42 7C BE 7C 7D E8 40 00 EB 0E ...a.&B|.|}.@... 0160 BE 81 7D E8 38 00 EB 06 BE 8B 7D E8 30 00 BE 90 ..}.8.....}.0... 0170 7D E8 2A 00 EB FE 47 52 55 42 20 00 47 65 6F 6D }.*...GRUB .Geom 0180 00 48 61 72 64 20 44 69 73 6B 00 52 65 61 64 00 .Hard Disk.Read. 0190 20 45 72 72 6F 72 00 BB 01 00 B4 0E CD 10 AC 3C Error.........< 01A0 00 75 F4 C3 00 00 00 00 00 00 00 00 00 00 00 00 .u.............. 01B0 00 00 00 00 00 00 00 00 A8 E1 A8 E1 00 00 80 01 ................ 01C0 01 00 07 FE FF 6D 3F 00 00 00 AF 39 D7 00 00 00 .....m?....9.... 01D0 C1 6E 0C FE FF FF EE 39 D7 00 BD 86 BB 00 00 FE .n.....9........ 01E0 FF FF 83 FE FF FF AB C0 92 01 CD 2F 03 00 00 FE .........../.... 01F0 FF FF 0F FE FF FF 78 F0 95 01 83 AF CC 00 55 AA ......x.......U. 0 1 2 3 4 5 6 7 8 9 A B C D E F
At offset 176h
(for 0.92/0.93) we find the Zero-terminated string "GRUB
". Under versions 0.94/0.95, it will begin at offset 179h, but in the SuSE 9.1 MBR (using ver. 0.94) an extra
instruction was added which shifted the "GRUB " string offset to 17Bh.
[Note: If you have an earlier version of GRUB (before 0.92), you may find this string in yet another location.]
The "GRUB " string is followed by a group of very brief Error Messages; each phrase in the Error Message section is zero-terminated as well. The bolded code inserted after the Error Message section is a subroutine used to display both the word "GRUB " and any Error Messages on the screen; it's called by the main body of code as needed.
Although GRUB is a Boot Manager, its stage1 code follows the structure of all MBRs by placing the standard four-entry Partition Table in its agreed upon location (offsets 01BEh through 01FDh) which is followed by the standard Word-sized signature ID of AA55h (remember hex Words for Intel x86 CPUs are stored in memory with the Lowest-byte first and the Highest-byte last; that's why you see: "55 AA" on the disk).
Finally, GRUB makes sure not to use any of the bytes between offsets 1B8h and 1BBh because they're used by Microsoft® Windows NT/2000/XP/2003 as the NT Drive Serial Number; which in our example above is the four-byte WORD E1A8E1A8h.
Unlike many bootloaders,
since GRUB can function as either a Master Boot Record (when installed in the
first sector of a PC's
/dev/hda device; that is, its Primary,
Master hard disk) or as a Linux install's Volume boot record, it
never bothers to relocate its code, since there will be no other VBR code that
needs to be immediately loaded at Segment:Offset 0000:7C00. Only after GRUB is
fully operational (i.e., running elsewhere in memory), would it possibly need to perform a
chainload of some OS's boot record that might require use of this area of memory.
GRUB stage1 MBR Code:
7C00 EB48 JMP 7C4A ; Jump (short) over BPB data 7C02 90 NOP ; area to main body of code.
Although GRUB's BPB (BIOS Parameter Block) could contain data useful to many OS utilities, it's only used this way when GRUB is installed to a floppy diskette; in which case it uses the standard FAT VBR format (as explained here):
0 1 2 3 4 5 6 7 8 9 A B C D E F 7C00 00 00 00 00 00 00 00 00 00 00 00 00 00 ............. 7C10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7C20 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ 7C30 00 00 00 00 00 00 00 00 00 00 00 00 00 00 03 02 ................ 7C40 80 00 00 80 DF 0A 93 01 00 08 ..........
Stage1 Version Information: [7C3E] -> COMPAT_VERSION_MAJOR (03h), [7C3F] -> COMPAT_VERSION_MINOR (02h). BYTES in the GRUB data area which are referenced in the code below: [7C05] -> "Disk Address Packet" for LBA mode (see 7C90 and 7CD3). NOTE: These values may not correspond to any bytes that happen to be stored on the media here, but rather are overwritten in memory with values created by execution of the code. Therefore, you can safely zero-out (or fill with any other byte) the whole BIOS Parameter Block area as we did above! [7C40] -> 80 ("Boot Drive") NOTE: For those of you with multi-OS booting systems, if your Linux installation with GRUB's See: remaining software (stage2, menu file, etc.) is located 7C5A somewhere other than on the Primary Master drive, this value will be 81, 82, etc. depending upon which drive that Linux OS's /boot/grub directory is located. In the stage1.S file, it's called the GRUB_INVALID_DRIVE byte and commented as: "the disk to load stage2 from." (The word INVALID has something to do with the code logic.) [7C41] -> 00 ("Force LBA mode byte"; at 7C80) [7C42] -> 00 80 (8000h) Memory location where GRUB stores the next stage of the code to execute. See 7D54 below ("stage2_address"). [7C44] -> Note: A very important location for anyone using GRUB! This (4-byte) Quad-Word contains the location of GRUB's stage2 file in sectors! It's called "stage2_sector" in the stage1.S code. If GRUB is installed in the MBR by a distro that always includes a numbmer of sectors from stage2 immediately following the GRUB MBR, you will see the bytes 01 00 00 00 in this location; otherwise, it will point to stage2 in the "/boot/grub" directory. Example: DF 0A 93 01 (1930ADFh) [ "stage2 Sector" -> 26,413,791 ] [So, for this GRUB install, its stage2 file is located at Absolute Sector 26413791. This value will of course vary depending upon the physical location of the stage2 file!] [7C48] -> 00 08 (800h) ["stage2_segment" at 7D40; do not confuse it with the "stage2_address" 8000 at 7D54.]
Another example: A /boot partition had so many system errors we decided to save the files and reformat it. When re-writing the saved files back to the partition, as expected, the stage2 file ended up in a different location. So, we used a disk editor with a search function (HxD under Windows) to find the string "Loading stage2", then converted its Absolute Sector value of 26,472,763 to: 193F13Bh and finally changed the bytes in the GRUB MBR to: 3B F1 93 01.
NOTE: For anyone who may need to do this some day, we ran into yet another problem: The stage2 file itself also contains a hard-coded value (two actually) pointing to other parts of the GRUB code! See: First sector of stage2 (values in red) starting at offset 1F0. Though I was successful in editing them (I noted the difference between the two values and our old stage2 "base location" then made changes in the new stage2 values accordingly), we still do not know for sure what they're actually used for. It was enough to keep GRUB from operating correctly until we made the changes though! So, our new values in stage2 became: 55 F1 93 01 (offsets 1F0-1F3) and: 3C F1 93 01 (at offsets 1F8-1FB).
7C4A FA CLI ; In the 0.94 and 0.95 code, an OR DL,80 instruction is inserted here ; when GRUB is installed in an MBR as a "workaround for buggy BIOSes.." ; which don't pass the boot drive byte correctly. If GRUB is installed ; as the Linux Boot Sector, a value of 00 is used instead of 80, which ; effectively makes it a NOP. This code (80 CA 80) causes all offsets ; after it to shift by 3 bytes, so all relative jumps below would be ; different for these versions; even though its the same code! ; ; For the GNU GRUB 0.97 code, its programmers substituted the following ; as their "workaround for buggy BIOSes.." using the test dl,0x80 ; instruction, etc. (as shown here): ; 7C4B 90 nop ; These 'nops' are prob. for
; 7C4C 90 nop ; anticipated future changes! ; 7C4D F6C280 test dl,0x80 ; Check if DL is masked correctly. ; 7C50 7502 jnz 0x7c54 ; If not, then assume it's a ; 7C52 B280 mov dl,0x80 ; bogus value and set DL to 80. ; Thus, all the instructions below this line would be shifted by 9 bytes ; for version 0.97 (7C4Bh + 9 = 7C54h). 7C4B EA507C0000 JMP 0000:7C50 ; Long Jump to the next instruction ; because some bogus BIOSes jump to ; 07C0:0000 instead of 0000:7C00. 7C50 31C0 XOR AX,AX 7C52 8ED8 MOV DS,AX 7C54 8ED0 MOV SS,AX 7C56 BC0020 MOV SP,2000 7C59 FB STI 7C5A A0407C MOV AL,[7C40] ; <<<<<<<< Boot Drive 7C5D 3CFF CMP AL,FF 7C5F 7402 JZ 7C63 7C61 88C2 MOV DL,AL 7C63 52 PUSH DX 7C64 BE767D MOV SI,7D76 ; --> "GRUB " 7C67 E83401 CALL 7D9E ; Display GRUB ID on screen. 7C6A F6C280 TEST DL,80 7C6D 7454 JZ 7CC3 7C6F B441 MOV AH,41 ; Function 41h of INT13 7C71 BBAA55 MOV BX,55AA 7C74 CD13 INT 13 ; Test for INT13 Extensions 7C76 5A POP DX 7C77 52 PUSH DX 7C78 7249 JC 7CC3 ; If CF = 1, something wrong ; with test, so use CHS Mode. 7C7A 81FB55AA CMP BX,AA55 7C7E 7543 JNE 7CC3 ; If ZF = 0, INT13 Extensions ; failed, so use CHS Mode. 7C80 A0417C MOV AL,[7C41] ; <<<< Force LBA mode byte 7C83 84C0 TEST AL,AL ; At this point, SuSE Linux 9.1 added a JS (Jmp if SF = 1) to jump to ; the code at 7CC3. Why? Neither 0.94 nor 0.95 have this! There are ; already 3 jumps above (7C6D, 7C78, 7C7E) and 2 below (7C8A, 7CBC) ; to this same location. Is there a problem with "TEST AL,AL" here? ; And although we looked at what was supposed to be the official source ; code for both SuSE 9.1 and SuSE 9.2's (for grub-0.94 and -0.95), we ; could not find this instruction listed in either; so no help there! ; ; One of our readers believes this was a 'feature' added by SuSE 9.1 ; to force CHS mode! If bit 7 is set, execution will jump to 7CC3 no ; matter whether LBA mode is supported or not! ; ; NOTE: We finally received a reply to our question about this code in ; August, 2023 from a reader, Fabian Vogt, who pointed out that this ; code is in the update file "force-LBA-off.diff" which can be found ; inside the rpm package: grub-0.94-44.src.rpm. 7C85 7505 JNZ 7C8C 7C87 83E101 AND CX,+01 7C8A 7437 JZ 7CC3 ; LBA mode begins here: ; ==================== 7C8C 668B4C10 * MOV ECX,[SI+10] 7C90 BE057C MOV SI,7C05 ; <<<<<< Setup "Disk Packet" for Extended Read. 7C93 C644FF01 MOV BYTE PTR [SI-01],01 7C97 668B1E447C * MOV EBX,[7C44] ; <<<<<<< Location of Stage2 code from the beginning of the partition (the offset is in number of sectors). 7C9C C7041000 MOV WORD PTR [SI],0010 7CA0 C744020100 MOV WORD PTR [SI+02],0001 7CA5 66895C08 * MOV [SI+08],EBX 7CA9 C744060070 MOV WORD PTR [SI+06],7000 7CAE 6631C0 * XOR EAX,EAX 7CB1 894404 MOV [SI+04],AX 7CB4 6689440C * MOV [SI+0C],EAX 7CB8 B442 MOV AH,42 ; Function 42h of INT13 7CBA CD13 INT 13 ; Extended Read (using ; Disk Address Packet). 7CBC 7205 JC 7CC3 ; If LBA not supported, ; go to CHS mode only. 7CBE BB0070 MOV BX,7000 7CC1 EB7D JMP 7D40 ; CHS mode begins here: ; ==================== 7CC3 B408 MOV AH,08 ; Function 08 of INT13 7CC5 CD13 INT 13 ; Get Drive Parameters 7CC7 730A JNB 7CD3 7CC9 F6C280 TEST DL,80 ; Tests if HDD exists. 7CCC 0F84F300 * JZ 7DC3 ; Therefore, this jump is ; never taken unless grub was installed on and running from a floppy ; disk. And only then will you find more executable code at 7DC3. ; In the source code file (stage1.S), you'll find this short comment ; about the extra code: "Kinda sneaky, huh?" 7CD0 E98D00 JMP 7D60 ; There was an HDD Error! 7CD3 BE057C MOV SI,7C05 <<<<<< "Disk Packet" 7CD6 C644FF00 MOV BYTE PTR [SI-01],00 7CDA 6631C0 * XOR EAX,EAX ; Save number of heads: 7CDD 88F0 MOV AL,DH 7CDF 40 INC AX 7CE0 66894404 * MOV [SI+04],EAX 7CE4 31D2 XOR DX,DX 7CE6 88CA MOV DL,CL 7CE8 C1E202 * SHL DX,02 7CEB 88E8 MOV AL,CH 7CED 88F4 MOV AH,DH ; Save number of cylinders: 7CEF 40 INC AX 7CF0 894408 MOV [SI+08],AX 7CF3 31C0 XOR AX,AX 7CF5 88D0 MOV AL,DL 7CF7 C0E802 * SHR AL,02 ; Save number of sectors: 7CFA 668904 * MOV [SI],EAX 7CFD 66A1447C * MOV EAX,[7C44] <<<<<< Location of Stage2 code from the beginning of the partition (the offset is in number of sectors). 7D01 6631D2 * XOR EDX,EDX 7D04 66F734 * DIV WORD PTR [SI] ; Double word here. 7D07 88540A MOV [SI+0A],DL 7D0A 6631D2 * XOR EDX,EDX 7D0D 66F77404 * DIV WORD PTR [SI+04] ; Double word here. 7D11 88540B MOV [SI+0B],DL 7D14 89440C MOV [SI+0C],AX 7D17 3B4408 CMP AX,[SI+08] 7D1A 7D3C JGE 7D58 ; There was a Geometry Error! 7D1C 8A540D MOV DL,[SI+0D] 7D1F C0E206 * SHL DL,06 7D22 8A4C0A MOV CL,[SI+0A] 7D25 FEC1 INC CL 7D27 08D1 OR CL,DL 7D29 8A6C0C MOV CH,[SI+0C] 7D2C 5A POP DX 7D2D 8A740B MOV DH,[SI+0B] 7D30 BB0070 MOV BX,7000 7D33 8EC3 MOV ES,BX 7D35 31DB XOR BX,BX 7D37 B80102 MOV AX,0201 ; Function 02 of INT13 7D3A CD13 INT 13 ; Read 1 sector into Memory 7D3C 722A JB 7D68 ; There was a Read Error! 7D3E 8CC3 MOV BX,ES 7D40 8E06487C MOV ES,[7C48] ; <<<<<<<< WORD [0800 hex] ; Note: 800:0000 = 0000:8000 7D44 60 * PUSHA 7D45 1E PUSH DS 7D46 B90001 MOV CX,0100 7D49 8EDB MOV DS,BX 7D4B 31F6 XOR SI,SI 7D4D 31FF XOR DI,DI 7D4F FC CLD 7D50 F3A5 REP MOVSW 7D52 1F POP DS 7D53 61 * POPA ; This is where we jump to the next stage of the code which GRUB loaded ; from the HDD into Memory locations 0000:8000 hex and following: 7D54 FF26427C JMP [7C42] ; WORD <<< 8000 hex. ; "stage2_address".
7D58 BE7C7D MOV SI,7D7C ; --> "Geom Error" 7D5B E84000 CALL 7D9E ; Display it on screen. 7D5E EB0E JMP 7D6E ; Finish it and 'lock-up' 7D60 BE817D MOV SI,7D81 ; --> "Hard Disk Error" 7D63 E83800 CALL 7D9E ; Display it on screen. 7D66 EB06 JMP 7D6E ; Finish it and 'lock-up' 7D68 BE8B7D MOV SI,7D8B ; --> "Read Error" 7D6B E83000 CALL 7D9E ; Display it on screen. 7D6E BE907D MOV SI,7D90 ; (For displaying " Error") 7D71 E82A00 CALL 7D9E ; Finish it and 'lock-up' 7D74 EBFE JMP 7D74 ; Locks-up execution in an ; infinite loop! You must ; reboot your computer!
Location of the
GRUB ID String
and Error Messages in Memory
(for versions 0.92/0.93)
6 7 8 9 A B C D E F 7D76 47 52 55 42 20 00 47 65 6F 6D GRUB .Geom 7D80 00 48 61 72 64 20 44 69 73 6B 00 52 65 61 64 00 .Hard Disk.Read. 7D90 20 45 72 72 6F 72 00 Error. 0 1 2 3 4 5 6
For versions 0.94/0.95,
these characters begin at 7D7B instead;
for version 0.97, they begin at 7D7F.
7D97 BB0100 MOV BX,0001 7D9A B40E MOV AH,0E ; Function 0Eh of INT 10h 7D9C CD10 INT 10 ; Display the character 7D9E AC LODSB 7D9F 3C00 CMP AL,00 7DA1 75F4 JNZ 7D97 ; Loop until finding a zero byte. 7DA3 C3 RET
Partition Table in Memory
E F 7DBE 80 01 ................ 7DC0 01 00 07 FE FF 6D 3F 00 00 00 AF 39 D7 00 00 00 .....m?....9.... 7DD0 C1 6E 0C FE FF FF EE 39 D7 00 BD 86 BB 00 00 FE .n.....9........ 7DE0 FF FF 83 FE FF FF AB C0 92 01 CD 2F 03 00 00 FE .........../.... 7DF0 FF FF 0F FE FF FF 78 F0 95 01 83 AF CC 00 55 AA ......x.......U. 0 1 2 3 4 5 6 7 8 9 A B C D E F
Some of the following
Console commands require you to be root in order to use them, so unless
you're already logged in as 'root' you'll need to use the Console command: su.
This command will copy the first drive's MBR sector into a new 512-byte file called MBRhda.bin (in the same directory you run the command from):
# dd if=/dev/hda of=MBRhda.bin bs=512 count=1
If the first drive is SCSI rather than IDE/ATA, replace any occurrence of 'hda' with 'sda' in the command. [Placing this file on a couple diskettes and learning how to use a linux rescue system, such as good 'ole "tomsrtbt" or the SuSE 9.1 install CD's "rescue" boot, makes it just as easy to restore the MBR sector with the command: # dd if=MBRhda.bin of=/dev/hda bs=512 count=1 ].
If GRUB is in your MBR, then MBRhda.bin will be a copy of GRUB's stage1 code along with that drive's Partition Table. As a quick check, you could use the command: # cat MBRhda.bin |grep "GRUB" to see if the word "GRUB" exists anywhere in the file. If linux outputs: "Binary file (standard input) matches" on the next line, then chances are it's GRUB's stage1. To know for sure, you'd have to check the code against a known source. You can view the file similar to the Disk Editor View of GRUB above, by running the command:
# hexdump -Cv MBRhda.bin |less
which allows you to scroll up or down while viewing it; just press the "q" key to quit. The letter "v" in "-Cv" means "show every byte" in the file.
To find out where GRUB's stage2 code is located, you need to write down the 4-byte (Quad) Word located at offsets 0044h-0047h in the file, or open MBRhda.bin in that nice GUI Hex Editor, KHexEdit from KDE (which will do the necessary decimal conversion for you too):
Note: highlighted background colors added.
If we didn't have KHexEdit, we'd use a calculator program to convert the Quad Hex word 01934335h to 26428213 decimal. NOTE that your own GRUB MBR will have a different number here! Once again, this is the Absolute Sector location where GRUB's stage2 code begins. If you ever move a Linux partition with the /boot/grub directory, such as resizing it or just replacing the files in the grub directory, GRUB cannot function correctly until you change these four bytes to point to the new location of its stage2 code! (This is the main reason all Linux installs should ask you to create a boot diskette with GRUB on it, so you can run the GRUB install program from the diskette to correct these hard-coded values if necessar; otherwise, you'd have to manually perform the calculations and edit your MBR sector as we're doing here.) To confirm that you've got the correct number, substitute your own sector number for the "skip" value in this command:
# dd if=/dev/hda of=stage2-1s.bin bs=512 skip=26428213 count=1
This means that 'dd' will skip 26,428,213 512-byte sectors (bs=512) from the beginning of the hard drive, before it copies the next sector into the new file "stage2-1s.bin" (just the first sector [count=1]; the whole stage2 file on our system would require 259 sectors). If you believe that you've copied the correct sector on your own HDD, then take a look at it with this familiar command:
# hexdump -C stage2-1s.bin |less
You can view our example hexdump screen output here.
Updates: 26 September 2008 (26.09.2008); 17 October 2009 (17.10.2009).
Last Update: 28 January 2018 (28.01.2018).
You can write to me using this: online
reply form. (It opens in a new window.)
MBR and Boot Records Index
The Starman's Realm Index Page