     [file version.texi not included]

Copyright © 1996 Erich Boleyn Copyright © 1999 Free Software Foundation, Inc.

Permission is granted to make and distribute verbatim copies of this manual provided the copyright notice and this permission notice are preserved on all copies.

Permission is granted to copy and distribute modified versions of this manual under the conditions for verbatim copying, provided also that the entire resulting derived work is distributed under the terms of a permission notice identical to this one.

Permission is granted to copy and distribute translations of this manual into another language, under the above conditions for modified versions.

GRUB
****

This file documents GNU GRUB, the Grand Unified Bootloader.  This edition documents version VERSION.

Introduction
************

Briefly, a bootloader is the first software program that runs when a computer starts.  It is responsible for loading and transferring control to the operating system kernel software (such as the Linux or Hurd kernels).  The kernel, in turn, initializes the rest of the operating system (usually GNU).

History of GRUB
===============

GRUB originated in 1995 when Erich Boleyn was trying to boot the GNU Hurd with the University of Utah's Mach 4 microkernel (now known as GNU Mach).  Erich and Brian Ford designed the Multiboot Standard (see Motivation (The Multiboot Standard)), because they were determined not to add to the large number of mutually-incompatible PC boot methods.

Erich then began modifying the FreeBSD bootloader so that it would understand Multiboot.  He quickly realized that it would be a lot easier to write his own bootloader from scratch than to keep working on the FreeBSD bootloader, and so GRUB was born.

Erich added many features to GRUB, but other priorities prevented him from keeping up with the demands of its quickly-expanding user base.  In 1999, Gordon Matzigkeit and OKUJI Yoshinori adopted GRUB as an official GNU package, and opened its development by making the latest sources available via anonymous CVS. (The repository is :pserver:anoncvs@anoncvs.gnu.org:/gd/gnu/anoncvsroot, module grub.  Just hit return when prompted for a password.)

GRUB features
=============

The primary requirement for GRUB is that it be compliant with the Multiboot Standard, which is described in Motivation (The Multiboot Standard).

The other goals, listed in approximate order of importance, are:

  * Basic functions must be easy for an end-user to use.

  * Rich functionality for OS experts/designers.

  * Compatibility for booting FreeBSD, NetBSD, OpenBSD, and GNU/Linux. Proprietary OS's such as DOS, Windows NT, and OS/2 are supported via a chain-loading function.

Except for specific compatibility modes (chain-loading and the Linux piggyback format), all kernels will be started in much the same state as in the Multiboot Standard listed above. Only kernels being loaded at 1 megabyte or above are presently supported. Any attempt to load below that boundary will simply result in immediate failure and an error message reporting the problem.

