1N/A@node Internals
1N/A@appendix Hacking GRUB
1N/A
1N/AThis chapter documents the user-invisible aspect of GRUB.
1N/A
1N/AAs a general rule of software development, it is impossible to keep the
1N/Adescriptions of the internals up-to-date, and it is quite hard to
1N/Adocument everything. So refer to the source code, whenever you are not
1N/Asatisfied with this documentation. Please assume that this gives just
1N/Ahints to you.
1N/A
1N/A@menu
1N/A* Memory map:: The memory map of various components
1N/A* Embedded data:: Embedded variables in GRUB
1N/A* Filesystem interface:: The generic interface for filesystems
1N/A* Command interface:: The generic interface for built-ins
1N/A* Bootstrap tricks:: The bootstrap mechanism used in GRUB
1N/A* I/O ports detection:: How to probe I/O ports used by INT 13H
1N/A* Memory detection:: How to detect all installed RAM
1N/A* Low-level disk I/O:: INT 13H disk I/O interrupts
1N/A* MBR:: The structure of Master Boot Record
1N/A* Partition table:: The format of partition tables
1N/A* Submitting patches:: Where and how you should send patches
1N/A@end menu
1N/A
1N/A
1N/A@node Memory map
1N/A@section The memory map of various components
1N/A
1N/AGRUB consists of two distinct components, called @dfn{stages}, which are
1N/Aloaded at different times in the boot process. Because they run
1N/Amutual-exclusively, sometimes a memory area overlaps with another
1N/Amemory area. And, even in one stage, a single memory area can be used
1N/Afor various purposes, because their usages are mutually exclusive.
1N/A
1N/AHere is the memory map of the various components:
1N/A
1N/A@table @asis
1N/A@item 0 to 4K-1
1N/ABIOS and real mode interrupts
1N/A
1N/A@item 0x07BE to 0x07FF
1N/APartition table passed to another boot loader
1N/A
1N/A@item down from 8K-1
1N/AReal mode stack
1N/A
1N/A@item 0x2000 to ?
1N/AThe optional Stage 1.5 is loaded here
1N/A
1N/A@item 0x2000 to 0x7FFF
1N/ACommand-line buffer for Multiboot kernels and modules
1N/A
1N/A@item 0x7C00 to 0x7DFF
1N/AStage 1 is loaded here by BIOS or another boot loader
1N/A
1N/A@item 0x7F00 to 0x7F42
1N/ALBA drive parameters
1N/A
1N/A@item 0x8000 to ?
1N/AStage2 is loaded here
1N/A
1N/A@item The end of Stage 2 to 416K-1
1N/AHeap, in particular used for the menu
1N/A
1N/A@item down from 416K-1
1N/AProtected mode stack
1N/A
1N/A@item 416K to 448K-1
1N/AFilesystem buffer
1N/A
1N/A@item 448K to 479.5K-1
1N/ARaw device buffer
1N/A
1N/A@item 479.5K to 480K-1
1N/A512-byte scratch area
1N/A
1N/A@item 480K to 512K-1
1N/ABuffers for various functions, such as password, command-line, cut and
1N/Apaste, and completion.
1N/A
1N/A@item The last 1K of lower memory
1N/ADisk swapping code and data
1N/A@end table
1N/A
1N/ASee the file @file{stage2/shared.h}, for more information.
1N/A
1N/A
1N/A@node Embedded data
1N/A@section Embedded variables in GRUB
1N/A
1N/AStage 1 and Stage 2 have embedded variables whose locations are
1N/Awell-defined, so that the installation can patch the binary file
1N/Adirectly without recompilation of the stages.
1N/A
1N/AIn Stage 1, these are defined:
1N/A
1N/A@table @code
1N/A@item 0x3E
1N/AThe version number (not GRUB's, but the installation mechanism's).
1N/A
1N/A@item 0x40
1N/AThe boot drive. If it is 0xFF, use a drive passed by BIOS.
1N/A
1N/A@item 0x41
1N/AThe flag for if forcing LBA.
1N/A
1N/A@item 0x42
1N/AThe starting address of Stage 2.
1N/A
1N/A@item 0x44
1N/AThe first sector of Stage 2.
1N/A
1N/A@item 0x48
1N/AThe starting segment of Stage 2.
1N/A
1N/A@item 0x1FE
1N/AThe signature (@code{0xAA55}).
1N/A@end table
1N/A
1N/ASee the file @file{stage1/stage1.S}, for more information.
1N/A
1N/AIn the first sector of Stage 1.5 and Stage 2, the block lists are
1N/Arecorded between @code{firstlist} and @code{lastlist}. The address of
1N/A@code{lastlist} is determined when assembling the file
1N/A@file{stage2/start.S}.
1N/A
1N/AThe trick here is that it is actually read backward, and the first
1N/A8-byte block list is not read here, but after the pointer is decremented
1N/A8 bytes, then after reading it, it decrements again, reads, and so on,
1N/Auntil it is finished. The terminating condition is when the number of
1N/Asectors to be read in the next block list is zero.
1N/A
1N/AThe format of a block list can be seen from the example in the code just
1N/Abefore the @code{firstlist} label. Note that it is always from the
1N/Abeginning of the disk, but @emph{not} relative to the partition
1N/Aboundaries.
1N/A
1N/AIn the second sector of Stage 1.5 and Stage 2, these are defined:
1N/A
1N/A@table @asis
1N/A@item @code{0x6}
1N/AThe version number (likewise, the installation mechanism's).
1N/A
1N/A@item @code{0x8}
1N/AThe installed partition.
1N/A
1N/A@item @code{0xC}
1N/AThe saved entry number.
1N/A
1N/A@item @code{0x10}
1N/AThe identifier.
1N/A
1N/A@item @code{0x11}
1N/AThe flag for if forcing LBA.
1N/A
1N/A@item @code{0x12}
1N/AThe version string (GRUB's).
1N/A
1N/A@item @code{0x12} + @dfn{the length of the version string}
1N/AThe name of a configuration file.
1N/A@end table
1N/A
1N/ASee the file @file{stage2/asm.S}, for more information.
1N/A
1N/A
1N/A@node Filesystem interface
1N/A@section The generic interface for filesystems
1N/A
1N/AFor any particular partition, it is presumed that only one of the
1N/A@dfn{normal} filesystems such as FAT, FFS, or ext2fs can be used, so
1N/Athere is a switch table managed by the functions in
1N/A@file{disk_io.c}. The notation is that you can only @dfn{mount} one at a
1N/Atime.
1N/A
1N/AThe block list filesystem has a special place in the system. In addition
1N/Ato the @dfn{normal} filesystem (or even without one mounted), you can
1N/Aaccess disk blocks directly (in the indicated partition) via the block
1N/Alist notation. Using the block list filesystem doesn't effect any other
1N/Afilesystem mounts.
1N/A
1N/AThe variables which can be read by the filesystem backend are:
1N/A
1N/A@vtable @code
1N/A@item current_drive
1N/AThe current BIOS drive number (numbered from 0, if a floppy, and
1N/Anumbered from 0x80, if a hard disk).
1N/A
1N/A@item current_partition
1N/AThe current partition number.
1N/A
1N/A@item current_slice
1N/AThe current partition type.
1N/A
1N/A@item saved_drive
1N/AThe @dfn{drive} part of the root device.
1N/A
1N/A@item saved_partition
1N/AThe @dfn{partition} part of the root device.
1N/A
1N/A@item part_start
1N/AThe current partition starting address, in sectors.
1N/A
1N/A@item part_length
1N/AThe current partition length, in sectors.
1N/A
1N/A@item print_possibilities
1N/ATrue when the @code{dir} function should print the possible completions
1N/Aof a file, and false when it should try to actually open a file of that
1N/Aname.
1N/A
1N/A@item FSYS_BUF
1N/AFilesystem buffer which is 32K in size, to use in any way which the
1N/Afilesystem backend desires.
1N/A@end vtable
1N/A
1N/AThe variables which need to be written by a filesystem backend are:
1N/A
1N/A@vtable @code
1N/A@item filepos
1N/AThe current position in the file, in sectors.
1N/A
1N/A@strong{Caution:} the value of @var{filepos} can be changed out from
1N/Aunder the filesystem code in the current implementation. Don't depend on
1N/Ait being the same for later calls into the backend code!
1N/A
1N/A@item filemax
1N/AThe length of the file.
1N/A
1N/A@item disk_read_func
1N/AThe value of @var{disk_read_hook} @emph{only} during reading of data
1N/Afor the file, not any other fs data, inodes, FAT tables, whatever, then
1N/Aset to @code{NULL} at all other times (it will be @code{NULL} by
1N/Adefault). If this isn't done correctly, then the @command{testload} and
1N/A@command{install} commands won't work correctly.
1N/A@end vtable
1N/A
1N/AThe functions expected to be used by the filesystem backend are:
1N/A
1N/A@ftable @code
1N/A@item devread
1N/AOnly read sectors from within a partition. Sector 0 is the first sector
1N/Ain the partition.
1N/A
1N/A@item grub_read
1N/AIf the backend uses the block list code, then @code{grub_read} can be
1N/Aused, after setting @var{block_file} to 1.
1N/A
1N/A@item print_a_completion
1N/AIf @var{print_possibilities} is true, call @code{print_a_completion} for
1N/Aeach possible file name. Otherwise, the file name completion won't work.
1N/A@end ftable
1N/A
1N/AThe functions expected to be defined by the filesystem backend are
1N/Adescribed at least moderately in the file @file{filesys.h}. Their usage
1N/Ais fairly evident from their use in the functions in @file{disk_io.c},
1N/Alook for the use of the @var{fsys_table} array.
1N/A
1N/A@strong{Caution:} The semantics are such that then @samp{mount}ing the
1N/Afilesystem, presume the filesystem buffer @code{FSYS_BUF} is corrupted,
1N/Aand (re-)load all important contents. When opening and reading a file,
1N/Apresume that the data from the @samp{mount} is available, and doesn't
1N/Aget corrupted by the open/read (i.e. multiple opens and/or reads will be
1N/Adone with only one mount if in the same filesystem).
1N/A
1N/A
1N/A@node Command interface
1N/A@section The generic interface for built-ins
1N/A
1N/AGRUB built-in commands are defined in a uniformal interface, whether
1N/Athey are menu-specific or can be used anywhere. The definition of a
1N/Abuiltin command consists of two parts: the code itself and the table of
1N/Athe information.
1N/A
1N/AThe code must be a function which takes two arguments, a command-line
1N/Astring and flags, and returns an @samp{int} value. The @dfn{flags}
1N/Aargument specifies how the function is called, using a bit mask. The
1N/Areturn value must be zero if successful, otherwise non-zero. So it is
1N/Anormally enough to return @var{errnum}.
1N/A
1N/AThe table of the information is represented by the structure
1N/A@code{struct builtin}, which contains the name of the command, a pointer
1N/Ato the function, flags, a short description of the command and a long
1N/Adescription of the command. Since the descriptions are used only for
1N/Ahelp messages interactively, you don't have to define them, if the
1N/Acommand may not be called interactively (such as @command{title}).
1N/A
1N/AThe table is finally registered in the table @var{builtin_table}, so
1N/Athat @code{run_script} and @code{enter_cmdline} can find the
1N/Acommand. See the files @file{cmdline.c} and @file{builtins.c}, for more
1N/Adetails.
1N/A
1N/A
1N/A@node Bootstrap tricks
1N/A@section The bootstrap mechanism used in GRUB
1N/A
1N/AThe disk space can be used in a boot loader is very restricted because
1N/Aa MBR (@pxref{MBR}) is only 512 bytes but it also contains a partition
1N/Atable (@pxref{Partition table}) and a BPB. So the question is how to
1N/Amake a boot loader code enough small to be fit in a MBR.
1N/A
1N/AHowever, GRUB is a very large program, so we break GRUB into 2 (or 3)
1N/Adistinct components, @dfn{Stage 1} and @dfn{Stage 2} (and optionally
1N/A@dfn{Stage 1.5}). @xref{Memory map}, for more information.
1N/A
1N/AWe embed Stage 1 in a MBR or in the boot sector of a partition, and
1N/Aplace Stage 2 in a filesystem. The optional Stage 1.5 can be installed
1N/Ain a filesystem, in the @dfn{boot loader} area in a FFS or a ReiserFS,
1N/Aand in the sectors right after a MBR, because Stage 1.5 is enough small
1N/Aand the sectors right after a MBR is normally an unused region. The size
1N/Aof this region is the number of sectors per head minus 1.
1N/A
1N/AThus, all Stage1 must do is just load Stage2 or Stage1.5. But even if
1N/AStage 1 needs not to support the user interface or the filesystem
1N/Ainterface, it is impossible to make Stage 1 less than 400 bytes, because
1N/AGRUB should support both the CHS mode and the LBA mode (@pxref{Low-level
1N/Adisk I/O}).
1N/A
1N/AThe solution used by GRUB is that Stage 1 loads only the first sector of
1N/AStage 2 (or Stage 1.5) and Stage 2 itself loads the rest. The flow of
1N/AStage 1 is:
1N/A
1N/A@enumerate
1N/A@item
1N/AInitialize the system briefly.
1N/A
1N/A@item
1N/ADetect the geometry and the accessing mode of the @dfn{loading drive}.
1N/A
1N/A@item
1N/ALoad the first sector of Stage 2.
1N/A
1N/A@item
1N/AJump to the starting address of the Stage 2.
1N/A@end enumerate
1N/A
1N/AThe flow of Stage 2 (and Stage 1.5) is:
1N/A
1N/A@enumerate
1N/A@item
1N/ALoad the rest of itself to the real starting address, that is, the
1N/Astarting address plus 512 bytes. The block lists are stored in the last
1N/Apart of the first sector.
1N/A
1N/A@item
1N/ALong jump to the real starting address.
1N/A@end enumerate
1N/A
1N/ANote that Stage 2 (or Stage 1.5) does not probe the geometry
1N/Aor the accessing mode of the @dfn{loading drive}, since Stage 1 has
1N/Aalready probed them.
1N/A
1N/A
1N/A@node I/O ports detection
1N/A@section How to probe I/O ports used by INT 13H
1N/A
1N/AFIXME: I will write this chapter after implementing the new technique.
1N/A
1N/A
1N/A
1N/A@node Memory detection
1N/A@section How to detect all installed RAM
1N/A
1N/AFIXME: I doubt if Erich didn't write this chapter only himself wholly,
1N/Aso I will rewrite this chapter.
1N/A
1N/A
1N/A@node Low-level disk I/O
1N/A@section INT 13H disk I/O interrupts
1N/A
1N/AFIXME: I'm not sure where some part of the original chapter is derived,
1N/Aso I will rewrite this chapter.
1N/A
1N/A
1N/A@node MBR
1N/A@section The structure of Master Boot Record
1N/A
1N/AFIXME: Likewise.
1N/A
1N/A
1N/A@node Partition table
1N/A@section The format of partition tables
1N/A
1N/AFIXME: Probably the original chapter is derived from "How It Works", so
1N/AI will rewrite this chapter.
1N/A
1N/A
1N/A@node Submitting patches
1N/A@section Where and how you should send patches
1N/A
1N/AWhen you write patches for GRUB, please send them to the mailing list
1N/A@email{bug-grub@@gnu.org}. Here is the list of items of which you
1N/Ashould take care:
1N/A
1N/A@itemize @bullet
1N/A@item
1N/APlease make your patch as small as possible. Generally, it is not a good
1N/Athing to make one big patch which changes many things. Instead,
1N/Asegregate features and produce many patches.
1N/A
1N/A@item
1N/AUse as late code as possible, for the original code. The CVS repository
1N/Aalways has the current version (@pxref{Obtaining and Building GRUB}).
1N/A
1N/A@item
1N/AWrite ChangeLog entries. @xref{Change Logs, , Change Logs, standards,
1N/AGNU Coding Standards}, if you don't know how to write ChangeLog.
1N/A
1N/A@item
1N/AMake patches in unified diff format. @samp{diff -urN} is appropriate in
1N/Amost cases.
1N/A
1N/A@item
1N/ADon't make patches reversely. Reverse patches are difficult to read and
1N/Ause.
1N/A
1N/A@item
1N/ABe careful enough of the license term and the copyright. Because GRUB
1N/Ais under GNU General Public License, you may not steal code from
1N/Asoftware whose license is incompatible against GPL. And, if you copy
1N/Acode written by others, you must not ignore their copyrights. Feel free
1N/Ato ask GRUB maintainers, whenever you are not sure what you should do.
1N/A
1N/A@item
1N/AIf your patch is too large to send in e-mail, put it at somewhere we can
1N/Asee. Usually, you shouldn't send e-mail over 20K.
1N/A@end itemize