|  | @node Internals | 
|  | @chapter Hacking GRUB | 
|  |  | 
|  | This chapter documents the user-invisible aspect of GRUB. | 
|  |  | 
|  | As a general rule of software development, it is impossible to keep the | 
|  | descriptions of the internals up-to-date, and it is quite hard to | 
|  | document everything. So refer to the source code, whenever you are not | 
|  | satisfied with this documentation.  Please assume that this gives just | 
|  | hints to you. | 
|  |  | 
|  | @menu | 
|  | * Memory map::                  The memory map of various components | 
|  | * Embedded data::               Embedded variables in GRUB | 
|  | * Filesystem interface::        The generic interface for filesystems | 
|  | * Command interface::           The generic interface for built-ins | 
|  | * Bootstrap tricks::            The bootstrap mechanism used in GRUB | 
|  | * I/O ports detection::         How to probe I/O ports used by INT 13H | 
|  | * Memory detection::            How to detect all installed 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 tables | 
|  | * Submitting patches::          Where and how you should send patches | 
|  | @end menu | 
|  |  | 
|  |  | 
|  | @node Memory map | 
|  | @section The memory map of various components | 
|  |  | 
|  | GRUB consists of two distinct components, called @dfn{stages}, which are | 
|  | loaded at different times in the boot process. Because they run | 
|  | mutual-exclusively, sometimes a memory area overlaps with another | 
|  | memory area. And, even in one stage, a single memory area can be used | 
|  | for various purposes, because their usages are mutually exclusive. | 
|  |  | 
|  | Here is the memory map of the various components: | 
|  |  | 
|  | @table @asis | 
|  | @item 0 to 4K-1 | 
|  | BIOS and real mode interrupts | 
|  |  | 
|  | @item 0x07BE to 0x07FF | 
|  | Partition table passed to another boot loader | 
|  |  | 
|  | @item down from 8K-1 | 
|  | Real mode stack | 
|  |  | 
|  | @item 0x2000 to ? | 
|  | The optional Stage 1.5 is loaded here | 
|  |  | 
|  | @item 0x2000 to 0x7FFF | 
|  | Command-line buffer for Multiboot kernels and modules | 
|  |  | 
|  | @item 0x7C00 to 0x7DFF | 
|  | Stage 1 is loaded here by BIOS or another boot loader | 
|  |  | 
|  | @item 0x7F00 to 0x7F42 | 
|  | LBA drive parameters | 
|  |  | 
|  | @item 0x8000 to ? | 
|  | Stage2 is loaded here | 
|  |  | 
|  | @item The end of Stage 2 to 416K-1 | 
|  | Heap, in particular used for the menu | 
|  |  | 
|  | @item down from 416K-1 | 
|  | Protected mode stack | 
|  |  | 
|  | @item 416K to 448K-1 | 
|  | Filesystem buffer | 
|  |  | 
|  | @item 448K to 479.5K-1 | 
|  | Raw device buffer | 
|  |  | 
|  | @item 479.5K to 480K-1 | 
|  | 512-byte scratch area | 
|  |  | 
|  | @item 480K to 512K-1 | 
|  | Buffers for various functions, such as password, command-line, cut and | 
|  | paste, and completion. | 
|  |  | 
|  | @item The last 1K of lower memory | 
|  | Disk swapping code and data | 
|  | @end table | 
|  |  | 
|  | See the file @file{stage2/shared.h}, for more information. | 
|  |  | 
|  |  | 
|  | @node Embedded data | 
|  | @section Embedded variables in GRUB | 
|  |  | 
|  | Stage 1 and Stage 2 have embedded variables whose locations are | 
|  | well-defined, so that the installation can patch the binary file | 
|  | directly without recompilation of the stages. | 
|  |  | 
|  | In Stage 1, these are defined: | 
|  |  | 
|  | @table @code | 
|  | @item 0x3E | 
|  | The version number (not GRUB's, but the installation mechanism's). | 
|  |  | 
|  | @item 0x40 | 
|  | The boot drive. If it is 0xFF, use a drive passed by BIOS. | 
|  |  | 
|  | @item 0x41 | 
|  | The flag for if forcing LBA. | 
|  |  | 
|  | @item 0x42 | 
|  | The starting address of Stage 2. | 
|  |  | 
|  | @item 0x44 | 
|  | The first sector of Stage 2. | 
|  |  | 
|  | @item 0x48 | 
|  | The starting segment of Stage 2. | 
|  |  | 
|  | @item 0x1FE | 
|  | The signature (@code{0xAA55}). | 
|  | @end table | 
|  |  | 
|  | See the file @file{stage1/stage1.S}, for more information. | 
|  |  | 
|  | In the first sector of Stage 1.5 and Stage 2, the block lists are | 
|  | recorded between @code{firstlist} and @code{lastlist}. The address of | 
|  | @code{lastlist} is determined when assembling the file | 
|  | @file{stage2/start.S}. | 
|  |  | 
|  | 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, and so on, | 
|  | until it is finished. The terminating condition is when the number of | 
|  | sectors to be read in the next block list is zero. | 
|  |  | 
|  | 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, but @emph{not} relative to the partition | 
|  | boundaries. | 
|  |  | 
|  | In the second sector of Stage 1.5 and Stage 2, these are defined: | 
|  |  | 
|  | @table @asis | 
|  | @item @code{0x6} | 
|  | The version number (likewise, the installation mechanism's). | 
|  |  | 
|  | @item @code{0x8} | 
|  | The installed partition. | 
|  |  | 
|  | @item @code{0xC} | 
|  | The saved entry number. | 
|  |  | 
|  | @item @code{0x10} | 
|  | The identifier. | 
|  |  | 
|  | @item @code{0x11} | 
|  | The flag for if forcing LBA. | 
|  |  | 
|  | @item @code{0x12} | 
|  | The version string (GRUB's). | 
|  |  | 
|  | @item @code{0x12} + @dfn{the length of the version string} | 
|  | The name of a configuration file. | 
|  | @end table | 
|  |  | 
|  | See the file @file{stage2/asm.S}, for more information. | 
|  |  | 
|  |  | 
|  | @node Filesystem interface | 
|  | @section The generic interface for filesystems | 
|  |  | 
|  | 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 block list 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 block | 
|  | list notation. Using the block list filesystem doesn't effect any other | 
|  | filesystem mounts. | 
|  |  | 
|  | The variables which can be read by the filesystem backend are: | 
|  |  | 
|  | @vtable @code | 
|  | @item current_drive | 
|  | The current BIOS drive number (numbered from 0, if a floppy, and | 
|  | numbered from 0x80, if a hard disk). | 
|  |  | 
|  | @item current_partition | 
|  | The current partition number. | 
|  |  | 
|  | @item current_slice | 
|  | The current partition type. | 
|  |  | 
|  | @item saved_drive | 
|  | The @dfn{drive} part of the root device. | 
|  |  | 
|  | @item saved_partition | 
|  | The @dfn{partition} part of the root device. | 
|  |  | 
|  | @item part_start | 
|  | The current partition starting address, in sectors. | 
|  |  | 
|  | @item part_length | 
|  | 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 | 
|  | 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 | 
|  | The current position in the file, in sectors. | 
|  |  | 
|  | @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 backend code! | 
|  |  | 
|  | @item filemax | 
|  | The length of the file. | 
|  |  | 
|  | @item disk_read_func | 
|  | The value of @var{disk_read_hook} @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 correctly, 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, then @code{grub_read} can be | 
|  | used, after setting @var{block_file} to 1. | 
|  |  | 
|  | @item print_a_completion | 
|  | If @var{print_possibilities} is true, call @code{print_a_completion} for | 
|  | each possible file name. Otherwise, the file name completion won't work. | 
|  | @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 @code{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 Command interface | 
|  | @section The generic interface for built-ins | 
|  |  | 
|  | GRUB built-in commands are defined in a uniformal interface, whether | 
|  | they are menu-specific or can be used anywhere. The definition of a | 
|  | builtin command consists of two parts: the code itself and the table of | 
|  | the information. | 
|  |  | 
|  | The code must be a function which takes two arguments, a command-line | 
|  | string and flags, and returns an @samp{int} value. The @dfn{flags} | 
|  | argument specifies how the function is called, using a bit mask. The | 
|  | return value must be zero if successful, otherwise non-zero. So it is | 
|  | normally enough to return @var{errnum}. | 
|  |  | 
|  | The table of the information is represented by the structure | 
|  | @code{struct builtin}, which contains the name of the command, a pointer | 
|  | to the function, flags, a short description of the command and a long | 
|  | description of the command. Since the descriptions are used only for | 
|  | help messages interactively, you don't have to define them, if the | 
|  | command may not be called interactively (such as @command{title}). | 
|  |  | 
|  | The table is finally registered in the table @var{builtin_table}, so | 
|  | that @code{run_script} and @code{enter_cmdline} can find the | 
|  | command. See the files @file{cmdline.c} and @file{builtins.c}, for more | 
|  | details. | 
|  |  | 
|  |  | 
|  | @node Bootstrap tricks | 
|  | @section The bootstrap mechanism used in GRUB | 
|  |  | 
|  | The disk space can be used in a boot loader is very restricted because | 
|  | a MBR (@pxref{MBR}) is only 512 bytes but it also contains a partition | 
|  | table (@pxref{Partition table}) and a BPB. So the question is how to | 
|  | make a boot loader code enough small to be fit in a MBR. | 
|  |  | 
|  | However, GRUB is a very large program, so we break GRUB into 2 (or 3) | 
|  | distinct components, @dfn{Stage 1} and @dfn{Stage 2} (and optionally | 
|  | @dfn{Stage 1.5}). @xref{Memory map}, for more information. | 
|  |  | 
|  | We embed Stage 1 in a MBR or in the boot sector of a partition, and | 
|  | place Stage 2 in a filesystem. The optional Stage 1.5 can be installed | 
|  | in a filesystem, in the @dfn{boot loader} area in a FFS or a ReiserFS, | 
|  | and in the sectors right after a MBR, because Stage 1.5 is enough small | 
|  | and the sectors right after a MBR is normally an unused region. The size | 
|  | of this region is the number of sectors per head minus 1. | 
|  |  | 
|  | Thus, all Stage1 must do is just load Stage2 or Stage1.5. But even if | 
|  | Stage 1 needs not to support the user interface or the filesystem | 
|  | interface, it is impossible to make Stage 1 less than 400 bytes, because | 
|  | GRUB should support both the CHS mode and the LBA mode (@pxref{Low-level | 
|  | disk I/O}). | 
|  |  | 
|  | The solution used by GRUB is that Stage 1 loads only the first sector of | 
|  | Stage 2 (or Stage 1.5) and Stage 2 itself loads the rest. The flow of | 
|  | Stage 1 is: | 
|  |  | 
|  | @enumerate | 
|  | @item | 
|  | Initialize the system briefly. | 
|  |  | 
|  | @item | 
|  | Detect the geometry and the accessing mode of the @dfn{loading drive}. | 
|  |  | 
|  | @item | 
|  | Load the first sector of Stage 2. | 
|  |  | 
|  | @item | 
|  | Jump to the starting address of the Stage 2. | 
|  | @end enumerate | 
|  |  | 
|  | The flow of Stage 2 (and Stage 1.5) is: | 
|  |  | 
|  | @enumerate | 
|  | @item | 
|  | Load the rest of itself to the real starting address, that is, the | 
|  | starting address plus 512 bytes. The block lists are stored in the last | 
|  | part of the first sector. | 
|  |  | 
|  | @item | 
|  | Long jump to the real starting address. | 
|  | @end enumerate | 
|  |  | 
|  | Note that Stage 2 (or Stage 1.5) does not probe the geometry | 
|  | or the accessing mode of the @dfn{loading drive}, since Stage 1 has | 
|  | already probed them. | 
|  |  | 
|  |  | 
|  | @node I/O ports detection | 
|  | @section How to probe I/O ports used by INT 13H | 
|  |  | 
|  | FIXME: I will write this chapter after implementing the new technique. | 
|  |  | 
|  |  | 
|  |  | 
|  | @node Memory detection | 
|  | @section How to detect all installed RAM | 
|  |  | 
|  | FIXME: I doubt if Erich didn't write this chapter only himself wholly, | 
|  | so I will rewrite this chapter. | 
|  |  | 
|  |  | 
|  | @node Low-level disk I/O | 
|  | @section INT 13H disk I/O interrupts | 
|  |  | 
|  | FIXME: I'm not sure where some part of the original chapter is derived, | 
|  | so I will rewrite this chapter. | 
|  |  | 
|  |  | 
|  | @node MBR | 
|  | @section The structure of Master Boot Record | 
|  |  | 
|  | FIXME: Likewise. | 
|  |  | 
|  |  | 
|  | @node Partition table | 
|  | @section The format of partition tables | 
|  |  | 
|  | FIXME: Probably the original chapter is derived from "How It Works", so | 
|  | I will rewrite this chapter. | 
|  |  | 
|  |  | 
|  | @node Submitting patches | 
|  | @section Where and how you should send patches | 
|  |  | 
|  | When you write patches for GRUB, please send them to the mailing list | 
|  | @email{bug-grub@@gnu.org}. Here is the list of items of which you | 
|  | should take care: | 
|  |  | 
|  | @itemize @bullet | 
|  | @item | 
|  | Please make your patch as small as possible. Generally, it is not a good | 
|  | thing to make one big patch which changes many things. Instead, | 
|  | segregate features and produce many patches. | 
|  |  | 
|  | @item | 
|  | Use as late code as possible, for the original code. The CVS repository | 
|  | always has the current version (@pxref{Obtaining and Building GRUB}). | 
|  |  | 
|  | @item | 
|  | Write ChangeLog entries. @xref{Change Logs, , Change Logs, standards, | 
|  | GNU Coding Standards}, if you don't know how to write ChangeLog. | 
|  |  | 
|  | @item | 
|  | Make patches in unified diff format. @samp{diff -urN} is appropriate in | 
|  | most cases. | 
|  |  | 
|  | @item | 
|  | Don't make patches reversely. Reverse patches are difficult to read and | 
|  | use. | 
|  |  | 
|  | @item | 
|  | Be careful enough of the license term and the copyright. Because GRUB | 
|  | is under GNU General Public License, you may not steal code from | 
|  | software whose license is incompatible against GPL. And, if you copy | 
|  | code written by others, you must not ignore their copyrights. Feel free | 
|  | to ask GRUB maintainers, whenever you are not sure what you should do. | 
|  |  | 
|  | @item | 
|  | If your patch is too large to send in e-mail, put it at somewhere we can | 
|  | see. Usually, you shouldn't send e-mail over 20K. | 
|  | @end itemize |