In addition to the requirements above, GRUB has the following features (note that the Multiboot Standard doesn't explicitly require everything listed in it, but GRUB will support all options):

Multiple Executable Formats
     Supports many of the a.out variants plus ELF. Any symbol table present is also loaded.

Supports Non-Multiboot OS's
     Supports many of the various free 32-bit OS's prior to any Multiboot compliance. Chiefly FreeBSD, NetBSD, OpenBSD, and Linux. Chain-loading is also supported.

Loads Multiples Modules
     Multiboot feature of loading multiple modules is fully supported.

Configuration File
     Supports a human-readable text configuration file with preset boot commands. The list of commands (see Commands) are a superset of those supported on the command-line. An example command-file is provided under the directory docs/ in the source tree.

Menu Interface
     A menu-interface listing the preset boot commands, with a programmable timeout, is available. There is no fixed limit on the number of boot command-set entries, and should have space for several hundred.

Flexible Command-Line Interface
     A fairly flexible command-line interface, accessible from the menu, is available to edit any preset commands, or simply start a new command-set from scratch. The list of commands (see Commands) are a subset of those supported for command-files. Editing commands closely resemble the BASH shell command-line (see Command Line Editing (Bash Features)), with TAB-completion-listing (it doesn't perform the completion, just lists the possibilities) of commands, devices, partitions, and files in a directory depending on context. If no config file is present, it goes into the command-line.

Multiple Filesystem Types
     Supports multiple filesystem types transparently, plus an explicitly usable block-list notation. The currently supported filesystem types are BSD FFS, DOS FAT, and Linux ext2fs. See Filesystems, for more information.

Decompression Support
     Can decompress files which were compressed with using gzip. This function is both automatic and transparent to the user (i.e. all functions operate normally upon the uncompressed contents of the files in question). This is a win on 2 fronts, as it both greatly reduces file size and loading time (there are a few pathological cases where loading a very badly organized ELF kernel might make it take longer, but IMO you'll never see this in practice), a particularly major win for floppies. It is conceivable that some kernel modules should be loaded in a compressed state, so a variant of the modules loading command which doesn't uncompress them can be used.

Access Data on Any Installed Device
     Supports reading data from any or all floppy or hard disk(s) recognized by the BIOS, independent of the setting for the root partition.

Geometry Translation-Independent
     Subject to the constraint that it cannot go past the end of the geometry-translated area of a drive, the particular translation used is generally irrelevant. This implies a drive installed and running on a controller with one translation in use may in general be moved to another controller with a different translation (or the translation settings on the first controller, if configurable, may be changed) with no adverse effects and no other changes necessary.

Detects All Installed RAM
     GRUB can generally find all the installed RAM on a PC-compatible machine. It uses the BIOS query technique (see Memory detection). As described on the Multiboot Standard (see Motivation (The Multiboot Standard)), OS's which only use the lower and upper memory values (whose presence is determined by bit 0 of the flags word passed to the OS) may not be capable of receiving information on all of installed memory. On most machines, upper memory is contiguous, so the problem does not arise.

Supports Logical Block Address Mode
     In traditional disk calls (called CHS mode), there is a geometry translation problem, that is, the BIOS cannot access over 1024 cylinders, so the accessible space is limited to at least 508 MB and to at most 8GB. GRUB can't universally solve this problem, as there is no new interface which is used in all machines. However, some newer machines have the new interface, Logical Block Address (LBA) mode. So GRUB will automatically detect if LBA mode is available and use it if available. In LBA mode, GRUB can access the whole of your disk space.

Future directions might include an internal programming language for supporting richer sets of boot options with control statements (it becomes a boot-script at that point), and possibly support for non-IBM PC-compatible machines (There is a port to NEC PC-98xx series. See http://www.kuis.kyoto-u.ac.jp/~kmc/proj/linux98/arch/i386/boot/grub98/, for more information.).

The role of a bootloader
========================

The following is a quotation from Gordon Matzigkeit, a GRUB fanatic:

     Some people like to acknowledge both the operating system and kernel when they talk about their computers, so they might say they use ``GNU/Linux'' or ``GNU/Hurd''.  Other people seem to think that the kernel is the most important part of the system, so they like to call their GNU operating systems ``Linux systems.''

     I, personally, believe that this is a grave injustice, because the bootloader is the most important software of all.  I used to refer to the above systems as either ``LILO'' (The LInux LOader, a bootloader that everybody uses, but nobody likes.) or ``GRUB'' systems.

     Unfortunately, nobody ever understood what I was talking about; now I just use the word ``GNU'' as a pseudonym for GRUB.

     So, if you ever hear people talking about their alleged ``GNU'' systems, remember that they are actually paying homage to the best bootloader around... GRUB!

We, the GRUB maintainers, do not (usually) encourage Gordon's level of fanaticism, but it helps to remember that bootloaders deserve careful design.  We hope at least that you enjoy using GNU GRUB as much as we did writing it.

How to install GRUB on your computer
************************************

Due to the nature of a bootloader, you need to install GRUB on bootable media, such as a floppy disk. The installation can be performed by dd or rawrite for a boot floppy, or the install= command at the GRUB command line (see Using).

Creating a GRUB boot floppy
===========================

     Caution: This procedure will destroy any data currently stored on the floppy.

If you install GRUB using this method, it will only have access to the command-line interface, since there is no filesystem in which to find a configuration file (FIXME: ref). If you want to use the menu interface, see Automated install.

Under an UNIX-like operating system, such as GNU, use dd as follows, where /dev/fd0 is the floppy device:

     dd if=stage1/stage1 of=/dev/fd0 bs=512 count=1
     dd if=stage2/stage2 of=/dev/fd0 bs=512 seek=1

Under DOS-based systems, such as Windows, use copy and rawrite:

     copy /b stage1 + stage2 grub.raw
     rawrite grub.new a:

rawrite is available as a part of the installation tools that come with many GNU and GNU/Linux distributions.

Installation via the install= command
=====================================

     Caution: Installing GRUB's stage1 in this manner will erase the normal boot-sector used by an OS.  GRUB can boot GNU Mach, Linux, FreeBSD, NetBSD, and OpenBSD directly, so this may be desired.  Generally, it is a good idea to back up the first sector of the partition on which you are installing GRUB's stage1.  This isn't as important if you are installing GRUB on the first sector of a hard disk, since it's easy to reinitialize it (by running FDISK /MBR from DOS).

GRUB has a command called install= which is described in see Using. The purpose of this section is to give examples and describe how to use the command in different situations.

First, make a GRUB boot floppy (see Boot floppy).  This is simply a way to get the process started easily; any bootable copy of the same version GRUB will work fine.

Then, make a /boot/grub directory (\boot\grub under DOS) in the install partition.  Place the GRUB stage2 file, any optional stage1.5 files, and the configuration file (menu.lst) in that directory.

Now figure out how to use the install= command appropriately, and you're done!

Examples of how to use the install= command:

  * Make a hard disk bootable with GRUB's stage2 on PC partition number 2: Make a directory in the partition called /boot/grub, place the stage2 (and if desired, your configuration file called menu.lst), then run the following command at GRUB's command line (after booting from the GRUB floppy):

          install= (fd0)+1 (hd0) (hd0,2)/boot/grub/stage2 0x8000 p

     This tells GRUB to grab the first sector of the floppy and use it as the stage1, create a block-list using the file /boot/grub/stage2 on the first hard disk (partition number 2), merge them together, set the load address correctly for a stage2 (0x8000), save the install partition in the first sector of the stage2 (the p at the end), then write the result to the first sector of the hard disk.

  * Same as above, but place the stage1 on the floppy, then have it start the stage2 on the hard disk: The difference here is you're telling GRUB's stage1 to read from the first hard disk no matter where the stage1 was loaded from:

          install= (fd0)+1 d (fd0) (hd0,2)/boot/grub/stage2 0x8000 p

     The d option near the beginning is what sets the forced loading from the disk where the stage2 was installed from.  Also, the destination device is changed to place the finished stage1 on the floppy disk.

  * Installing from an install directory to the second hard disk: Here we're loading the stage1 from a file on the first hard disk, installing stage2 from the first BSD a partition on the second hard disk, and setting the stage2's configuration file to (hd1,a)/grubdir/configfile:

          install= (hd0,2)/boot/grub/stage1 (hd1) (hd1,a)/boot/grub/stage2 0x8000 p /grubdir/configfile

You can automate these steps by using a GRUB floppy with a filesystem and a configuration file which contains entries such as:

     # Start of entries
     title= GNU/Linux installation

     # install command
     install= (fd0)+1 (hd0) (hd0,1)/boot/grub/stage2 0x8000 p

     # actually boot here
     root= (hd0,1)
     kernel= /zImage root=/dev/hda2

... then have the install script continue from there after boot of the OS.

Booting your operating system
*****************************

GRUB has both a simple menu interface for choosing preset entries from a configuration file, and a highly flexible command-line for performing any desired combination of boot commands.

GRUB looks for its configuration file as soon as it is loaded.  If one is found, then the full menu interface is activated using whatever entries were found in the file.  If you choose the `command line' menu option, or if the configuration file was not found, then GRUB drops into the command-line interface.

The flexible command-line interface
===================================

The command-line interface provides a prompt and after it an editable text area much like a command-line in Unix or DOS. Each command is immediately executed after it is entered  (However, this behavior will be changed in the future version, in an user-invisible way.). The commands are a subset of those available in the configuration file, used with exactly the same syntax.

Cursor movement and editing of the text on the line can be done via a subset of the functions available in the BASH (FIXME: ref) shell (C-f forward, C-b backward, C-a beginning of line, C-e end of line, C-k delete to end, C-u delete to beginning; the PC left and right arrow keys, HOME, DEL, and END work as well).

When typing commands interactively, if the cursor is before the = character in a command being typed, pressing the TAB key will display a listing of the available commands, and if the cursor is after the = character, the TAB will provide a completion listing of disks, partitions, and filenames depending on the context.

The simple menu interface
=========================

The menu interface is quite easy to use.  It's commands are both reasonably intuitive and described on screen.

Basically, the menu interface provides a list of boot configurations to the user to choose from.  Use the arrow keys to select the entry of choice, then press RET to run it.  An optional timeout is available to boot the default entry (the first one if not set), which is aborted by pressing any key.

Commands are available to enter a bare command-line (operating exactly like the non-config-file version of GRUB, but allowing one to return to the menu if desired) or to edit any of the boot configurations, respectively by pressing c or e.

Editing a menu entry
====================

This looks much like the main menu interface, but with the lines in the menu being individual commands of the selected configuration instead of configuration names.

If an ESC is pressed in the editor, it aborts all the changes made to the configuration entry and goes back to the main menu interface.

When a particular line is selected, then it places the user in a special version of the command-line for editing that line.  When the user is finished, GRUB replaces the line in question in the boot configuration with the changes (unless it was aborted via ESC, and in that case the changes are thrown away).

The list of available commands
==============================

In this section, we list the available commands, both in the configuration file and in the command-line.

The configuration file should follow these rules:

 1. The configuration file specific commands have to be used before any others.

 2. A multiboot kernel must be loaded before modules can be.

 3. A kernel must be loaded before either the configuration file entry ends, or any boot command is issued in any case.

The semantics are as follows:

  * The files must be in plain-text format.

  * # at the beginning of a line means it is a comment line in a configuration file only.

  * Options are separated by spaces.

  * All numbers can be either decimal or hexadecimal. A hexadecimal number must be preceded by 0x, and is case insensitive.

  * Extra options/text at the end of the line is ignored unless otherwise specified.

  * Bad commands generally get included in the current entry being added to, except before entries start, where they are ignored.

Commands usable in configuration files only.

timeout= SEC
     Set a timeout, in SEC seconds, before automatically booting the default entry (normally the first entry defined).

default= NUM
     Set the default entry to entry number NUM (otherwise it is 0, the first entry).

fallback= NUM
     Go into unattended boot mode: if the default boot entry has any errors, instead of waiting for the user to do anything, it immediately starts over using the NUM entry (same numbering as the default= command). This obviously doesn't help if the machine was in the middle of the boot process (after leaving GRUB's code) and rebooted.

password= PASSWD NEW_CONFIG_FILE
     Disable all interactive editing control (menu entry editor and command-line). If the password PASSWD is entered, it loads the NEW_CONFIG_FILE as a new config file and restarts the GRUB Stage 2.

title= ...
     Start a new menu entry, and set its name to the contents of the rest of the line, starting with the first non-space character.

Commands usable in configuration files and interactively.

pause= ...
     Print the entirety to the end of its line, then wait until a key is pressed. Note that placing a ^G in it will cause the speaker to emit the standard beep sound, which is useful when asking the user to change floppies, etc.

uppermem= KBYTES
     Force GRUB to ignore what it found during the autoprobe of the memory available to the system, and to use KBYTES as the number of kilobytes of upper memory installed. Any address range maps of the system are discarded.

     Caution: This should be used with great caution, and should only be necessary on some old machines. GRUB's BIOS probe can pick up all RAM on all new machines the author has ever heard of. It can also be used for debugging purposes to lie to an OS.

root= DEVICE [HDBIAS]
     Set the current root partition to the device DEVICE, then attempt to mount it to get the partition size (for passing the partition descriptor in ES:ESI, used by some chain-loaded bootloaders), the BSD drive-type (for booting BSD kernels using their native boot format), and fix up automatic determination of the PC partition where a BSD sub-partition is located. The optional HDBIAS parameter is a number to tell a kernel which is using one of the BSD boot methodologies how many BIOS drive numbers are on controllers before the current one. An example is if there is an IDE disk and a SCSI disk, then set the root partition normally, except for a kernel using a BSD boot methodology (FreeBSD or NetBSD), then use a 1 for HDBIAS.

rootnoverify= DEVICE [HDBIAS]
     Similar to root=, but don't attempt to mount the partition. This is useful for when an OS is outside of the area of the disk that GRUB can read, but setting the correct root partition is still desired. Note that the items mentioned in root= above which derived from attempting the mount will NOT work correctly.

chainloader= FILE
     Load FILE as a chain-loader. Like any other file loaded by the filesystem code, it can use the block-list notation to grab the first sector of the current partition with +1.

kernel= FILE ...
     Attempt to load the primary boot image (Multiboot a.out or ELF, Linux zImage or bzImage, FreeBSD-a.out, or NetBSD-a.out) from FILE. This command ignores the rest of the contents of the line, except that the entire line starting with the kernel filename is passed verbatim as the kernel command-line. The module state is reset by this (i.e. reload any modules).

module= FILE ...
     Load a boot module for a Multiboot format boot image (no interpretation of the file contents are made, so that user of this command/writer of the configuration file must know what the kernel in question works with). The rest of the line is passed as the module command-line much like with the kernel= command.

modulenounzip= FILE ...
     Exactly like module=, except that automatic decompress is disabled.

initrd= FILE ...
     Load an initial ramdisk for a Linux format boot image and set the appropriate parameters in the Linux setup area in memory.

install= STAGE1_FILE [d] DEST_DEV FILE ADDR [p] [CONFIG_FILE]
     This command is fairly complex, and for detailed examples one should look at Automated install. In short, it will perform a full install presuming the stage1.5 or stage2 (they're loaded the same way, I'll just refer to it as a stage2 from now on) is in its final install location (pretty much all other edits are performed by the install= command).

     In slightly more detail, it will load STAGE1_FILE, validate that it is a GRUB stage1 of the right version number, install block-list for loading FILE (if the option d is present, the stage1 will always look for the actual disk FILE was installed on, rather than using the booting drive) as a stage2 into memory at address ADDR (for a stage1.5, an address of 0x2000 should be used, and for a stage2, an address of 0x8000 should be used), then write the completed stage1 to the first block of the device DEST_DEV. If the options p or CONFIG_FILE are present, then it reads the first block of stage2, modifies it with the values of the partition FILE was found on (for p) or places the string CONFIG_FILE into the area telling the stage2 where to look for a configuration file at boot time. Finally, it preserves the DOS BPB (and for hard disks, the partition table) of the sector the stage1 is to be installed into.

makeactive
     Set the active partition on the root disk to GRUB's root partition (on a floppy this is a NO-OP). This is limited to working with primary PC partitions.

boot
     This boots the OS/chain-loader which has been loaded. Only necessary if running the fully interactive command-line (it is implicit at the end of a config-file entry).

Commands usable in configuration files and interactively which are only available in the debug version of the GRUB Stage 2.

testload= FILE
     Read the entire contents of FILE in several different ways and compares them, to test the filesystem code. The output is somewhat cryptic (see the T subcommand of syscmd= below), but if no errors are reported and the part right at the end which reads i=X, filepos=Y has X and Y equal, then it is definitely consistent, and very likely works correctly subject to a consistent offset error. A good idea if this works is then to try loading a kernel with your code.

read= ADDR
     Read a 32-bit unsigned value at address ADDR and displays it in hex format.

displaymem
     Display what GRUB thinks the system address space map of the machine is, including all regions of physical RAM installed. The upper/lower memory thing GRUB has uses the standard BIOS interface for the available memory in the first megabyte, or lower memory, and a synthesized number from various BIOS interfaces of the memory starting at 1MB and going up to the first chipset hole for upper memory (the standard PC upper memory interface is limited to reporting a maximum of 64MB).

impsprobe
     Probe Intel MPS spec 1.1 or 1.4 configuration table and boot the various other CPUs which are found into a tight loop.

fstest
     Toggle filesystem test mode.

     Filesystem test mode, when turned on, prints out data corresponding to all the device reads and what values are being sent to the low-level routines. The format is <SECTOR, BYTE_OFFSET, BYTE_LEN> for high-level reads inside a partition (so SECTOR is an offset from the start of the partition), and [SECTOR] for low-level sector requests from the disk (so SECTOR is offset from the start of the disk).

     Filesystem test mode is turned off by any uses of the install= or testload= commands.

Filesystem syntax and semantics
*******************************

GRUB uses special syntax for specifying disk drives, that can be accessed by BIOS. Because of BIOS limitations, GRUB cannot distinguish IDE, ESDI, SCSI, etc. So you must know which BIOS device is equivalent to which OS device.

How to specify devices
======================

The device syntax is like this:

     (BIOS_DEVICE[,PART_NUM][,BSD_SUBPART_LETTER])

[] means the parameter is optional. BIOS_DEVICE should be either fd or hd followed by a digit, like fd0. But you can also set BIOS_DEVICE to a hexadecimal or a decimal, which is a BIOS drive number, so these are equivalent:

     (hd0)
     (0x80)
     (128)

PART_NUM represents the partition number of BIOS_DEVICE, starting from zero, and BSD_SUBPART_LETTER represents the BSD sub-partition, like a or e.

A shortcut for specifying BSD sub-partitions is (BIOS_DEVICE,BSD_SUBPART_LETTER), in this case, GRUB searches for the first PC partition containing BSD sub-partitions, then finds the sub-partition BSD_SUBPART_LETTER. Here is an example:

     (hd0,a)

How to specify files
====================

There are two ways to specify files, absolute pathname and block-list.

Absolute pathname resembles a Unix absolute pathname. Use / for the directory separator but not \ like DOS. For example, /boot/grub/menu.lst.

Block-list is used for specifying a file that doesn't appear in the filesystem, like a chain-loader. The syntax is a bit complex, like this:

     1+100,200+1,300+300

This represents that GRUB should read 100 blocks from the offset 1, 1 block from the offset 200, and 300 blocks from the offset 300. The offset is counted from the start of a partition, so the length must be within the partition size. If you omit a offset, then GRUB assumes the offset is zero.

Error messages reported by GRUB
*******************************

This chapter describes the meanings of the error messages reported by GRUB when you encounter some troubles.

Errors reported by the Stage 1
==============================

The general way that the Stage 1 handles errors is to print an error string and then halt. Pressing CTRL-ALT-DEL will reboot.

The following is a comprehensive list of error messages for the Stage 1:

Hard Disk Error
     This error message will occur if the Stage 2 or Stage 1.5 is being read from a hard disk, and the attempt to determine the size and geometry of the hard disk fails.

Floppy Error
     This error message will occur if the Stage 2 or Stage 1.5 is being read from a floppy disk, and the attempt to determine the size and geometry of the floppy disk fails. It's listed as a different error since the probe sequence is different than for hard disks.

Read Error
     This error message will occur if a disk read error happens while trying to read the Stage 2 or Stage 1.5.

Geom Error
     This error message will occur if the location of the Stage 2 or Stage 1.5 is not in the area supported by reading the disk with the BIOS directly. This could occur because the BIOS translated geometry has been changed by the user or the disk is moved to another machine or controller after installation, or GRUB was not installed using itself (if it was, the Stage 2 version of this error would have been seen during that process and it would not have completed the install).

Errors reported by the Stage 1.5
================================

The general way that the Stage 1.5 handles errors is to print an error number in the form Error: NUM and then halt. Pressing CTRL-ALT-DEL will reboot.

The error numbers correspond to the Stage2 errors in the listed sequence.

Errors reported by the Stage 2
==============================

The general way that the Stage 2 handles errors is to abort the operation in question, print an error string, then (if possible) either continue based on the fact that an error occurred or wait for the user to deal with the error.

The following is a comprehensive list of error messages for the Stage 2 (error numbers for the Stage 1.5 are listed before the colon in each description):

1 : Selected item won't fit into memory
     This error is returned if a kernel, module, or raw file load command is either trying to load its data such that it won't fit into memory or it is simply too big.

2 : Selected disk doesn't exist
     This error is returned if the device part of a device- or full filename refers to a disk or BIOS device that is not present or not recognized by the BIOS in the system.

3 : Disk read error
     This error is returned if there is a disk read error when trying to probe or read data from a particular disk.

4 : Disk write error
     This error is returned if there is a disk write error when trying to write to a particular disk. This would generally only occur during an install of set active partition command.

5 : Disk geometry error
     This error is returned when a read is attempted at a linear block address beyond the end of the BIOS translated area. This generally happens if your disk is larger than the BIOS can handle (512MB for (E)IDE disks on older machines or larger than 8GB in general).

6 : Attempt to access block outside partition
     This error is returned if a linear block address is outside of the disk partition. This generally happens because of a corrupt filesystem on the disk or a bug in the code handling it in GRUB (it's a great debugging tool).

7 : Partition table invalid or corrupt
     This error s returned if the sanity checks on the integrity of the partition table fail. This is a bad sign.

8 : No such partition
     This error is returned if a partition is requested in the device part of a device- or full filename which isn't on the selected disk.

9 : Bad filename (must be absolute pathname or blocklist)
     This error is returned if a filename is requested which doesn't fit the syntax/rules listed in the Filesystems.

10 : Bad file or directory type
     This error is returned if a file requested is not a regular file, but something like a symbolic link, directory, or FIFO.

11 : File not found
     This error is returned if the specified filename cannot be found, but everything else (like the disk/partition info) is OK.

12 : Cannot mount selected partition
     This error is returned if the partition requested exists, but the filesystem type cannot be recognized by GRUB.

13 : Inconsistent filesystem structure
     This error is returned by the filesystem code to denote an internal error caused by the sanity checks of the filesystem structure on disk not matching what it expects. This is usually caused by a corrupt filesystem or bugs in the code handling it in GRUB.

14 : Filesystem compatibility error, can't read whole file
     Some of the filesystem reading code in GRUB has limits on the length of the files it can read. This error is returned when the user runs into such a limit.

15 : Error while parsing number
     This error is returned if GRUB was expecting to read a number and encountered bad data.

16 : Device string unrecognizable
     This error is returned if a device string was expected, and the string encountered didn't fit the syntax/rules listed in the Filesystems.

17 : Invalid device requested
     This error is returned if a device string is recognizable but does not fall under the other device errors.

18 : Invalid or unsupported executable format
     This error is returned if the kernel image being loaded is not recognized as Multiboot or one of the supported native formats (Linux zImage or bzImage, FreeBSD, or NetBSD).

19 : Loading below 1MB is not supported
     This error is returned if the lowest address in a kernel is below the 1MB boundary. The Linux zImage format is a special case and can be handled since it has a fixed loading address and maximum size.

20 : Unsupported Multiboot features requested
     This error is returned when the Multiboot features word in the Multiboot header requires a feature that is not recognized. The point of this is that the kernel requires special handling which GRUB is likely usable to provide.

21 : Unknown boot failure
     This error is returned if the boot attempt did not succeed for reasons which are unknown.

22 : Must load Multiboot kernel before modules
     This error is returned if the module load command is used before loading a Multiboot kernel. It only makes sense in this case anyway, as GRUB has no idea how to communicate the presence of location of such modules to a non-Multiboot-aware kernel.

23 : Must load Linux kernel before initrd
     This error is returned if the initrd command is used before loading a Linux kernel. Similar to the above error, it only makes sense in that case anyway.

24 : Cannot boot without kernel loaded
     This error is returned if GRUB is told to execute the boot sequence without having a kernel to start.

25 : Unrecognized command
     This error is returned if an unrecognized command is entered into the command-line or in a boot sequence section of a configuration file and that entry is selected.

26 : Bad or incompatible header on compressed file
     This error is returned if the file header for a supposedly compressed file is bad.

27 : Bad or corrupt data while decompressing file
     This error is returned the run-length decompression code gets an internal error. This is usually from a corrupt file.

28 : Bad or corrupt version of stage1/stage2
     This error is returned if the install command is pointed to incompatible or corrupt versions of the stage1 or stage2. It can't detect corruption in general, but this is a sanity check on the version numbers, which should be correct.

The command grub
****************

Introduction into the Stage 2 emulator
======================================

FIXME

The list of grub options
========================

FIXME

How to install GRUB by grub
===========================

FIXME

Implementation details
**********************

This chapter describes the GRUB internals so that developers can understand the implementation and start to hack GRUB. Of course, the source code has the complete information, so refer to it when you are not satisfied with this documentation.

The memory map of various components
====================================

GRUB is broken into 2 distinct components, or stages, which are loaded at different times in the boot process. The Stage 1 has to know where to find Stage 2, and the Stage 2 has to know where to find its configuration file (if Stage 2 doesn't have a configuration file, it drops into the command-line interface and waits for a user command).

Here is the memory map of the various components (Currently GRUB does not use the extended memory for itself, since it is used to load an operating system. But we are planning to use it for GRUB itself in the future by lazy loading. Ask okuji for more information.):

0 to 4K-1
     Interrupt & BIOS area

down from 8K-1
     16-bit stack area

8K to (ebss1.5)
     Stage 1.5 (optionally) loaded here by Stage 1

0x7c00 to 0x7dff
     Stage 1 loaded here by the BIOS

0x7e00 to 0x7e08
     Scratch space used by Stage 1

32K to (ebss2)
     Stage 2 loaded here by Stage 1.5 or Stage 1

(middle area)
     Heap used for random memory allocation

down from 416K-1
     32-bit stack area

416K to 448K-1
     Filesystem info buffer (when reading a filesystem)

448K to 479.5K-1
     BIOS track read buffer

479.5K to 480K-1
     512 byte fixed SCRATCH area

480K to 511K-1
     General storage heap

Embedded variables in GRUB
==========================

GRUB's stage1 and stage2 have embedded variables whose locations are well-defined, so that the installation can patch the binary file directly without recompilation of the modules.

In stage1, these are defined (The number in the parenthesis of each entry is an offset number):

major version (0x1bc)
     This is the major version byte (should be 2).

minor version (0x1bd)
     This is the minor version byte (should be 0).

stage2 start address (0x1b8)
     This is the data for the ljmp command to the starting address of the component loaded by the stage1. The format is two 2-byte words: the first is the IP, and the second is the CS segment register (remember, we're in x86 real-mode... 16-bit instruction pointer and segment registers shifted left by 4bits).

     A stage1.5 should be loaded at address 0x2000, and a stage2 should be loaded at address 0x8000. Both use a CS of 0.

firstlist (0x1b05)
     This is the ending address of the block-list data area.

     The trick here is that it is actually read backward, and the first 8-byte block-list is not read here, but after the pointer is decremented 8 bytes, then after reading it, it decrements again, reads, decrements, reads, etc. until it is finished.  The terminating condition is when the number of sectors to be read in the next block-list is 0.

     The format of a block-list can be seen from the example in the code just before the firstlist label.  (note that it is always from the beginning of the disk, and not relative to the partition boundaries)

loading drive (0x1b05)
     This is the BIOS drive number to load the block-lists from. If the number is 0xff, then load from the booting drive.

In stage1.5 and stage2 (these are all defined at the beginning of shared_src/asm.S):

major version (0x6)
     This is the major version byte (should be 2).

minor version (0x7)
     This is the minor version byte (should be 0).

install_partition (0x8)
     This is an unsigned long representing the partition on the currently booted disk which GRUB should expect to find it's data files and treat as the default root partition.

     The format of is exactly the same as the partition part (the disk part is ignored) of the data passed to an OS by a Multiboot-compliant bootloader in the boot_device data element, with one exception.

     The exception is that if the first level of disk partitioning is left as 0xFF (decimal 255, which is marked as no partitioning being used), but the second level does have a partition number, it looks for the first BSD-style PC partition, and finds the numbered BSD sub-partition in it. The default install_partition 0xFF00FF, would then find the first BSD-style PC partition, and use the a partition in it, and 0xFF01FF would use the b partition, etc.

     If an explicit first-level partition is given, then no search is performed, and it will expect that the BSD-style PC partition is in the appropriate location, else a no such partition error will be returned.

     If a stage1.5 is being used, it will pass its own install_partition to any stage2 it loads, therefore overwriting the one present in the stage2.

version_string (0xc)
     This is the stage1.5 or stage2 version string. It isn't meant to be changed, simply easy to find.

config_file (after the terminating zero of version_string)
     This is the location, using the GRUB filesystem syntax, of the config file.  It will, by default, look in the install_partition of the disk GRUB was loaded from, though one can use any valid GRUB filesystem string, up to and including making it look on other disks.

     The bootloader itself doesn't search for the end of version_string, it simply knows where config_file is, so the beginning of the string cannot be moved after compile-time.  This should be OK, since the version_string is meant to be static.

     The code of stage2 starts again at offset 0x70,	so config_file string obviously can't go past there.  Also, remember to terminate the string with a 0.

How to detect all installed RAM
===============================

There are three BIOS calls which return the information of installed RAM. GRUB uses these calls to detect all installed RAM and which address range should be treated by operating systems.

INT 15H, AX=E820h interrupt call
--------------------------------

Real mode only.

This call returns a memory map of all the installed RAM, and of physical memory ranges reserved by the BIOS. The address map is returned by making successive calls to this API, each returning one "run" of physical address information.  Each run has a type which dictates how this run of physical address range should be treated by the operating system.

If the information returned from INT 15h, AX=E820h in some way differs from INT 15h, AX=E801h (see Get Large Memory Size) or INT 15h AH=88h (see Get Extended Memory Size), then the information returned from E820h supersedes what is returned from these older interfaces. This allows the BIOS to return whatever information it wishes to for compatibility reasons.

Input:

EAX   Function Code   E820h

EBX   Continuation   Contains the continuation
value to get the next run of physical memory. This is the value
returned by a previous call to this routine. If this is the first call,
EBX must contain zero.

ES:DI   Buffer Pointer   Pointer to an Address Range
Descriptor structure which the BIOS is to fill in.

ECX   Buffer Size   The length in bytes of the
structure passed to the BIOS. The BIOS will fill in at most ECX
bytes of the structure or however much of the structure the BIOS
implements. The minimum size which must be supported by both the BIOS
and the caller is 20 bytes. Future implementations may extend this
structure.

EDX   Signature   SMAP - Used by the BIOS to
verify the caller is requesting the system map information to be
returned in ES:DI.

Output:

CF   Carry Flag   Non-Carry - indicates no error

EAX   Signature   SMAP - Signature to verify
correct BIOS revision.

ES:DI   Buffer Pointer   Returned Address Range
Descriptor pointer. Same value as on input.

ECX   Buffer Size   Number of bytes returned by the
BIOS in the address range descriptor. The minimum size structure
returned by the BIOS is 20 bytes.

EBX   Continuation   Contains the continuation value
to get the next address descriptor. The actual significance of the
continuation value is up to the discretion of the BIOS. The caller must
pass the continuation value unchanged as input to the next iteration of
the E820h call in order to get the next Address Range Descriptor. A
return value of zero means that this is the last descriptor. Note that
the BIOS indicate that the last valid descriptor has been returned by
either returning a zero as the continuation value, or by returning
carry.

The Address Range Descriptor Structure is:

Offset in Bytes   Name   Description

0   BaseAddrLow   Low 32 Bits of Base Address

4   BaseAddrHigh   High 32 Bits of Base Address

8   LengthLow   Low 32 Bits of Length in Bytes

12   LengthHigh   High 32 Bits of Length in Bytes

16   Type   Address type of this range

The BaseAddrLow and BaseAddrHigh together are the 64 bit BaseAddress of this range. The BaseAddress is the physical address of the start of the range being specified.

The LengthLow and LengthHigh together are the 64 bit Length of this range. The Length is the physical contiguous length in bytes of a range being specified.

The Type field describes the usage of the described address range as defined in the table below:

Value   Pneumonic   Description

1   AddressRangeMemory   This run is available
RAM usable by the operating system.

2   AddressRangeReserved   This run of addresses is in
use or reserved by the system, and must not be used by the operating
system.

Other   Undefined   Undefined - Reserved for future
use. Any range of this type must be treated by the OS as if the type
returned was AddressRangeReserved.

The BIOS can use the AddressRangeReserved address range type to block out various addresses as not suitable for use by a programmable device.

Some of the reasons a BIOS would do this are:

  * The address range contains system ROM.

  * The address range contains RAM in use by the ROM.

  * The address range is in use by a memory mapped system device.

  * The address range is for whatever reason are unsuitable for a standard device to use as a device memory space.

Here is the list of assumptions and limitations:

 1. The BIOS will return address ranges describing base board memory and ISA or PCI memory that is contiguous with that base board memory.

 2. The BIOS will not return a range description for the memory mapping of PCI devices. ISA Option ROM's, and ISA plug & play cards. This is because the OS has mechanisms available to detect them.

 3. The BIOS will return chipset defined address holes that are not being used by devices as reserved.

 4. Address ranges defined for base board memory mapped I/O devices (for example APICs) will be returned as reserved.

 5. All occurrences of the system BIOS will be mapped as reserved. This includes the area below 1 MB, at 16 MB (if present) and at end of the address space (4 GB).

 6. Standard PC address ranges will not be reported. Example video memory at A0000 to BFFFF physical will not be described by this function. The range from E0000 to EFFFF is base board specific and will be reported as suits the bas board.

 7. All of lower memory is reported as normal memory. It is OS's responsibility to handle standard RAM locations reserved for specific uses, for example: the interrupt vector table (0:0) and the BIOS data area (40:0).

Here we explain an example address map. This sample address map describes a machine which has 128 MB RAM, 640K of base memory and 127 MB extended.  The base memory has 639K available for the user and 1K for an extended BIOS data area.  There is a 4 MB Linear Frame Buffer (LFB) based at 12 MB.  The memory hole created by the chipset is from 8 M to 16 M.  There are memory mapped APIC devices in the system.  The IO Unit is at FEC00000 and the Local Unit is at FEE00000.  The system BIOS is remapped to 4G - 64K.

Note that the 639K endpoint of the first memory range is also the base memory size reported in the BIOS data segment at 40:13.

Key to types: ARM is AddressRangeMemory, ARR is AddressRangeReserved.

Base (Hex)   Length   Type   Description

0000 0000   639K   ARM   Available Base memory -
typically the same value as is returned via the INT 12 function.

0009 FC00   1K   ARR   Memory reserved for use by the
BIOS(s). This area typically includes the Extended BIOS data area.

000F 0000   64K   ARR   System BIOS.

0010 0000   7M   ARM   Extended memory, this is not
limited to the 64MB address range.

0080 0000   8M   ARR   Chipset memory hole required to
support the LFB mapping at 12 MB.

0100 0000   120M   ARM   Base board RAM relocated
above a chipset memory hole.

FE00 0000   4K   ARR   IO APIC memory mapped I/O at
FEC00000. Note the range of addresses required for an APIC device may
vary from base OEM to OEM.

FEE0 0000   4K   ARR   Local APIC memory mapped I/O at
FEE00000.

FFFF 0000   64K   ARR   Remapped System BIOS at end of
address space.

The following code segment is intended to describe the algorithm needed when calling the Query System Address Map function. It is an implementation example and uses non standard mechanisms.

     E820Present = FALSE;
     Regs.ebx = 0;
     do
       {
         Regs.eax = 0xE820;
         Regs.es = SEGMENT (&Descriptor);
         Regs.di = OFFSET (&Descriptor);
         Regs.ecx = sizeof (Descriptor);
         Regs.edx = 'SMAP';

         _int (0x15, Regs);

         if ((Regs.eflags & EFLAGS_CARRY) || Regs.eax != 'SMAP')
           {
             break;
           }

         if (Regs.ecx < 20 || Regs.ecx > sizeof (Descriptor))
           {
             /* bug in bios - all returned descriptors must be at
                least 20 bytes long, and can not be larger than
                the input buffer.  */
             break;
           }

         E820Present = TRUE;
         .
         .
         .
         Add address range Descriptor.BaseAddress through
         Descriptor.BaseAddress + Descriptor.Length
         as type Descriptor.Type
         .
         .
         .
       }
     while (Regs.ebx != 0);

     if (! E820Present)
       {
         .
         .
         .
         call INT 15H, AX E801h and/or INT 15H, AH=88h to obtain old style
         memory information
         .
         .
         .
       }

INT 15H, AX=E801h interrupt call
--------------------------------

Real mode only.

Originally defined for EISA servers, this interface is capable of reporting up to 4 GB of RAM.  While not nearly as flexible as E820h, it is present in many more systems.

Input:

AX   Function Code   E801h.

Output:

CF   Carry Flag   Non-Carry - indicates no error.

AX   Extended 1   Number of contiguous KB between 1
and 16 MB, maximum 0x3C00 = 15 MB.

BX   Extended 2   Number of contiguous 64KB blocks
between 16 MB and 4GB.

CX   Configured 1   Number of contiguous KB between 1
and 16 MB, maximum 0x3c00 = 15 MB.

DX   Configured 2   Number of contiguous 64KB blocks
between 16 MB and 4 GB.

Not sure what this difference between the Extended and Configured numbers are, but they appear to be identical, as reported from the BIOS.

It is possible for a machine using this interface to report a memory hole just under 16 MB (Count 1 is less than 15 MB, but Count 2 is non-zero).

INT 15H, AX=88h interrupt call
------------------------------

Real mode only.

This interface is quite primitive.  It returns a single value for contiguous memory above 1 MB.  The biggest limitation is that the value returned is a 16-bit value, in KB, so it has a maximum saturation of just under 64 MB even presuming it returns as much as it can.  On some systems, it won't return anything above the 16 MB boundary.

The one useful point is that it works on every PC available.

Input:

AH   Function Code   88h

Output:

CF   Carry Flag   Non-Carry - indicates no error.

AX   Memory Count   Number of contiguous KB above 1
MB.

INT 13H disk I/O interrupts
===========================

In the PC world, living with the BIOS disk interface is definitely a nightmare. This section documents how awful the chaos is and how GRUB deals with the BIOS disks.

CHS addressing and LBA addressing
---------------------------------

CHS --- Cylinder/Head/Sector --- is the traditional way to address sectors on a disk. There are at least two types of CHS addressing; the CHS that is used at the INT 13H interface and the CHS that is used at the ATA device interface. In the MFM/RLL/ESDI and early ATA days the CHS used at the INT 13H interface was the same as the CHS used at the device interface.

Today we have CHS translating BIOS types that can use one CHS at the INT 13H interface and a different CHS at the device interface. These two types of CHS will be called the logical CHS or L-CHS and the physical CHS or P-CHS in this section. L-CHS is the CHS used at the INT 13H interface and P-CHS is the CHS used at the device interface.

The L-CHS used at the INT 13 interface allows up to 256 heads, up to 1024 cylinders and up to 63 sectors. This allows support of up to 8GB drives. This scheme started with either ESDI or SCSI adapters many years ago.

The P-CHS used at the device interface allows up to 16 heads up to 65535 cylinders, and up to 63 sectors. This allows access to 2^28 sectors (136GB) on an ATA device.  When a P-CHS is used at the INT 13H interface it is limited to 1024 cylinders, 16 heads and 63 sectors. This is where the old 528MB limit originated.

LBA --- Logical Block Address --- is another way of addressing sectors that uses a simple numbering scheme starting with zero as the address of the first sector on a device. The ATA standard requires that cylinder 0, head 0, sector 1 address the same sector as addressed by LBA 0. LBA addressing can be used at the ATA interface if the ATA device supports it. LBA addressing is also used at the INT 13H interface by the AH=4xH read/write calls.

ATA devices may also support LBA at the device interface. LBA allows access to approximately 2^28 sectors (137GB) on an ATA device.

A SCSI host adapter can convert a L-CHS directly to an LBA used in the SCSI read/write commands. On a PC today, SCSI is also limited to 8GB when CHS addressing is used at the INT 13H interface.

First, all OS's that want to be co-resident with another OS (and that is all of the PC based OS's that I know of) must use INT 13H to determine the capacity of a hard disk. And that capacity information must be determined in L-CHS mode. Why is this?  Because:

 1. FDISK and the partition tables are really L-CHS based.

 2. MS/PC DOS uses INT 13H AH=02H and AH=03H to read and write the disk and these BIOS calls are L-CHS based.

 3. The boot processing done by the BIOS is all L-CHS based.

During the boot processing, all of the disk read accesses are done in L-CHS mode via INT 13H and this includes loading the first of the OS's kernel code or boot manager's code.

Second, because there can be multiple BIOS types in any one system, each drive may be under the control of a different type of BIOS. For example, drive 80H (the first hard drive) could be controlled by the original system BIOS, drive 81H (the second drive) could be controlled by a option ROM BIOS and drive 82H (the third drive) could be controlled by a software driver. Also, be aware that each drive could be a different type, for example, drive 80H could be an MFM drive, drive 81H could be an ATA drive, drive 82H could be a SCSI drive.

Third, not all OS's understand or use BIOS drive numbers greater than 81H. Even if there is INT 13H support for drives 82H or greater, the OS may not use that support.

Fourth, the BIOS INT 13H configuration calls are:

AH=08H, Get Drive Parameters
     This call is restricted to drives up to 528MB without CHS translation and to drives up to 8GB with CHS translation. For older BIOS with no support for >1024 cylinders or >528MB, this call returns the same CHS as is used at the ATA interface (the P-CHS). For newer BIOS's that do support >1024 cylinders or >528MB, this call returns a translated CHS (the L-CHS). The CHS returned by this call is used by FDISK to build partition records.

AH=41H, Get BIOS Extensions Support
     This call is used to determine if the IBM/Microsoft Extensions or if the Phoenix Enhanced INT 13H calls are supported for the BIOS drive number.

AH=48H, Extended Get Drive Parameters
     This call is used to determine the CHS geometries, LBA information and other data about the BIOS drive number.

An ATA disk must implement both CHS and LBA addressing and must at any given time support only one P-CHS at the device interface. And, the drive must maintain a strick relationship between the sector addressing in CHS mode and LBA mode. Quoting the ATA-2 document:

     LBA = ( (cylinder * heads_per_cylinder + heads )
             * sectors_per_track ) + sector - 1

     where heads_per_cylinder and sectors_per_track are the current
     translation mode values.

This algorithm can also be used by a BIOS or an OS to convert a L-CHS to an LBA.

This algorithm can be reversed such that an LBA can be converted to a CHS:

     cylinder = LBA / (heads_per_cylinder * sectors_per_track)
         temp = LBA % (heads_per_cylinder * sectors_per_track)
         head = temp / sectors_per_track
       sector = temp % sectors_per_track + 1

While most OS's compute disk addresses in an LBA scheme, an OS like DOS must convert that LBA to a CHS in order to call INT 13H.

The basic problem is that there is no requirement that a CHS translating BIOS followed these rules. There are many other algorithms that can be implemented to perform a similar function. Today, there are at least two popular implementions: the Phoenix implementation (described above) and the non-Phoenix implementations. Because a protected mode OS that does not want to use INT 13H must implement the same CHS translation algorithm. If it doesn't, your data gets scrambled.

In the perfect world of tomorrow, maybe only LBA will be used. But today we are faced with the following problems:

  * Some drives >528MB don't implement LBA.

  * Some drives are optimized for CHS and may have lower performance when given commands in LBA mode. Don't forget that LBA is something new for the ATA disk designers who have worked very hard for many years to optimize CHS address handling. And not all drive designs require the use of LBA internally.

  * The L-CHS to LBA conversion is more complex and slower than the bit shifting L-CHS to P-CHS conversion.

  * DOS, FDISK and the MBR are still CHS based --- they use the CHS returned by INT 13H AH=08H.  Any OS that can be installed on the same disk with DOS must understand CHS addressing.

  * The BIOS boot processing and loading of the first OS kernel code is done in CHS mode --- the CHS returned by INT 13H AH=08H is used.

  * Microsoft has said that their OS's will not use any disk capacity that can not also be accessed by INT 13H AH=0xH.

These are difficult problems to overcome in today's industry environment. The result: chaos.

INT 13H, AH=0xh interrupt call
------------------------------

Real mode only. These functions are the traditional CHS mode disk interface. GRUB calls them only if LBA mode is not available.

INT 13H, AH=02h reads sectors into memory.

Input:

AH   02h

AL   The number of sectors to read (must be non-zero).

CH   Low 8 bits of cylinder number.

CL   Sector number in bits 0-5, and high 2 bits of
cylinder number in bits 6-7.

DH   Head number.

DL   Drive number (bit 7 set for hard disk).

ES:BX   Data buffer.

Output:

CF   Set on error.

AH   Status.

AL   The number of sectors transferred (only valid if CF
set for some BIOSes).

INT 13H, AH=03h writes disk sectors.

Input:

AH   03h

AL   The number of sectors to write (must be non-zero).

CH   Low 8 bits of cylinder number.

CL   Sector number in bits 0-5, and high 2 bits of
cylinder number in bits 6-7.

DH   Head number.

DL   Drive number (bit 7 set for hard disk).

ES:BX   Data buffer.

Output:

CF   Set on error.

AH   Status.

AL   The number of sectors transferred (only valid if CF
set for some BIOSes).

INT 13H, AH=08h returns drive parameters. For systems predating the IBM PC/AT, this call is only valid for hard disks.

Input:

AH   08h

DL   Drive number (bit 7 set for hard disk).

Output:

CF   Set on error.

AH   0.

AL   0 on at least some BIOSes.

BL   Drive type (AT/PS2 floppies only).

CH   Low 8 bits of maximum cylinder number.

CL   Maximum sector number in bits 0-5, and high 2 bits
of maximum cylinder number in bits 6-7.

DH   Maxiumum head number.

DL   The number of drives.

ES:DI   Drive parameter table (floppies only).

GRUB does not use this call for floppies, but attempts to read the first sector from the last head of the last cylinder to determine the maximum head number and the maximum cylinder number.

INT 13H, AH=4xh interrupt call
------------------------------

Real mode only. These functions are IBM/MS INT 13 Extensions to support LBA mode. GRUB uses them if available so that it can read/write over 8GB area.

INT 13, AH=41h checks if LBA is supported.

Input:

AH   41h.

BX   55AAh.

DL   Drive number.

Output:

CF   Set on error.

AH   Major version of extensions (01h for 1.x, 20h for
2.0 / EDD-1.0, 21h for 2.1 / EDD-1.1 and 30h for EDD-3.0) if successful,
otherwise 01h (the error code of invalid function).

BX   AA55h if installed.

AL   Internal use.

CX   API subset support bitmap (see below).

DH   Extension version.

The bitfields for the API subset support bitmap are:

Bit(s)   Description

0   Extended disk access functions (AH=42h-44h, 47h, 48h)
supported.

1   Removable drive controller functions (AH=45h, 46h, 48h,
49h, INT 15H, AH=52h) supported.

2   Enhanced disk drive (EDD) functions (AH=48h, 4Eh)
supported.

3-15   Reserved (0).

INT 13, AH=42h reads sectors into memory.

Input:

AH   42h.

DL   Drive number.

DS:SI   Disk Address Packet (see below).

Output:

CF   Set on error.

AH   0 if successful, otherwise error code.

The format of Disk Address Packet is:

Offset (hex)   Size (byte)   Description

00   1   10h (The size of packet).

01   1   Reserved (0).

02   2   The number of blocks to transfer (max 007F for
Phoenix EDD).

04   4   Transfer buffer (SEGMENT:OFFSET).

08   8   Starting absolute block number.

INT 13, AH=43h writes disk sectors.

Input:

AH   43h.

AL   Write flags (In version 1.0 and 2.0, bit 0 is the
flag for verify write and other bits are reserved (0). In version
2.1, 00h and 01h indicates write without verify, and 02h indicates
write with verify.

DL   Drive number.

DS:SI   Disk Address Packet (see above).

Output:

CF   Set on error.

AH   0 if successful, otherwise error code.

INT 13, AH=48h returns drive parameters. GRUB only makes use of the total number of sectors, and ignore the CHS information, because only L-CHS makes sense. See CHS Translation, for more information.

Input:

AH   48h.

DL   Drive number.

DS:SI   Buffer for drive parameters (see below).

Output:

CF   Set on error.

AH   0 if successful, otherwise error code.

The format of drive parameters is:

Offset (hex)   Size (byte)   Description

00   2   The size of buffer. Before calling this function,
set to the maximum buffer size, at least 1Ah. The size actually filled
is returned (1Ah for version 1.0, 1Eh for 2.x and 42h for 3.0).

02   2   Information flags (see below).

04   4   The number of physical cylinders.

08   4   The number of physical heads.

0C   4   The number of physical sectors per track.

10   8   The total number of sectors.

18   2   The bytes per sector.

v2.0 and later

1A   4   EDD configuration parameters.

v3.0

1E   2   Signature BEDD to indicate presence of Device Path
information.

20   1   The length of Device Path information, including
signature and this byte (24h for version 3.0).

21   3   Reserved (0).

24   4   ASCIZ name of host bus (ISA or PCI).

28   8   ASCIZ name of interface type (ATA,
ATAPI, SCSI, USB, 1394 or FIBRE).

30   8   Interface Path.

38   8   Device Path.

40   1   Reserved (0).

41   1   Checksum of bytes 1Eh-40h (2's complement of sum,
which makes the 8 bit sum of bytes 1Eh-41h equal to 00h).

The information flags are:

Bit(s)   Description

0   DMA boundary errors handles transparently.

1   CHS information is valid.

2   Removable drive.

3   Write with verify supported.

4   Drive has change-line support (required if drive is
removable).

5   Drive can be locked (required if drive is removable).

6   CHS information set to maximum supported values, not
current media.

7-15   Reserved (0).

The structure of Master Boot Record
===================================

A Master Boot Record (MBR) is the sector at cylinder 0, head 0, sector 1 of a hard disk. A MBR-like structure must be created in each of partitions by the FDISK program.

At the completion of your system's Power On Self Test (POST), INT 19H is called. Usually INT 19 tries to read a boot sector from the first floppy drive (Which drive is read first depends on your BIOS settings.). If a boot sector is found on the floppy disk, that boot sector is read into memory at location 0000:7C00 and INT 19H jumps to memory location 0000:7C00. However, if no boot sector is found on the first floppy drive, INT 19H tries to read the MBR from the first hard drive. If an MBR is found it is read into memory at location 0000:7C00 and INT 19H jumps to memory location 0000:7C00. The small program in the MBR will atempt to locate an active (bootable) partition in its partition table (This behavior is DOS MBR's, and GRUB ignores the active flag.). The small program in the boot sector must locate the first part of the operating system's kernel loader program (or perhaps the kernel itself or perhaps a boot manager program) and read that into memory.

INT 19H is also called when the CTRL-ALT-DEL keys are used. On most systems, CTRL-ALT-DEL causes an short version of the POST to be executed before INT 19H is called.

The stuff is:

Offset 0000
     The address where the MBR code starts.

Offset 01BE
     The address where the partition table starts (see Partition table).

Offset 01FE
     The signature, AA55.

However, the first 62 bytes of a boot sector are known as the BIOS Parameter Block (BPB), so GRUB cannot use these bytes for its own purpose.

If an active partition is found, that partition's boot record is read into 0000:7C00 and the MBR code jumps to 0000:7C00 with SI pointing to the partition table entry that describes the partition being booted. The boot record program uses this data to determine the drive being booted from and the location of the partition on the disk.

The first byte of an active partition table entry is 80. This byte is loaded into the DL register before INT 13H is called to read the boot sector. When INT 13H is called, DL is the BIOS device number. Because of this, the boot sector read by this MBR program can only be read from BIOS device number 80 (the first hard disk). This is one of the reasons why it is usually not possible to boot from any other hard disk.

The format of partition table
=============================

Overview the partition table
----------------------------

FDISK creates all partition records (sectors). The primary purpose of a partition record is to hold a partition table. The rules for how FDISK works are unwritten but so far most FDISK programs seem to follow the same basic idea.

First, all partition table records (sectors) have the same format. This includes the partition table record at cylinder 0, head 0, sector 1 -- what is known as the Master Boot Record (MBR). The last 66 bytes of a partition table record contain a partition table and a 2 byte signature. The first 446 bytes of these sectors usually contain a program but only the program in the MBR is ever executed (so extended partition table records could contain something other than a program in the first 466 bytes). For more information, see MBR.

Second, extended partitions are nested inside one another and extended partition table records form a linked list. I will attempt to show this in a diagram at Partition entry format.

Each partition table entry is 16 bytes and contains things like the start and end location of a partition in CHS, the start in LBA, the size in sectors, the partition type and the active flag. Older versions of FDISK may compute incorrect LBA or size values. And when your computer boots itself, only the CHS fields of the partition table entries are used (another reason LBA doesn't solve the >528MB problem). The CHS fields in the partition tables are in L-CHS format, see CHS Translation.

The list of the type code
-------------------------

There is no central clearing house to assign the codes used in the one byte type field. But codes are assigned (or used) to define most every type of file system that anyone has ever implemented on the x86 PC: 12-bit FAT, 16-bit FAT, HPFS, NTFS, etc. Plus, an extended partition also has a unique type code.

In the FDISK program sfdisk, the following list is assumed:

00
     Empty

01
     DOS 12-bit FAT

02
     XENIX /

03
     XENIX /usr

04
     DOS 16-bit FAT <32M

05
     DOS Extended

06
     DOS 16-bit FAT >=32M

07
     HPFS / NTFS

08
     AIX boot or SplitDrive

09
     AIX data or Coherent

0A
     OS/2 Boot Manager

0B
     Windows95 FAT32

0C
     Windows95 FAT32 (LBA)

0E
     Windows95 FAT16 (LBA)

0F
     Windows95 Extended (LBA)

10
     OPUS

11
     Hidden DOS FAT12

12
     Compaq diagnostics

14
     Hidden DOS FAT16

16
     Hidden DOS FAT16 (big)

17
     Hidden HPFS/NTFS

18
     AST Windows swapfile

24
     NEC DOS

3C
     PartitionMagic recovery

40
     Venix 80286

41
     Linux/MINIX (sharing disk with DRDOS)

42
     SFS or Linux swap (sharing disk with DRDOS)

43
     Linux native (sharing disk with DRDOS)

50
     DM (disk manager)

51
     DM6 Aux1 (or Novell)

52
     CP/M or Microsoft SysV/AT

53
     DM6 Aux3

54
     DM6

55
     EZ-Drive (disk manager)

56
     Golden Bow (disk manager)

5C
     Priam Edisk (disk manager)

61
     SpeedStor

63
     GNU Hurd or Mach or Sys V/386 (such as ISC UNIX) (But the reason why they decided that 63 means GNU Hurd is not known. Do not use 63 for GNU Hurd.)

64
     Novell Netware 286

65
     Novell Netware 386

70
     DiskSecure Multi-Boot

75
     PC/IX

77
     QNX4.x

78
     QNX4.x 2nd part

79
     QNX4.x 3rd part

80
     MINIX until 1.4a

81
     MINIX / old Linux

82
     Linux swap

83
     Linux native (This is not true. Use 83 for ext2fs even if the owner OS is GNU/Hurd.)

84
     OS/2 hidden C: drive

85
     Linux extended

86
     NTFS volume set

87
     NTFS volume set

93
     Amoeba

94
     Amoeba BBT

A0
     IBM Thinkpad hibernatoin

A5
     BSD/386

A7
     NeXTSTEP 486

B7
     BSDI fs

B8
     BSDI swap

C1
     DRDOS/sec (FAT-12)

C4
     DRDOS/sec (FAT-16, < 32M)

C6
     DRDOS/sec (FAT-16, >= 32M)

C7
     Syrinx

DB
     CP/M or Concurrent CP/M or Concurrent DOS or CTOS

E1
     DOS access or SpeedStor 12-bit FAT extended partition

E3
     DOS R/O or SpeedStor

E4
     SpeedStor 16-bit FAT extended partition < 1024 cyl.

F1
     SpeedStor

F2
     DOS 3.3+ secondary

F4
     SpeedStor large partition

FE
     SpeedStor >1024 cyl. or LANstep

FF
     Xenix Bad Block Table

The format of the table entry
-----------------------------

The 16 bytes of a partition table entry are used as follows:

         +--- Bit 7 is the active partition flag, bits 6-0 are zero.
         |
         |    +--- Starting CHS in INT 13 call format.
         |    |
         |    |      +--- Partition type byte.
         |    |      |
         |    |      |    +--- Ending CHS in INT 13 call format.
         |    |      |    |
         |    |      |    |        +-- Starting LBA.
         |    |      |    |        |
         |    |      |    |        |       +-- Size in sectors.
         |    |      |    |        |       |
         v <--+--->  v <--+-->     v       v

        0  1  2  3  4  5  6  7  8 9 A B  C D E F
        DH DL CH CL TB DL CH CL LBA..... SIZE....

        80 01 01 00 06 0e be 94 3e000000 0c610900  1st entry

        00 00 81 95 05 0e fe 7d 4a610900 724e0300  2nd entry

        00 00 00 00 00 00 00 00 00000000 00000000  3rd entry

        00 00 00 00 00 00 00 00 00000000 00000000  4th entry

Bytes 0-3 are used by the small program in the Master Boot Record to read the first sector of an active partition into memory. The DH, DL, CH and CL above show which x86 register is loaded when the MBR program calls INT 13H AH=02h to read the active partition's boot sector. For more information, see MBR.

These entries define the following partitions:

 1. The first partition, a primary partition DOS FAT, starts at CHS 0H,1H,1H (LBA 3EH) and ends at CHS 294H,EH,3EH with a size of 9610CH sectors.

 2. The second partition, an extended partition, starts at CHS 295H,0H,1H (LBA 9614AH) and ends at CHS 37DH,EH,3EH with a size of 34E72H sectors.

 3. The third and fourth table entries are unused.

Some basic rules for Partition table.
-------------------------------------

Keep in mind that there are no written rules and no industry standards on how FDISK should work but here are some basic rules that seem to be followed by most versions of FDISK:

 1. In the MBR there can be 0-4 primary partitions, OR, 0-3 primary partitions and 0-1 extended partition entry.

 2. In an extended partition there can be 0-1 secondary partition entries and 0-1 extended partition entries.

 3. Only 1 primary partition in the MBR can be marked active at any given time.

 4. In most versions of FDISK, the first sector of a partition will be aligned such that it is at head 0, sector 1 of a cylinder. This means that there may be unused sectors on the track(s) prior to the first sector of a partition and that there may be unused sectors following a partition table sector.

     For example, most new versions of FDISK start the first partition (primary or extended) at cylinder 0, head 1, sector 0. This leaves the sectors at cylinder 0, head 0, sectors 2...n as unused sectors. This same layout may be seen on the first track of an extended partition. See example 2 below.

     Also note that software drivers like Ontrack's Disk Manager depend on these unused sectors because these drivers will hide their code there (in cylinder 0, head 0, sectors 2...n). This is also a good place for boot sector virus programs to hang out.

 5. The partition table entries (slots) can be used in any order. Some versions of FDISK fill the table from the bottom up and some versions of FDISK fill the table from the top down. Deleting a partition can leave an unused entry (slot) in the middle of a table.

 6. And then there is the hack that some newer OS's (OS/2 and Linux) use in order to place a partition spanning or passed cylinder 1024 on a system that does not have a CHS translating BIOS. These systems create a partition table entry with the partition's starting and ending CHS information set to all FFH. The starting and ending LBA information is used to describe the location of the partition. The LBA can be converted back to a CHS --- most likely a CHS with more than 1024 cylinders. Since such a CHS can't be used by the system BIOS, these partitions can not be booted or accessed until the OS's kernel and hard disk device drivers are loaded.  It is not known if the systems using this hack follow the same rules for the creation of these type of partitions.

There are no written rules as to how an OS scans the partition table entries so each OS can have a different method. For DOS, this means that different versions could assign different drive letters to the same FAT file system partitions.

The generic interface for the fs code
=====================================

For any particular partition, it is presumed that only one of the normal filesystems such as FAT, FFS, or ext2fs can be used, so there is a switch table managed by the functions in disk_io.c. The notation is that you can only mount one at a time.

The blocklist filesystem has a special place in the system. In addition to the normal filesystem (or even without one mounted), you can access disk blocks directly (in the indicated partition) via the blocklist notation. Using the blocklist filesystem doesn't effect any other filesystem mounts.

The variables which can be read by the filesystem backend are:

current_drive
     Contain the current BIOS drive number (numbered from 0, if a floppy, and numbered from 0x80, if a hard disk).

current_slice
     Contain the current partition length, in sectors.

print_possibilities
     True when the dir function should print the possible completions of a file, and false when it should try to actually open a file of that name.

FSYS_BUF
     Point to a filesystem buffer which is 32K in size, to use in any way which the filesystem backend desires.

The variables which need to be written by a filesystem backend are:

filepos
     Should be the current position in the file.

     Caution: the value of FILEPOS can be changed out from under the filesystem code in the current implementation. Don't depend on it being the same for later calls into the back-end code!

filemax
     Should be the length of the file.

debug_fs_func
     Should be set to the value of debug_fs only during reading of data for the file, not any other fs data, inodes, FAT tables, whatever, then set to NULL at all other times (it will be NULL by default). If this isn't done corrently, then the testload= and install= commands won't work correctly.

The functions expected to be used by the filesystem backend are:

devread
     Only read sectors from within a partition. Sector 0 is the first sector in the partition.

grub_read
     If the backend uses the block-list code (like the FAT filesystem backend does), then grub_read can be used, after setting BLOCK_FILE to 1.

The functions expected to be defined by the filesystem backend are described at least moderately in the file filesys.h. Their usage is fairly evident from their use in the functions in disk_io.c, look for the use of the FSYS_TABLE array.

Caution: The semantics are such that then mounting the filesystem, presume the filesystem buffer FSYS_BUF is corrupted, and (re-)load all important contents. When opening and reading a file, presume that the data from the mount is available, and doesn't get corrupted by the open/read (i.e. multiple opens and/or reads will be done with only one mount if in the same filesystem).