| \input texinfo @c -*-texinfo-*- |
| @setfilename grub.info |
| @include version.texi |
| |
| @c Unify all our little indices for now. |
| @syncodeindex fn cp |
| @syncodeindex vr cp |
| @syncodeindex ky cp |
| @syncodeindex pg cp |
| @syncodeindex tp cp |
| |
| @dircategory Kernel |
| @direntry |
| * GRUB: (grub). The GRand Unified Bootloader. |
| @end direntry |
| |
| @ifinfo |
| Copyright @copyright{} 1996 Erich Boleyn |
| Copyright @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. |
| |
| @ignore |
| Permission is granted to process this file through TeX and print the |
| results, provided the printed document carries a copying permission |
| notice identical to this one except for the removal of this paragraph |
| (this paragraph not being relevant to the printed manual). |
| |
| @end ignore |
| |
| 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. |
| @end ifinfo |
| |
| @c @setchapternewpage odd |
| @settitle GRUB Manual |
| @titlepage |
| @finalout |
| @title The GRUB Manual |
| @author Gordon Matzigkeit |
| @author OKUJI Yoshinori |
| @page |
| |
| @vskip 0pt plus 1filll |
| Copyright @copyright{} 1996 Erich Boleyn |
| Copyright @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. |
| @end titlepage |
| |
| @c The Top node should not appear in TeX. |
| @ifnottex |
| |
| @node Top |
| @top GRUB |
| |
| This file documents GNU GRUB, the Grand Unified Bootloader. This |
| edition documents version @value{VERSION}. |
| @end ifnottex |
| |
| |
| @menu |
| * Introduction:: Capturing the spirit of GRUB. |
| * Installing:: How to install GRUB on your computer. |
| * Using:: Booting your operating system. |
| * Filesystems:: Filesystem syntax and semantics. |
| * Troubleshooting:: Error messages produced by GRUB. |
| * Stage 2 Emulator:: The @command{grub} command. |
| * Hacking:: Implementation details. |
| * Index:: Index. |
| |
| @detailmenu |
| --- The Detailed Node Listing --- |
| |
| Introduction |
| |
| * History:: From maggot to house fly. |
| * Features:: How GRUB is different. |
| * Role of a bootloader:: Judging a system by its bootloader. |
| |
| How to install GRUB on your computer |
| |
| * Boot floppy:: Creating a GRUB boot floppy. |
| * Automated install:: Installation via @code{install=}. |
| |
| Booting your operating system |
| |
| * Command line:: The flexible command-line interface. |
| * Menu:: The simple menu interface. |
| * Menu entry editor:: Editing a menu entry. |
| * Commands:: The list of available commands. |
| |
| Filesystem syntax and semantics |
| |
| * Device syntax:: How to specify devices. |
| * Filename syntax:: How to specify files. |
| |
| Error messages reported by GRUB |
| |
| * Stage1 errors:: Errors reported by the Stage 1. |
| * Stage1.5 errors:: Errors reported by the Stage 1.5. |
| * Stage2 errors:: Errors reported by the Stage 2. |
| |
| The @command{grub} command |
| |
| * Basic usage:: How to use the Stage 2 emulator. |
| * Installation under UNIX:: How to install GRUB via @command{grub}. |
| |
| Implementation details |
| |
| * Memory map:: The memory map of the various |
| components. |
| * Embedded data:: Embedded variables in GRUB. |
| * Memory detection:: How to detect all installed @sc{ram}. |
| * Low-level disk I/O:: INT 13H disk I/O interrupts. |
| * MBR:: The structure of Master Boot Record. |
| * Partition table:: The format of partition table. |
| * Filesystem interface:: The generic interface for the fs code. |
| |
| @end detailmenu |
| @end menu |
| |
| |
| @node Introduction |
| @chapter Introduction |
| |
| Briefly, a @dfn{bootloader} is the first software program that runs when |
| a computer starts. It is responsible for loading and transferring |
| control to the operating system @dfn{kernel} software (such as the Linux |
| or GNU Hurd kernel). The kernel, in turn, initializes the rest of the |
| operating system (usually GNU). |
| |
| @menu |
| * History:: From maggot to house fly. |
| * Features:: How GRUB is different. |
| * Role of a bootloader:: Judging a system by its bootloader. |
| @end menu |
| |
| |
| @node History |
| @section 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 |
| (@pxref{Top, Multiboot Standard, Motivation, multiboot, 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 soon 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.@footnote{The repository is |
| @code{:pserver:anoncvs@@anoncvs.gnu.org:/gd/gnu/anoncvsroot}, module |
| @code{grub}. Just hit return when prompted for a password.} |
| |
| |
| @node Features |
| @section GRUB features |
| |
| The primary requirement for GRUB is that it be compliant with the |
| @dfn{Multiboot Standard}, which is described in @ref{Top, Multiboot |
| Standard, Motivation, multiboot, The Multiboot Standard}. |
| |
| The other goals, listed in approximate order of importance, are: |
| |
| @itemize |
| @item |
| Basic functions must be straightforward for end-users. |
| |
| @item |
| Rich functionality to support kernel experts and designers. |
| |
| @item |
| Backward compatibility for booting FreeBSD, NetBSD, OpenBSD, and |
| Linux. Proprietary kernels (such as DOS, Windows NT, and OS/2) are |
| supported via a chain-loading function. |
| @end itemize |
| |
| Except for specific compatibility modes (chain-loading and the Linux |
| @dfn{piggyback} format), all kernels will be started in much the same |
| state as in the Multiboot Standard. Only kernels 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 require all the features that |
| GRUB supports): |
| |
| @table @asis |
| @item Multiple Executable Formats |
| Supports many of the @dfn{a.out} variants plus @dfn{ELF}. Symbol |
| tables are also loaded. |
| |
| @item Supports Non-Multiboot Kernels |
| Supports many of the various free 32-bit kernels that lack Multiboot |
| compliance (primarily FreeBSD, NetBSD, OpenBSD, and |
| Linux). Chain-loading of other bootloaders is also supported. |
| |
| @item Loads Multiples Modules |
| GRUB fully supports the Multiboot feature of loading multiple modules. |
| |
| @item Configuration File |
| Supports a human-readable text configuration file with preset boot |
| commands. The list of commands (@pxref{Commands}) are a superset of |
| those supported on the command line. An example command file is provided |
| in @file{docs/menu.lst} in the source tree. |
| |
| @item 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 |
| entries, and the current implementation has space for several hundred. |
| |
| @item Flexible Command Line Interface |
| A fairly flexible command line interface, accessible from the menu, |
| is available to edit any preset commands, or write a new boot command |
| set from scratch. If no command file is present, GRUB drops to |
| the command line. |
| |
| The list of commands (@pxref{Commands}) are a subset of those supported |
| for command files. Editing commands closely resemble the Bash command |
| line (@pxref{Command Line Editing, Bash, Command Line Editing, features, |
| Bash Features}), with @key{TAB}-completion of commands, devices, |
| partitions, and files in a directory depending on context. |
| |
| @item Multiple Filesystem Types |
| Supports multiple filesystem types transparently, plus a useful explicit |
| blocklist notation. The currently supported filesystem types are |
| @dfn{BSD FFS}, @dfn{DOS FAT}, and @dfn{Linux ext2fs}. |
| @xref{Filesystems}, for more information. |
| |
| @item Decompression Support |
| Can decompress files which were compressed by |
| @command{gzip}. This function is both automatic and transparent to the |
| user (i.e. all functions operate upon the uncompressed contents |
| of the specified files). This greatly |
| reduces file size and loading time, a particularly major |
| benefit for floppies.@footnote{There are a few pathological cases |
| where loading a very badly organized ELF kernel might take |
| longer, but in practice this never happens.} |
| |
| It is conceivable that some kernel modules should be loaded in a |
| compressed state, so a different module-loading command can be specified |
| to avoid uncompressing the modules. |
| |
| @item 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 of the root partition. |
| |
| @item Independent of Drive Geometry Translation |
| Unlike many other bootloaders, GRUB makes the particular drive |
| translation irrelevant. A drive installed and running |
| with one translation may be converted to another translation without any |
| adverse effects or changes in GRUB's configuration. |
| |
| @item Detects All Installed @sc{ram} |
| GRUB can generally find all the installed @sc{ram} on a PC-compatible |
| machine. It uses an advanced BIOS query technique for finding all |
| memory regions (@pxref{Memory detection}). As described on the Multiboot |
| Standard (@pxref{Top, Multiboot Standard, Motivation, multiboot, The |
| Multiboot Standard}), not all kernels make use of this information, but |
| GRUB provides it for those who do. |
| |
| @item Supports Logical Block Address Mode |
| In traditional disk calls (called @dfn{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 |
| standard interface used in all machines. However, some newer machines |
| have the a new interface, Logical Block Address (@dfn{LBA}) mode. GRUB |
| automatically detects if LBA mode is available and uses it if |
| available. In LBA mode, GRUB can access the entire disk. |
| @end table |
| |
| Future directions might include an internal programming language for |
| supporting richer sets of boot options with control statements (which |
| would make GRUB its own kind of kernel). Support for non-PC hardware |
| architectures is also planned.@footnote{There is already a port to the |
| NEC PC-98xx series. See |
| @url{http://www.kuis.kyoto-u.ac.jp/~kmc/proj/linux98/arch/i386/boot/grub98/}, |
| for more information.} |
| |
| |
| @node Role of a bootloader |
| @section The role of a bootloader |
| |
| The following is a quotation from Gordon Matzigkeit, a GRUB fanatic: |
| |
| @quotation |
| 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 |
| @emph{bootloader} is the most important software of all. I used to |
| refer to the above systems as either ``LILO''@footnote{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@dots{} GRUB! |
| @end quotation |
| |
| We, the GRUB maintainers, do not (usually) encourage Gordon's level of |
| fanaticism, but it helps to remember that bootloaders deserve |
| recognition. We hope that you enjoy using GNU GRUB as much as we did |
| writing it. |
| |
| |
| @node Installing |
| @chapter How to install GRUB on your computer |
| |
| Due to the nature of a @dfn{bootloader}, you need to install GRUB on |
| bootable media, such as a floppy disk. The installation can be performed |
| by @code{dd} or @code{rawrite} for a boot floppy, or the @code{install=} |
| command at the GRUB command line (@pxref{Using}). |
| |
| @menu |
| * Boot floppy:: Creating a GRUB boot floppy. |
| * Automated install:: Installation via @code{install=}. |
| @end menu |
| |
| |
| @node Boot floppy |
| @section Creating a GRUB boot floppy |
| |
| @quotation |
| @strong{Caution:} This procedure will destroy any data currently stored |
| on the floppy. |
| @end quotation |
| |
| 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. If you want to use the menu interface, see |
| @ref{Automated install}. |
| |
| Under an UNIX-like operating system, such as GNU, use @code{dd} as |
| follows, where @file{/lib/grub/i386-pc} is the GRUB install directory |
| and @file{/dev/fd0} is the floppy device: |
| |
| @example |
| $ cd /lib/grub/i386-pc |
| $ dd if=stage1 of=/dev/fd0 bs=512 count=1 |
| 1+0 records in |
| 1+0 records out |
| $ dd if=stage2 of=/dev/fd0 bs=512 seek=1 |
| 67+1 records in |
| 67+1 records out |
| $ |
| @end example |
| |
| Under DOS-based systems, such as Windows, use @code{copy} and |
| @code{rawrite}: |
| |
| @example |
| copy /b stage1 + stage2 grub.raw |
| rawrite grub.raw a: |
| @end example |
| |
| @code{rawrite} is available as a part of the installation tools that |
| come with many GNU and GNU/Linux distributions. |
| |
| |
| @node Automated install |
| @section Installation via the @code{install=} command |
| |
| @quotation |
| @strong{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 @code{FDISK /MBR} from DOS). |
| @end quotation |
| |
| GRUB has a command called @code{install=} which is described in |
| @xref{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 (@pxref{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 @file{/boot/grub} directory (@file{\boot\grub} under DOS) |
| in the @dfn{install partition}. Place the GRUB @file{stage2} file, any |
| optional @file{stage1.5} files, and the configuration file |
| (@file{menu.lst}) in that directory. |
| |
| Now figure out how to use the @code{install=} command appropriately, and |
| you're done! |
| |
| Examples of how to use the @code{install=} command: |
| |
| @c FIXME: Gord stopped here |
| @itemize @bullet |
| @item |
| @strong{Make a hard disk bootable with GRUB's stage2 on PC partition |
| number 2:} Make a directory in the partition called @file{/boot/grub}, |
| place the @file{stage2} (and if desired, your configuration file called |
| @file{menu.lst}), then run the following command at GRUB's command line |
| (after booting from the GRUB floppy): |
| |
| @example |
| install= (fd0)+1 (hd0) (hd0,1)/boot/grub/stage2 0x8000 p |
| @end example |
| |
| This tells GRUB to grab the first sector of the floppy and use it as the |
| stage1, create a block-list using the file @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 @dfn{install |
| partition} in the first sector of the stage2 (the @samp{p} at the end), |
| then write the result to the first sector of the hard disk. |
| |
| @item |
| @strong{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: |
| |
| @example |
| install= (fd0)+1 d (fd0) (hd0,1)/boot/grub/stage2 0x8000 p |
| @end example |
| |
| The @samp{d} option near the beginning is what sets the @emph{forced} |
| loading from the disk where the stage2 was installed from. Also, the |
| @dfn{destination device} is changed to place the finished stage1 on the |
| floppy disk. |
| |
| @item |
| @strong{Same as above, but place the stage1.5 in the first cylinder of |
| the hard disk, and load the stage2 via the stage1.5:} Each of Stage 1.5s |
| supports only one filesystem, so choose a stage1.5 that supports the |
| filesystem where stage2 is located. Here it is assumed that the |
| filesystem is ext2fs. |
| |
| First, copy @file{e2fs_stage1_5} to the first cylinder after MBR |
| (@pxref{MBR}): |
| |
| @example |
| dd if=stage2/e2fs_stage1_5 of=/dev/hda bs=512 seek=1 |
| @end example |
| |
| Second, specify the stage2 argument in the block-list format: |
| |
| @example |
| install= (fd0)+1 (hd0) (hd0)1+1 0x2000 p (hd0,1)/boot/grub/stage2 |
| @end example |
| |
| @item |
| @strong{Installing from an @emph{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 @samp{a} partition on the second |
| hard disk, and setting the stage2's @dfn{configuration file} to |
| @file{(hd1,a)/grubdir/configfile}: |
| |
| @example |
| install= (hd0,1)/boot/grub/stage1 (hd1) (hd1,a)/boot/grub/stage2 0x8000 p /grubdir/configfile |
| @end example |
| @end itemize |
| |
| You can automate these steps by using a GRUB floppy with a filesystem |
| and a configuration file which contains entries such as: |
| |
| @example |
| # 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 |
| @end example |
| |
| @dots{} then have the install script continue from there after boot of |
| the OS. |
| |
| |
| @node Using |
| @chapter 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. |
| |
| @menu |
| * Command line:: The flexible command line interface. |
| * Menu:: The simple menu interface. |
| * Menu entry editor:: Editing a menu entry. |
| * Commands:: The list of available commands. |
| @end menu |
| |
| |
| @node Command line |
| @section 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 @footnote{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. |
| |
| @c The list of available keys should be listed in @table, and should be |
| @c explained exactly. Current explanation is obscure. |
| Cursor movement and editing of the text on the line can be done via a |
| subset of the functions available in the BASH shell |
| (@kbd{C-f} forward, @kbd{C-b} backward, @kbd{C-a} beginning of line, |
| @kbd{C-e} end of line, @kbd{C-k} delete to end, @kbd{C-u} delete to |
| beginning; the PC left and right arrow keys, @key{HOME}, @key{DEL}, and |
| @key{END} work as well). |
| |
| When typing commands interactively, if the cursor is before the @samp{=} |
| character in a command being typed, pressing the @key{TAB} key will |
| display a listing of the available commands, and if the cursor is after |
| the @samp{=} character, the @key{TAB} will provide a completion listing |
| of disks, partitions, and filenames depending on the context. |
| @c But I want to stop this stupid hack and provide more BASH-like |
| @c interface. I don't think commands ending with @samp{=} are |
| @c beautiful. |
| |
| |
| @node Menu |
| @section 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 @dfn{boot |
| configurations} to the user to choose from. Use the arrow keys to |
| select the entry of choice, then press @key{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 @dfn{boot configurations}, |
| respectively by pressing @key{c} or @key{e}. |
| |
| |
| @node Menu entry editor |
| @section 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 @key{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 @dfn{boot |
| configuration} with the changes (unless it was aborted via @key{ESC}, |
| and in that case the changes are thrown away). |
| |
| |
| @node Commands |
| @section 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: |
| |
| @enumerate |
| @item |
| The configuration file specific commands have to be used before any |
| others. |
| |
| @item |
| A multiboot kernel must be loaded before modules can be. |
| |
| @item |
| A kernel must be loaded before either the configuration file entry ends, |
| or any @samp{boot} command is issued in any case. |
| @end enumerate |
| |
| The semantics are as follows: |
| |
| @itemize @bullet |
| @item |
| The files @emph{must} be in plain-text format. |
| |
| @item |
| @samp{#} at the beginning of a line means it is a comment line in a |
| configuration file only. |
| |
| @item |
| Options are separated by spaces. |
| |
| @item |
| All numbers can be either decimal or hexadecimal. A hexadecimal number |
| must be preceded by @samp{0x}, and is case insensitive. |
| |
| @item |
| Extra options/text at the end of the line is ignored unless otherwise |
| specified. |
| |
| @item |
| Bad commands generally get included in the current entry being added to, |
| except before entries start, where they are ignored. |
| @end itemize |
| |
| Commands usable in configuration files only. |
| |
| @table @code |
| @item timeout= @var{sec} |
| Set a timeout, in @var{sec} seconds, before automatically booting the |
| default entry (normally the first entry defined). |
| |
| @item default= @var{num} |
| Set the default entry to entry number @var{num} (otherwise it is 0, the |
| first entry). |
| |
| @item fallback= @var{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 @var{num} entry (same numbering as the @code{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. |
| |
| @item password= @var{passwd} @var{new_config_file} |
| Disable all interactive editing control (menu entry editor and |
| command line). If the password @var{passwd} is entered, it loads the |
| @var{new_config_file} as a new config file and restarts the GRUB Stage |
| 2. |
| |
| @item title= @dots{} |
| 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. |
| @end table |
| |
| Commands usable in configuration files and interactively. |
| |
| @table @code |
| @item pause= @dots{} |
| 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. |
| |
| @item uppermem= @var{kbytes} |
| Force GRUB to ignore what it found during the autoprobe of the memory |
| available to the system, and to use @var{kbytes} as the number of |
| kilobytes of upper memory installed. Any address range maps of the |
| system are discarded. |
| |
| @strong{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 @sc{ram} on all new machines the author has ever heard of. It can |
| also be used for debugging purposes to lie to an OS. |
| |
| @item root= @var{device} [@var{hdbias}] |
| Set the current @dfn{root partition} to the device @var{device}, then |
| attempt to mount it to get the partition size (for passing the partition |
| descriptor in @code{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 @var{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 @samp{1} for @var{hdbias}. |
| |
| @item rootnoverify= @var{device} [@var{hdbias}] |
| Similar to @command{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 @command{root=} above which |
| derived from attempting the mount will NOT work correctly. |
| |
| @item chainloader= @var{file} |
| Load @var{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 @samp{+1}. |
| |
| @item kernel= @var{file} @dots{} |
| Attempt to load the primary boot image (Multiboot a.out or @sc{elf}, |
| Linux zImage or bzImage, FreeBSD-a.out, or NetBSD-a.out) from |
| @var{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 @dfn{kernel command line}. The module state is reset by |
| this (i.e. reload any modules). |
| |
| @item module= @var{file} @dots{} |
| 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 @dfn{module command line} |
| much like with the @command{kernel=} command. |
| |
| @item modulenounzip= @var{file} @dots{} |
| Exactly like @command{module=}, except that automatic decompress is |
| disabled. |
| |
| @item initrd= @var{file} @dots{} |
| Load an initial ramdisk for a Linux format boot image and set the |
| appropriate parameters in the Linux setup area in memory. |
| |
| @item install= @var{stage1_file} [d] @var{dest_dev} @var{file} @var{addr} [p] [@var{config_file}] |
| This command is fairly complex, and for detailed examples one should |
| look at @ref{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 |
| @command{install=} command). |
| |
| In slightly more detail, it will load @var{stage1_file}, validate that |
| it is a GRUB stage1 of the right version number, install block-list for |
| loading @var{file} (if the option @samp{d} is present, the stage1 will |
| always look for the actual disk @var{file} was installed on, rather than |
| using the booting drive) as a stage2 into memory at address |
| @var{addr} (for a stage1.5, an address of @samp{0x2000} should be |
| used, and for a stage2, an address of @samp{0x8000} should be used), |
| then write the completed stage1 to the first block of the device |
| @var{dest_dev}. If the options @samp{p} or @var{config_file} are |
| present, then it reads the first block of stage2, modifies it with the |
| values of the partition @var{file} was found on (for @samp{p}) or places |
| the string @var{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. |
| |
| @item 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 @emph{primary} |
| PC partitions. |
| |
| @item 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). |
| |
| @item color= @var{normal} [@var{highlight}] |
| Change the menu colors. The color @var{normal} is used for the normal |
| line in the menu, and the color @var{highlight} is used to highlight the |
| line where the cursor points to. If you omit @var{highlight}, then the |
| inverted color of @var{normal} is used for the highlighted line. You |
| must specify an integer for a color value, and the 0-3 bits represents |
| the foreground color, the 4-6 bits represents the background color, and |
| the 7 bit represents that the foreground blinks. |
| |
| These are the possible values and the meanings: |
| |
| @table @asis |
| @item 0 |
| black |
| |
| @item 1 |
| blue |
| |
| @item 2 |
| green |
| |
| @item 3 |
| cyan |
| |
| @item 4 |
| red |
| |
| @item 5 |
| magenta |
| |
| @item 6 |
| brown |
| |
| @item 7 |
| light gray |
| |
| @item |
| @strong{These below can be specified only for the foreground.} |
| |
| @item 8 |
| dark gray |
| |
| @item 9 |
| light blue |
| |
| @item A |
| light green |
| |
| @item B |
| light cyan |
| |
| @item C |
| light red |
| |
| @item D |
| light magenta |
| |
| @item E |
| yellow |
| |
| @item F |
| white |
| @end table |
| |
| The background is represented by 3 bits, so you cannot specify more than |
| 7 for it. |
| |
| This command can be used in the configuration file and on the |
| command line, so you may write something like this in your configuration |
| file: |
| |
| @example |
| # the default colors (light gray / blue, black / light gray) |
| color= 0x17 0x70 |
| |
| # change the colors |
| title= OS-BS like |
| color= 0x16 0x60 |
| @end example |
| |
| @item testload= @var{file} |
| Read the entire contents of @var{file} in several different ways and |
| compares them, to test the filesystem code. The output is somewhat |
| cryptic (see the @samp{T} subcommand of @command{syscmd=} below), but if |
| no errors are reported and the part right at the end which reads |
| @samp{i=@var{X}, filepos=@var{Y}} has @var{X} and @var{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. |
| |
| @item read= @var{addr} |
| Read a 32-bit unsigned value at address @var{addr} and displays it in |
| hex format. |
| |
| @item displaymem |
| Display what GRUB thinks the system address space map of the machine is, |
| including all regions of physical @sc{ram} installed. The |
| @dfn{upper/lower memory} thing GRUB has uses the standard BIOS |
| interface for the available memory in the first megabyte, or @dfn{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 |
| @dfn{upper memory} (the standard PC @dfn{upper memory} interface is |
| limited to reporting a maximum of 64MB). |
| |
| @item 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. |
| |
| @item 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 @samp{<@var{sector}, @var{byte_offset}, |
| @var{byte_len}>} for high-level reads inside a partition (so |
| @var{sector} is an offset from the start of the partition), and |
| @samp{[@var{sector}]} for low-level sector requests from the disk (so |
| @var{sector} is offset from the start of the disk). |
| |
| Filesystem test mode is turned off by any uses of the @command{install=} |
| or @command{testload=} commands. |
| |
| @item quit |
| Finish GRUB in the Stage 2 emulator @command{grub} (@pxref{Stage 2 |
| emulator}). This is just ignored in the native Stage 2. |
| @end table |
| |
| |
| @node Filesystems |
| @chapter 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. |
| |
| @menu |
| * Device syntax:: How to specify devices. |
| * Filename syntax:: How to specify files. |
| @end menu |
| |
| |
| @node Device syntax |
| @section How to specify devices |
| |
| The device syntax is like this: |
| |
| @example |
| @code{(@var{bios_device}[,@var{part_num}][,@var{bsd_subpart_letter}])} |
| @end example |
| |
| @samp{[]} means the parameter is optional. @var{bios_device} should be |
| either @samp{fd} or @samp{hd} followed by a digit, like @samp{fd0}. |
| But you can also set @var{bios_device} to a hexadecimal or a decimal, |
| which is a BIOS drive number, so these are equivalent: |
| |
| @example |
| (hd0) |
| (0x80) |
| (128) |
| @end example |
| |
| @var{part_num} represents the partition number of @var{bios_device}, |
| starting from zero, and @var{bsd_subpart_letter} represents the BSD |
| sub-partition, like @samp{a} or @samp{e}. |
| |
| A shortcut for specifying BSD sub-partitions is |
| @code{(@var{bios_device},@var{bsd_subpart_letter})}, in this case, GRUB |
| searches for the first PC partition containing BSD sub-partitions, then |
| finds the sub-partition @var{bsd_subpart_letter}. Here is an example: |
| |
| @example |
| (hd0,a) |
| @end example |
| |
| |
| @node Filename syntax |
| @section How to specify files |
| |
| There are two ways to specify files, @dfn{absolute pathname} and |
| @dfn{block-list}. |
| |
| Absolute pathname resembles a Unix absolute pathname. Use @samp{/} for |
| the directory separator but not @samp{\} like DOS. For example, |
| @samp{/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: |
| |
| @example |
| @code{1+100,200+1,300+300} |
| @end example |
| |
| 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. |
| |
| |
| @node Troubleshooting |
| @chapter Error messages reported by GRUB |
| |
| This chapter describes the meanings of the error messages reported by |
| GRUB when you encounter some troubles. |
| |
| @menu |
| * Stage1 errors:: Errors reported by the Stage 1. |
| * Stage1.5 errors:: Errors reported by the Stage 1.5. |
| * Stage2 errors:: Errors reported by the Stage 2. |
| @end menu |
| |
| |
| @node Stage1 errors |
| @section 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 @kbd{@key{CTRL}-@key{ALT}-@key{DEL}} will |
| reboot. |
| |
| The following is a comprehensive list of error messages for the Stage 1: |
| |
| @table @asis |
| @item 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. |
| |
| @item 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. |
| |
| @item Read Error |
| This error message will occur if a disk read error happens while trying |
| to read the Stage 2 or Stage 1.5. |
| |
| @item 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). |
| @end table |
| |
| |
| @node Stage1.5 errors |
| @section 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 @code{Error: @var{num}} and then halt. Pressing |
| @kbd{@key{CTRL}-@key{ALT}-@key{DEL}} will reboot. |
| |
| The error numbers correspond to the @ref{Stage2 errors} in the listed |
| sequence. |
| |
| |
| @node Stage2 errors |
| @section 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): |
| |
| @table @asis |
| @item 1 : 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 @ref{Filesystems}. |
| |
| @item 2 : 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. |
| |
| @item 3 : 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. |
| |
| @item 4 : Bad or incompatible header on compressed file |
| This error is returned if the file header for a supposedly compressed |
| file is bad. |
| |
| @item 5 : 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. |
| |
| @item 6 : 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. |
| |
| @item 7 : 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. |
| |
| @item 8 : Cannot boot without kernel loaded |
| This error is returned if GRUB is told to execute the boot sequence |
| without having a kernel to start. |
| |
| @item 9 : Unknown boot failure |
| This error is returned if the boot attempt did not succeed for reasons |
| which are unknown. |
| |
| @item 10 : 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. |
| |
| @item 11 : 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 @ref{Filesystems}. |
| |
| @item 12 : Invalid device requested |
| This error is returned if a device string is recognizable but does not |
| fall under the other device errors. |
| |
| @item 13 : 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). |
| |
| @item 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. |
| |
| @item 15 : File not found |
| This error is returned if the specified filename cannot be found, but |
| everything else (like the disk/partition info) is OK. |
| |
| @item 16 : 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. |
| |
| @item 17 : Cannot mount selected partition |
| This error is returned if the partition requested exists, but the |
| filesystem type cannot be recognized by GRUB. |
| |
| @item 18 : Selected cylinder exceeds maximum supported by BIOS |
| 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). |
| |
| @item 19 : 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. |
| |
| @item 20 : 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. |
| |
| @item 21 : Selected disk does not 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. |
| |
| @item 22 : 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. |
| |
| @item 23 : Error while parsing number |
| This error is returned if GRUB was expecting to read a number and |
| encountered bad data. |
| |
| @item 24 : 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). |
| |
| @item 25 : 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. |
| |
| @item 26 : Too many symbolic links |
| This error is returned if the link count is beyond the maximum |
| (currently 5), possibly the symbolic links are looped. |
| |
| @item 27 : 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. |
| |
| @item 28 : 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. |
| |
| @item 29 : 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. |
| @end table |
| |
| |
| @node Stage 2 emulator |
| @chapter The command @command{grub} |
| |
| This chapter documents the Stage 2 emulator @command{grub}. |
| |
| @menu |
| * Basic usage:: How to use the Stage 2 emulator. |
| * Installation under UNIX:: How to install GRUB via @command{grub}. |
| @end menu |
| |
| |
| @node Basic usage |
| @section Introduction into the Stage 2 emulator |
| |
| You can use the command @command{grub} for installing GRUB under your |
| operating systems and for a testbed when you add a new feature into GRUB |
| or when fix a bug. @command{grub} is almost the same as Stage 2, and, in |
| fact, it shares the source code with Stage 2 and you can use the same |
| commands in @command{grub}. It is emulated by replacing BIOS calls with |
| UNIX system calls and libc functions. |
| |
| The command @command{grub} accepts the following options: |
| |
| @table @code |
| @item --help |
| Print a summary of the command line options and exit. |
| |
| @item --version |
| Print the version number of GRUB and exit. |
| |
| @item --verbose |
| Print some verbose messages for debugging purpose. |
| |
| @item --config-file=@var{file} |
| Read the configuration file @var{file} instead of |
| @file{/boot/grub/menu.lst}. The format is the same as the normal GRUB |
| syntax. See @ref{Filesystems}, for more information. |
| |
| @item --boot-drive=@var{drive} |
| Set the stage2 @var{boot_drive} to @var{drive}. This argument should be |
| an integer (decimal, octal or hexadecimal). |
| |
| @item --install-partition=@var{par} |
| Set the stage2 @var{install_partition} to @var{par}. This argument |
| should be an hexadecimal number. |
| |
| @item --no-config-file |
| Do not use the configuration file even if it can be read. |
| |
| @item --no-curses |
| Do not use the curses interface even if it is available. |
| |
| @item --batch |
| This option has the same meaning as @samp{--no-config-file --no-curses}. |
| |
| @item --read-only |
| Disable writing to any disk. |
| |
| @item --hold |
| Wait until a debegger will attach. This option is useful when you want |
| to debug the startup code. |
| @end table |
| |
| |
| @node Installation under UNIX |
| @section How to install GRUB via @command{grub} |
| |
| The installation procedure is the same as under the @dfn{native} Stage |
| 2. See @ref{Automated install} for more information. The command |
| @command{grub}-specific information is described here. |
| |
| What you should be careful about is @dfn{buffer cache}. @command{grub} |
| makes use of raw devices instead of filesystems that your operating |
| systems serve, so there exists a potential problem that some cache |
| inconsistency may corrupt your filesystems. What we recommend is: |
| |
| @itemize @bullet |
| @item |
| If you can unmount drives to which GRUB may write any amount of data, |
| unmount them before running @command{grub}. |
| |
| @item |
| If a drive cannot be unmounted but can be mounted with the read-only |
| flag, mount it in read-only mode. That should be secure. |
| |
| @item |
| If a drive must be mounted with the read-write flag, make sure that any |
| activity is not being done on it during running the command |
| @command{grub}. |
| |
| @item |
| Reboot your operating system as soon as possible. Probably that is not |
| required if you follow these rules above, but reboot is the most secure |
| way. |
| @end itemize |
| |
| In addition, enter the command @command{quit} when you finish the |
| installation. That is @emph{very important} because @command{quit} makes |
| the buffer cache consistent. Do not push @key{C-c}. |
| |
| If you want to install GRUB non-interactively, specify @samp{--batch} |
| option in the command line. This is a simple example: |
| |
| @example |
| #!/bin/sh |
| |
| /sbin/grub --batch <<EOT 1>/dev/null 2>/dev/null |
| root= (hd0,0) |
| install= /boot/grub/stage1 (hd0) /boot/grub/stage2 0x8000 p |
| quit |
| EOT |
| @end example |
| |
| |
| @node Hacking |
| @chapter 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. |
| |
| @menu |
| * Memory map:: The memory map of the various |
| components. |
| * Embedded data:: Embedded variables in GRUB. |
| * Memory detection:: How to detect all installed @sc{ram}. |
| * Low-level disk I/O:: INT 13H disk I/O interrupts. |
| * MBR:: The structure of Master Boot Record. |
| * Partition table:: The format of partition table. |
| * Filesystem interface:: The generic interface for the fs code. |
| @end menu |
| |
| |
| @node Memory map |
| @section The memory map of various components |
| |
| GRUB is broken into 2 distinct components, or @dfn{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 |
| @footnote{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 @dfn{lazy loading}. Ask okuji for |
| more information.}: |
| |
| @table @asis |
| @item 0 to 4K-1 |
| Interrupt & BIOS area |
| |
| @item down from 8K-1 |
| 16-bit stack area |
| |
| @item 8K to (ebss1.5) |
| Stage 1.5 (optionally) loaded here by Stage 1 |
| |
| @item 0x7c00 to 0x7dff |
| Stage 1 loaded here by the BIOS |
| |
| @item 0x7e00 to 0x7e08 |
| Scratch space used by Stage 1 |
| |
| @item 32K to (ebss2) |
| Stage 2 loaded here by Stage 1.5 or Stage 1 |
| |
| @item (middle area) |
| Heap used for random memory allocation |
| |
| @item down from 416K-1 |
| 32-bit stack area |
| |
| @item 416K to 448K-1 |
| Filesystem info buffer (when reading a filesystem) |
| |
| @item 448K to 479.5K-1 |
| BIOS track read buffer |
| |
| @item 479.5K to 480K-1 |
| 512 byte fixed SCRATCH area |
| |
| @item 480K to 511K-1 |
| General storage heap |
| @end table |
| |
| |
| @node Embedded data |
| @section 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): |
| |
| @table @asis |
| @item @dfn{major version} (0x1bc) |
| This is the major version byte (should be 2). |
| |
| @item @dfn{minor version} (0x1bd) |
| This is the minor version byte (should be 0). |
| |
| @item @dfn{stage2 start address} (0x1b8) |
| This is the data for the @code{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@dots{} 16-bit instruction pointer and segment |
| registers shifted left by 4bits). |
| |
| A @dfn{stage1.5} should be loaded at address 0x2000, and a @dfn{stage2} |
| should be loaded at address 0x8000. Both use a CS of 0. |
| |
| @item @dfn{firstlist} (0x1b05) |
| This is the @emph{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 @code{firstlist} label. (note that it is always from the |
| beginning of the disk, and @emph{not} relative to the partition |
| boundaries) |
| |
| @item @dfn{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. |
| @end table |
| |
| In stage1.5 and stage2 (these are all defined at the beginning of |
| @file{shared_src/asm.S}): |
| |
| @table @asis |
| @item @dfn{major version} (0x6) |
| This is the major version byte (should be 2). |
| |
| @item @dfn{minor version} (0x7) |
| This is the minor version byte (should be 0). |
| |
| @item @dfn{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 @dfn{partition} part (the |
| @dfn{disk} part is ignored) of the data passed to an OS by a |
| Multiboot-compliant bootloader in the @dfn{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 @dfn{install_partition} 0xFF00FF, would then find the first |
| BSD-style PC partition, and use the @samp{a} partition in it, and |
| 0xFF01FF would use the @samp{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 @samp{no such partition} error will be |
| returned. |
| |
| If a @dfn{stage1.5} is being used, it will pass its own |
| @dfn{install_partition} to any @dfn{stage2} it loads, therefore |
| overwriting the one present in the @dfn{stage2}. |
| |
| @item @dfn{version_string} (0xc) |
| This is the @dfn{stage1.5} or @dfn{stage2} version string. It isn't |
| meant to be changed, simply easy to find. |
| |
| @item @dfn{config_file} (after the terminating zero of @dfn{version_string}) |
| This is the location, using the GRUB filesystem syntax, of the config |
| file. It will, by default, look in the @dfn{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 |
| @dfn{version_string}, it simply knows where @dfn{config_file} is, so the |
| beginning of the string cannot be moved after compile-time. This should |
| be OK, since the @dfn{version_string} is meant to be static. |
| |
| The code of stage2 starts again at offset 0x70, so @dfn{config_file} |
| string obviously can't go past there. Also, remember to terminate the |
| string with a 0. |
| @end table |
| |
| |
| @node Memory detection |
| @section How to detect all installed @sc{ram} |
| |
| There are three BIOS calls which return the information of installed |
| @sc{ram}. GRUB uses these calls to detect all installed @sc{ram} and |
| which address range should be treated by operating systems. |
| |
| @menu |
| * Query System Address Map:: INT 15H, AX=E820h interrupt call. |
| * Get Large Memory Size:: INT 15H, AX=E801h interrupt call. |
| * Get Extended Memory Size:: INT 15H, AX=88h interrupt call. |
| @end menu |
| |
| |
| @node Query System Address Map |
| @subsection INT 15H, AX=E820h interrupt call |
| |
| Real mode only. |
| |
| This call returns a memory map of all the installed @sc{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 (@pxref{Get Large Memory Size}) or INT 15h AH=88h |
| (@pxref{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: |
| |
| @multitable @columnfractions .15 .25 .6 |
| @item @code{EAX} @tab Function Code @tab E820h |
| |
| @item @code{EBX} @tab Continuation @tab Contains the @dfn{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, |
| @code{EBX} must contain zero. |
| |
| @item @code{ES:DI} @tab Buffer Pointer @tab Pointer to an Address Range |
| Descriptor structure which the BIOS is to fill in. |
| |
| @item @code{ECX} @tab Buffer Size @tab The length in bytes of the |
| structure passed to the BIOS. The BIOS will fill in at most @code{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. |
| |
| @item @code{EDX} @tab Signature @tab @samp{SMAP} - Used by the BIOS to |
| verify the caller is requesting the system map information to be |
| returned in @code{ES:DI}. |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.25 0.6 |
| @item @code{CF} @tab Carry Flag @tab Non-Carry - indicates no error |
| |
| @item @code{EAX} @tab Signature @tab @samp{SMAP} - Signature to verify |
| correct BIOS revision. |
| |
| @item @code{ES:DI} @tab Buffer Pointer @tab Returned Address Range |
| Descriptor pointer. Same value as on input. |
| |
| @item @code{ECX} @tab Buffer Size @tab Number of bytes returned by the |
| BIOS in the address range descriptor. The minimum size structure |
| returned by the BIOS is 20 bytes. |
| |
| @item @code{EBX} @tab Continuation @tab 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. |
| @end multitable |
| |
| The Address Range Descriptor Structure is: |
| |
| @multitable @columnfractions 0.25 0.3 0.45 |
| @item Offset in Bytes @tab Name @tab Description |
| |
| @item 0 @tab @dfn{BaseAddrLow} @tab Low 32 Bits of Base Address |
| |
| @item 4 @tab @dfn{BaseAddrHigh} @tab High 32 Bits of Base Address |
| |
| @item 8 @tab @dfn{LengthLow} @tab Low 32 Bits of Length in Bytes |
| |
| @item 12 @tab @dfn{LengthHigh} @tab High 32 Bits of Length in Bytes |
| |
| @item 16 @tab @dfn{Type} @tab Address type of this range |
| @end multitable |
| |
| The @dfn{BaseAddrLow} and @dfn{BaseAddrHigh} together are the 64 bit |
| @dfn{BaseAddress} of this range. The @dfn{BaseAddress} is the physical |
| address of the start of the range being specified. |
| |
| The @dfn{LengthLow} and @dfn{LengthHigh} together are the 64 bit |
| @dfn{Length} of this range. The @dfn{Length} is the physical contiguous |
| length in bytes of a range being specified. |
| |
| The @dfn{Type} field describes the usage of the described address range |
| as defined in the table below: |
| |
| @multitable @columnfractions 0.1 0.35 0.55 |
| @item Value @tab Pneumonic @tab Description |
| |
| @item 1 @tab @dfn{AddressRangeMemory} @tab This run is available |
| @sc{ram} usable by the operating system. |
| |
| @item 2 @tab @dfn{AddressRangeReserved} @tab This run of addresses is in |
| use or reserved by the system, and must not be used by the operating |
| system. |
| |
| @item Other @tab @dfn{Undefined} @tab Undefined - Reserved for future |
| use. Any range of this type must be treated by the OS as if the type |
| returned was @dfn{AddressRangeReserved}. |
| @end multitable |
| |
| The BIOS can use the @dfn{AddressRangeReserved} address range type to |
| block out various addresses as @emph{not suitable} for use by a |
| programmable device. |
| |
| Some of the reasons a BIOS would do this are: |
| |
| @itemize @bullet |
| @item |
| The address range contains system @sc{rom}. |
| |
| @item |
| The address range contains @sc{ram} in use by the @sc{rom}. |
| |
| @item |
| The address range is in use by a memory mapped system device. |
| |
| @item |
| The address range is for whatever reason are unsuitable for a |
| standard device to use as a device memory space. |
| @end itemize |
| |
| Here is the list of assumptions and limitations: |
| |
| @enumerate |
| @item |
| The BIOS will return address ranges describing base board memory and ISA |
| or PCI memory that is contiguous with that base board memory. |
| |
| @item |
| The BIOS @emph{will not} return a range description for the memory |
| mapping of PCI devices. ISA Option @sc{rom}'s, and ISA plug & play |
| cards. This is because the OS has mechanisms available to detect them. |
| |
| @item |
| The BIOS will return chipset defined address holes that are not being |
| used by devices as reserved. |
| |
| @item |
| Address ranges defined for base board memory mapped I/O devices (for |
| example APICs) will be returned as reserved. |
| |
| @item |
| 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). |
| |
| @item |
| 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. |
| |
| @item |
| All of lower memory is reported as normal memory. It is OS's |
| responsibility to handle standard @sc{ram} locations reserved for |
| specific uses, for example: the interrupt vector table (0:0) and the |
| BIOS data area (40:0). |
| @end enumerate |
| |
| Here we explain an example address map. This sample address map |
| describes a machine which has 128 MB @sc{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: @dfn{ARM} is AddressRangeMemory, @dfn{ARR} is |
| AddressRangeReserved. |
| |
| @multitable @columnfractions 0.15 0.1 0.1 0.65 |
| @item Base (Hex) @tab Length @tab Type @tab Description |
| |
| @item 0000 0000 @tab 639K @tab ARM @tab Available Base memory - |
| typically the same value as is returned via the INT 12 function. |
| |
| @item 0009 FC00 @tab 1K @tab ARR @tab Memory reserved for use by the |
| BIOS(s). This area typically includes the Extended BIOS data area. |
| |
| @item 000F 0000 @tab 64K @tab ARR @tab System BIOS. |
| |
| @item 0010 0000 @tab 7M @tab ARM @tab Extended memory, this is not |
| limited to the 64MB address range. |
| |
| @item 0080 0000 @tab 8M @tab ARR @tab Chipset memory hole required to |
| support the LFB mapping at 12 MB. |
| |
| @item 0100 0000 @tab 120M @tab ARM @tab Base board @sc{ram} relocated |
| above a chipset memory hole. |
| |
| @item FE00 0000 @tab 4K @tab ARR @tab 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. |
| |
| @item FEE0 0000 @tab 4K @tab ARR @tab Local APIC memory mapped I/O at |
| FEE00000. |
| |
| @item FFFF 0000 @tab 64K @tab ARR @tab Remapped System BIOS at end of |
| address space. |
| @end multitable |
| |
| 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. |
| |
| @example |
| 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 |
| . |
| . |
| . |
| @} |
| @end example |
| |
| |
| @node Get Large Memory Size |
| @subsection 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 @sc{ram}. While not nearly as flexible as |
| E820h, it is present in many more systems. |
| |
| Input: |
| |
| @multitable @columnfractions 0.15 0.25 0.6 |
| @item @code{AX} @tab Function Code @tab E801h. |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.25 0.6 |
| @item @code{CF} @tab Carry Flag @tab Non-Carry - indicates no error. |
| |
| @item @code{AX} @tab Extended 1 @tab Number of contiguous KB between 1 |
| and 16 MB, maximum 0x3C00 = 15 MB. |
| |
| @item @code{BX} @tab Extended 2 @tab Number of contiguous 64KB blocks |
| between 16 MB and 4GB. |
| |
| @item @code{CX} @tab Configured 1 @tab Number of contiguous KB between 1 |
| and 16 MB, maximum 0x3c00 = 15 MB. |
| |
| @item @code{DX} @tab Configured 2 @tab Number of contiguous 64KB blocks |
| between 16 MB and 4 GB. |
| @end multitable |
| |
| Not sure what this difference between the @dfn{Extended} and |
| @dfn{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). |
| |
| |
| @node Get Extended Memory Size |
| @subsection 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: |
| |
| @multitable @columnfractions 0.15 0.25 0.6 |
| @item @code{AH} @tab Function Code @tab 88h |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.25 0.6 |
| @item @code{CF} @tab Carry Flag @tab Non-Carry - indicates no error. |
| |
| @item @code{AX} @tab Memory Count @tab Number of contiguous KB above 1 |
| MB. |
| @end multitable |
| |
| |
| @node Low-level disk I/O |
| @section 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. |
| |
| @menu |
| * CHS Translation:: CHS addressing and LBA addressing. |
| * CHS mode disk I/O:: INT 13H, AH=0xh interrupt call. |
| * LBA mode disk I/O:: INT 13H, AH=4xh interrupt call. |
| @end menu |
| |
| |
| @node CHS Translation |
| @subsection 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 @dfn{L-CHS} and the |
| physical CHS or @dfn{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) @emph{must} use INT 13H to |
| determine the capacity of a hard disk. And that capacity information |
| @emph{must} be determined in L-CHS mode. Why is this? Because: |
| |
| @enumerate |
| @item |
| FDISK and the partition tables are really L-CHS based. |
| |
| @item |
| 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. |
| |
| @item |
| The boot processing done by the BIOS is all L-CHS based. |
| @end enumerate |
| |
| 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 @sc{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: |
| |
| @table @asis |
| @item 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. |
| |
| @item 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. |
| |
| @item 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. |
| @end table |
| |
| 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 @cite{the ATA-2 document}: |
| |
| @example |
| @group |
| 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. |
| @end group |
| @end example |
| |
| 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: |
| |
| @example |
| @group |
| 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 |
| @end group |
| @end example |
| |
| 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: |
| |
| @itemize @bullet |
| @item |
| Some drives >528MB don't implement LBA. |
| |
| @item |
| 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. |
| |
| @item |
| The L-CHS to LBA conversion is more complex and slower than the bit |
| shifting L-CHS to P-CHS conversion. |
| |
| @item |
| 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. |
| |
| @item |
| 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. |
| |
| @item |
| Microsoft has said that their OS's will not use any disk capacity that |
| can not also be accessed by INT 13H AH=0xH. |
| @end itemize |
| |
| These are difficult problems to overcome in today's industry |
| environment. The result: chaos. |
| |
| |
| @node CHS mode disk I/O |
| @subsection 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: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{AH} @tab 02h |
| |
| @item @code{AL} @tab The number of sectors to read (must be non-zero). |
| |
| @item @code{CH} @tab Low 8 bits of cylinder number. |
| |
| @item @code{CL} @tab Sector number in bits 0-5, and high 2 bits of |
| cylinder number in bits 6-7. |
| |
| @item @code{DH} @tab Head number. |
| |
| @item @code{DL} @tab Drive number (bit 7 set for hard disk). |
| |
| @item @code{ES:BX} @tab Data buffer. |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab Status. |
| |
| @item @code{AL} @tab The number of sectors transferred (only valid if CF |
| set for some BIOSes). |
| @end multitable |
| |
| INT 13H, AH=03h writes disk sectors. |
| |
| Input: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{AH} @tab 03h |
| |
| @item @code{AL} @tab The number of sectors to write (must be non-zero). |
| |
| @item @code{CH} @tab Low 8 bits of cylinder number. |
| |
| @item @code{CL} @tab Sector number in bits 0-5, and high 2 bits of |
| cylinder number in bits 6-7. |
| |
| @item @code{DH} @tab Head number. |
| |
| @item @code{DL} @tab Drive number (bit 7 set for hard disk). |
| |
| @item @code{ES:BX} @tab Data buffer. |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab Status. |
| |
| @item @code{AL} @tab The number of sectors transferred (only valid if CF |
| set for some BIOSes). |
| @end multitable |
| |
| INT 13H, AH=08h returns drive parameters. For systems predating the IBM |
| PC/AT, this call is only valid for hard disks. |
| |
| Input: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{AH} @tab 08h |
| |
| @item @code{DL} @tab Drive number (bit 7 set for hard disk). |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab 0. |
| |
| @item @code{AL} @tab 0 on at least some BIOSes. |
| |
| @item @code{BL} @tab Drive type (AT/PS2 floppies only). |
| |
| @item @code{CH} @tab Low 8 bits of maximum cylinder number. |
| |
| @item @code{CL} @tab Maximum sector number in bits 0-5, and high 2 bits |
| of maximum cylinder number in bits 6-7. |
| |
| @item @code{DH} @tab Maxiumum head number. |
| |
| @item @code{DL} @tab The number of drives. |
| |
| @item @code{ES:DI} @tab Drive parameter table (floppies only). |
| @end multitable |
| |
| 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. |
| |
| |
| @node LBA mode disk I/O |
| @subsection 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: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{AH} @tab 41h. |
| |
| @item @code{BX} @tab 55AAh. |
| |
| @item @code{DL} @tab Drive number. |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab 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 @dfn{invalid function}). |
| |
| @item @code{BX} @tab AA55h if installed. |
| |
| @item @code{AL} @tab Internal use. |
| |
| @item @code{CX} @tab API subset support bitmap (see below). |
| |
| @item @code{DH} @tab Extension version. |
| @end multitable |
| |
| The bitfields for the API subset support bitmap are: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item Bit(s) @tab Description |
| |
| @item 0 @tab Extended disk access functions (AH=42h-44h, 47h, 48h) |
| supported. |
| |
| @item 1 @tab Removable drive controller functions (AH=45h, 46h, 48h, |
| 49h, INT 15H, AH=52h) supported. |
| |
| @item 2 @tab Enhanced disk drive (EDD) functions (AH=48h, 4Eh) |
| supported. |
| |
| @item 3-15 @tab Reserved (0). |
| @end multitable |
| |
| INT 13, AH=42h reads sectors into memory. |
| |
| Input: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{AH} @tab 42h. |
| |
| @item @code{DL} @tab Drive number. |
| |
| @item @code{DS:SI} @tab Disk Address Packet (see below). |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions .15 .85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab 0 if successful, otherwise error code. |
| @end multitable |
| |
| The format of @dfn{Disk Address Packet} is: |
| |
| @multitable @columnfractions 0.15 0.15 0.7 |
| @item Offset (hex) @tab Size (byte) @tab Description |
| |
| @item 00 @tab 1 @tab 10h (The size of packet). |
| |
| @item 01 @tab 1 @tab Reserved (0). |
| |
| @item 02 @tab 2 @tab The number of blocks to transfer (max 007F for |
| Phoenix EDD). |
| |
| @item 04 @tab 4 @tab Transfer buffer (SEGMENT:OFFSET). |
| |
| @item 08 @tab 8 @tab Starting absolute block number. |
| @end multitable |
| |
| INT 13, AH=43h writes disk sectors. |
| |
| Input: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{AH} @tab 43h. |
| |
| @item @code{AL} @tab Write flags (In version 1.0 and 2.0, bit 0 is the |
| flag for @dfn{verify write} and other bits are reserved (0). In version |
| 2.1, 00h and 01h indicates @dfn{write without verify}, and 02h indicates |
| @dfn{write with verify}. |
| |
| @item @code{DL} @tab Drive number. |
| |
| @item @code{DS:SI} @tab Disk Address Packet (see above). |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab 0 if successful, otherwise error code. |
| @end multitable |
| |
| 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. @xref{CHS Translation}, for more information. |
| |
| Input: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{AH} @tab 48h. |
| |
| @item @code{DL} @tab Drive number. |
| |
| @item @code{DS:SI} @tab Buffer for drive parameters (see below). |
| @end multitable |
| |
| Output: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item @code{CF} @tab Set on error. |
| |
| @item @code{AH} @tab 0 if successful, otherwise error code. |
| @end multitable |
| |
| The format of drive parameters is: |
| |
| @multitable @columnfractions 0.25 0.15 0.6 |
| @item Offset (hex) @tab Size (byte) @tab Description |
| |
| @item 00 @tab 2 @tab 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). |
| |
| @item 02 @tab 2 @tab Information flags (see below). |
| |
| @item 04 @tab 4 @tab The number of physical cylinders. |
| |
| @item 08 @tab 4 @tab The number of physical heads. |
| |
| @item 0C @tab 4 @tab The number of physical sectors per track. |
| |
| @item 10 @tab 8 @tab The total number of sectors. |
| |
| @item 18 @tab 2 @tab The bytes per sector. |
| |
| @comment Add an empty row for readability... |
| @item @tab @tab |
| |
| @item @strong{v2.0 and later} @tab @tab |
| |
| @item 1A @tab 4 @tab EDD configuration parameters. |
| |
| @comment Add an empty row for readability... |
| @item @tab @tab |
| |
| @item @strong{v3.0} @tab @tab |
| |
| @item 1E @tab 2 @tab Signature BEDD to indicate presence of Device Path |
| information. |
| |
| @item 20 @tab 1 @tab The length of Device Path information, including |
| signature and this byte (24h for version 3.0). |
| |
| @item 21 @tab 3 @tab Reserved (0). |
| |
| @item 24 @tab 4 @tab ASCIZ name of host bus (@samp{ISA} or @samp{PCI}). |
| |
| @item 28 @tab 8 @tab ASCIZ name of interface type (@samp{ATA}, |
| @samp{ATAPI}, @samp{SCSI}, @samp{USB}, @samp{1394} or @samp{FIBRE}). |
| |
| @item 30 @tab 8 @tab Interface Path. |
| |
| @item 38 @tab 8 @tab Device Path. |
| |
| @item 40 @tab 1 @tab Reserved (0). |
| |
| @item 41 @tab 1 @tab Checksum of bytes 1Eh-40h (2's complement of sum, |
| which makes the 8 bit sum of bytes 1Eh-41h equal to 00h). |
| @end multitable |
| |
| The information flags are: |
| |
| @multitable @columnfractions 0.15 0.85 |
| @item Bit(s) @tab Description |
| |
| @item 0 @tab DMA boundary errors handles transparently. |
| |
| @item 1 @tab CHS information is valid. |
| |
| @item 2 @tab Removable drive. |
| |
| @item 3 @tab Write with verify supported. |
| |
| @item 4 @tab Drive has change-line support (required if drive is |
| removable). |
| |
| @item 5 @tab Drive can be locked (required if drive is removable). |
| |
| @item 6 @tab CHS information set to maximum supported values, not |
| current media. |
| |
| @item 7-15 @tab Reserved (0). |
| @end multitable |
| |
| |
| @node MBR |
| @section The structure of Master Boot Record |
| |
| A Master Boot Record (@dfn{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 (@dfn{POST}), INT |
| 19H is called. Usually INT 19 tries to read a boot sector from the first |
| floppy drive@footnote{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@footnote{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 @dfn{boot manager program}) and read that |
| into memory. |
| |
| INT 19H is also called when the @key{CTRL}-@key{ALT}-@key{DEL} keys are |
| used. On most systems, @key{CTRL}-@key{ALT}-@key{DEL} causes an short |
| version of the POST to be executed before INT 19H is called. |
| |
| The stuff is: |
| |
| @table @asis |
| @item Offset 0000 |
| The address where the MBR code starts. |
| |
| @item Offset 01BE |
| The address where the partition table starts (@pxref{Partition table}). |
| |
| @item Offset 01FE |
| The signature, AA55. |
| @end table |
| |
| However, the first 62 bytes of a boot sector are known as the BIOS |
| Parameter Block (@dfn{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 @code{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 @code{DL} register before INT 13H is called to read the |
| boot sector. When INT 13H is called, @code{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. |
| |
| |
| @node Partition table |
| @section The format of partition table |
| |
| @menu |
| * Partition basics:: Overview the partition table. |
| * Partition types:: The list of the @dfn{type} code. |
| * Partition entry format:: The format of the table entry. |
| * Partition table rules:: Some basic rules for Partition table. |
| @end menu |
| |
| |
| @node Partition basics |
| @subsection 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 @ref{MBR}. |
| |
| Second, extended partitions are @emph{nested} inside one another and |
| extended partition table records form a @dfn{linked list}. I will |
| attempt to show this in a diagram at @ref{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 @dfn{type} and the @dfn{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 @ref{CHS Translation}. |
| |
| |
| @node Partition types |
| @subsection The list of the @dfn{type} code |
| |
| There is no central clearing house to assign the codes used in the one |
| byte @dfn{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 @samp{sfdisk}, the following list is assumed: |
| |
| @table @asis |
| @item 00 |
| Empty |
| |
| @item 01 |
| DOS 12-bit FAT |
| |
| @item 02 |
| XENIX / |
| |
| @item 03 |
| XENIX /usr |
| |
| @item 04 |
| DOS 16-bit FAT <32M |
| |
| @item 05 |
| DOS Extended |
| |
| @item 06 |
| DOS 16-bit FAT >=32M |
| |
| @item 07 |
| HPFS / NTFS |
| |
| @item 08 |
| AIX boot or SplitDrive |
| |
| @item 09 |
| AIX data or Coherent |
| |
| @item 0A |
| OS/2 Boot Manager |
| |
| @item 0B |
| Windows95 FAT32 |
| |
| @item 0C |
| Windows95 FAT32 (LBA) |
| |
| @item 0E |
| Windows95 FAT16 (LBA) |
| |
| @item 0F |
| Windows95 Extended (LBA) |
| |
| @item 10 |
| OPUS |
| |
| @item 11 |
| Hidden DOS FAT12 |
| |
| @item 12 |
| Compaq diagnostics |
| |
| @item 14 |
| Hidden DOS FAT16 |
| |
| @item 16 |
| Hidden DOS FAT16 (big) |
| |
| @item 17 |
| Hidden HPFS/NTFS |
| |
| @item 18 |
| AST Windows swapfile |
| |
| @item 24 |
| NEC DOS |
| |
| @item 3C |
| PartitionMagic recovery |
| |
| @item 40 |
| Venix 80286 |
| |
| @item 41 |
| Linux/MINIX (sharing disk with DRDOS) |
| |
| @item 42 |
| SFS or Linux swap (sharing disk with DRDOS) |
| |
| @item 43 |
| Linux native (sharing disk with DRDOS) |
| |
| @item 50 |
| DM (disk manager) |
| |
| @item 51 |
| DM6 Aux1 (or Novell) |
| |
| @item 52 |
| CP/M or Microsoft SysV/AT |
| |
| @item 53 |
| DM6 Aux3 |
| |
| @item 54 |
| DM6 |
| |
| @item 55 |
| EZ-Drive (disk manager) |
| |
| @item 56 |
| Golden Bow (disk manager) |
| |
| @item 5C |
| Priam Edisk (disk manager) |
| |
| @item 61 |
| SpeedStor |
| |
| @item 63 |
| GNU Hurd or Mach or Sys V/386 (such as ISC UNIX)@footnote{But the reason |
| why they decided that 63 means GNU Hurd is not known. Do not use 63 for |
| GNU Hurd.} |
| |
| @item 64 |
| Novell Netware 286 |
| |
| @item 65 |
| Novell Netware 386 |
| |
| @item 70 |
| DiskSecure Multi-Boot |
| |
| @item 75 |
| PC/IX |
| |
| @item 77 |
| QNX4.x |
| |
| @item 78 |
| QNX4.x 2nd part |
| |
| @item 79 |
| QNX4.x 3rd part |
| |
| @item 80 |
| MINIX until 1.4a |
| |
| @item 81 |
| MINIX / old Linux |
| |
| @item 82 |
| Linux swap |
| |
| @item 83 |
| Linux native@footnote{This is not true. Use 83 for ext2fs even if the |
| owner OS is GNU/Hurd.} |
| |
| @item 84 |
| OS/2 hidden C: drive |
| |
| @item 85 |
| Linux extended |
| |
| @item 86 |
| NTFS volume set |
| |
| @item 87 |
| NTFS volume set |
| |
| @item 93 |
| Amoeba |
| |
| @item 94 |
| Amoeba BBT |
| |
| @item A0 |
| IBM Thinkpad hibernatoin |
| |
| @item A5 |
| BSD/386 |
| |
| @item A7 |
| NeXTSTEP 486 |
| |
| @item B7 |
| BSDI fs |
| |
| @item B8 |
| BSDI swap |
| |
| @item C1 |
| DRDOS/sec (FAT-12) |
| |
| @item C4 |
| DRDOS/sec (FAT-16, < 32M) |
| |
| @item C6 |
| DRDOS/sec (FAT-16, >= 32M) |
| |
| @item C7 |
| Syrinx |
| |
| @item DB |
| CP/M or Concurrent CP/M or Concurrent DOS or CTOS |
| |
| @item E1 |
| DOS access or SpeedStor 12-bit FAT extended partition |
| |
| @item E3 |
| DOS R/O or SpeedStor |
| |
| @item E4 |
| SpeedStor 16-bit FAT extended partition < 1024 cyl. |
| |
| @item F1 |
| SpeedStor |
| |
| @item F2 |
| DOS 3.3+ secondary |
| |
| @item F4 |
| SpeedStor large partition |
| |
| @item FE |
| SpeedStor >1024 cyl. or LANstep |
| |
| @item FF |
| Xenix Bad Block Table |
| @end table |
| |
| @node Partition entry format |
| @subsection The format of the table entry |
| |
| The 16 bytes of a partition table entry are used as follows: |
| |
| @example |
| @group |
| +--- 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 |
| @end group |
| @end example |
| |
| 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 @dfn{DH}, |
| @dfn{DL}, @dfn{CH} and @dfn{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 @ref{MBR}. |
| |
| These entries define the following partitions: |
| |
| @enumerate |
| @item |
| 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. |
| |
| @item |
| 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. |
| |
| @item |
| The third and fourth table entries are unused. |
| @end enumerate |
| |
| |
| @node Partition table rules |
| @subsection Some basic rules for Partition table. |
| |
| Keep in mind that there are @emph{no} written rules and @emph{no} |
| industry standards on how FDISK should work but here are some basic |
| rules that seem to be followed by most versions of FDISK: |
| |
| @enumerate |
| @item |
| In the MBR there can be 0-4 @dfn{primary} partitions, OR, 0-3 primary |
| partitions and 0-1 extended partition entry. |
| |
| @item |
| In an extended partition there can be 0-1 @dfn{secondary} partition |
| entries and 0-1 extended partition entries. |
| |
| @item |
| Only 1 primary partition in the MBR can be marked @dfn{active} at any |
| given time. |
| |
| @item |
| 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 @dfn{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. |
| |
| @item |
| 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. |
| |
| @item |
| And then there is the @dfn{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 @dfn{hack} follow |
| the same rules for the creation of these type of partitions. |
| @end enumerate |
| |
| There are @emph{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. |
| |
| |
| @node Filesystem interface |
| @section The generic interface for the fs code |
| |
| For any particular partition, it is presumed that only one of the |
| @dfn{normal} filesystems such as FAT, FFS, or ext2fs can be used, so |
| there is a switch table managed by the functions in |
| @file{disk_io.c}. The notation is that you can only @dfn{mount} one at a |
| time. |
| |
| The blocklist filesystem has a special place in the system. In addition |
| to the @dfn{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: |
| |
| @vtable @code |
| @item current_drive |
| Contain the current BIOS drive number (numbered from 0, if a floppy, |
| and numbered from 0x80, if a hard disk). |
| |
| @item current_slice |
| Contain the current partition length, in sectors. |
| |
| @item print_possibilities |
| True when the @code{dir} function should print the possible completions |
| of a file, and false when it should try to actually open a file of that |
| name. |
| |
| @item FSYS_BUF |
| Point to a filesystem buffer which is 32K in size, to use in any way |
| which the filesystem backend desires. |
| @end vtable |
| |
| The variables which need to be written by a filesystem backend are: |
| |
| @vtable @code |
| @item filepos |
| Should be the current position in the file. |
| |
| @strong{Caution:} the value of @var{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! |
| |
| @item filemax |
| Should be the length of the file. |
| |
| @item debug_fs_func |
| Should be set to the value of @samp{debug_fs} @emph{only} during reading |
| of data for the file, not any other fs data, inodes, FAT tables, |
| whatever, then set to @code{NULL} at all other times (it will be |
| @code{NULL} by default). If this isn't done corrently, then the |
| @command{testload=} and @command{install=} commands won't work |
| correctly. |
| @end vtable |
| |
| The functions expected to be used by the filesystem backend are: |
| |
| @ftable @code |
| @item devread |
| Only read sectors from within a partition. Sector 0 is the first sector |
| in the partition. |
| |
| @item grub_read |
| If the backend uses the block-list code (like the FAT filesystem backend |
| does), then @code{grub_read} can be used, after setting @var{block_file} |
| to 1. |
| @end ftable |
| |
| The functions expected to be defined by the filesystem backend are |
| described at least moderately in the file @file{filesys.h}. Their usage |
| is fairly evident from their use in the functions in @file{disk_io.c}, |
| look for the use of the @var{fsys_table} array. |
| |
| @strong{Caution:} The semantics are such that then @samp{mount}ing the |
| filesystem, presume the filesystem buffer @var{FSYS_BUF} is corrupted, |
| and (re-)load all important contents. When opening and reading a file, |
| presume that the data from the @samp{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). |
| |
| |
| @node Index |
| @unnumbered Index |
| |
| @c Currently, we use only the Concept Index. |
| @printindex cp |
| |
| @contents |
| @bye |