⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 internals.texi

📁 i386的bootloader源码grub
💻 TEXI
字号:
@node Internals@chapter Hacking GRUBThis chapter documents the user-invisible aspect of GRUB.As a general rule of software development, it is impossible to keep thedescriptions of the internals up-to-date, and it is quite hard todocument everything. So refer to the source code, whenever you are notsatisfied with this documentation.  Please assume that this gives justhints 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 componentsGRUB consists of two distinct components, called @dfn{stages}, which areloaded at different times in the boot process. Because they runmutual-exclusively, sometimes a memory area overlaps with anothermemory area. And, even in one stage, a single memory area can be usedfor various purposes, because their usages are mutually exclusive.Here is the memory map of the various components:@table @asis@item 0 to 4K-1BIOS and real mode interrupts@item 0x07BE to 0x07FFPartition table passed to another boot loader@item down from 8K-1Real mode stack@item 0x2000 to ?The optional Stage 1.5 is loaded here@item 0x2000 to 0x7FFFCommand-line buffer for Multiboot kernels and modules@item 0x7C00 to 0x7DFFStage 1 is loaded here by BIOS or another boot loader@item 0x7F00 to 0x7F42LBA drive parameters@item 0x8000 to ?Stage2 is loaded here@item The end of Stage 2 to 416K-1Heap, in particular used for the menu@item down from 416K-1Protected mode stack@item 416K to 448K-1Filesystem buffer@item 448K to 479.5K-1Raw device buffer@item 479.5K to 480K-1512-byte scratch area@item 480K to 512K-1Buffers for various functions, such as password, command-line, cut andpaste, and completion.@item The last 1K of lower memoryDisk swapping code and data@end tableSee the file @file{stage2/shared.h}, for more information.@node Embedded data@section Embedded variables in GRUBStage 1 and Stage 2 have embedded variables whose locations arewell-defined, so that the installation can patch the binary filedirectly without recompilation of the stages.In Stage 1, these are defined:@table @code@item 0x3EThe version number (not GRUB's, but the installation mechanism's).@item 0x40The boot drive. If it is 0xFF, use a drive passed by BIOS.@item 0x41The flag for if forcing LBA.@item 0x42The starting address of Stage 2.@item 0x44The first sector of Stage 2.@item 0x48The starting segment of Stage 2.@item 0x1FEThe signature (@code{0xAA55}).@end tableSee the file @file{stage1/stage1.S}, for more information.In the first sector of Stage 1.5 and Stage 2, the block lists arerecorded 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 first8-byte block list is not read here, but after the pointer is decremented8 bytes, then after reading it, it decrements again, reads, and so on,until it is finished. The terminating condition is when the number ofsectors 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 justbefore the @code{firstlist} label. Note that it is always from thebeginning 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 tableSee the file @file{stage2/asm.S}, for more information.@node Filesystem interface@section The generic interface for filesystemsFor any particular partition, it is presumed that only one of the@dfn{normal} filesystems such as FAT, FFS, or ext2fs can be used, sothere is a switch table managed by the functions in@file{disk_io.c}. The notation is that you can only @dfn{mount} one at atime.The block list filesystem has a special place in the system. In additionto the @dfn{normal} filesystem (or even without one mounted), you canaccess disk blocks directly (in the indicated partition) via the blocklist notation. Using the block list filesystem doesn't effect any otherfilesystem mounts.The variables which can be read by the filesystem backend are:@vtable @code@item current_driveThe current BIOS drive number (numbered from 0, if a floppy, andnumbered from 0x80, if a hard disk).@item current_partitionThe current partition number.@item current_sliceThe current partition type.@item saved_driveThe @dfn{drive} part of the root device.@item saved_partitionThe @dfn{partition} part of the root device.@item part_startThe current partition starting address, in sectors.@item part_lengthThe current partition length, in sectors.@item print_possibilitiesTrue when the @code{dir} function should print the possible completionsof a file, and false when it should try to actually open a file of thatname.@item FSYS_BUFFilesystem buffer which is 32K in size, to use in any way which thefilesystem backend desires.@end vtableThe variables which need to be written by a filesystem backend are:@vtable @code@item fileposThe current position in the file, in sectors.@strong{Caution:} the value of @var{filepos} can be changed out fromunder the filesystem code in the current implementation. Don't depend onit being the same for later calls into the backend code!@item filemaxThe length of the file.@item disk_read_funcThe value of @var{disk_read_hook} @emph{only} during reading of datafor the file, not any other fs data, inodes, FAT tables, whatever, thenset to @code{NULL} at all other times (it will be @code{NULL} bydefault). If this isn't done correctly, then the @command{testload} and@command{install} commands won't work correctly.@end vtableThe functions expected to be used by the filesystem backend are:@ftable @code@item devreadOnly read sectors from within a partition. Sector 0 is the first sectorin the partition.@item grub_readIf the backend uses the block list code, then @code{grub_read} can beused, after setting @var{block_file} to 1.@item print_a_completionIf @var{print_possibilities} is true, call @code{print_a_completion} foreach possible file name. Otherwise, the file name completion won't work.@end ftableThe functions expected to be defined by the filesystem backend aredescribed at least moderately in the file @file{filesys.h}. Their usageis 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 thefilesystem, 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'tget corrupted by the open/read (i.e. multiple opens and/or reads will bedone with only one mount if in the same filesystem).@node Command interface@section The generic interface for built-insGRUB built-in commands are defined in a uniformal interface, whetherthey are menu-specific or can be used anywhere. The definition of abuiltin command consists of two parts: the code itself and the table ofthe information.The code must be a function which takes two arguments, a command-linestring and flags, and returns an @samp{int} value. The @dfn{flags}argument specifies how the function is called, using a bit mask. Thereturn value must be zero if successful, otherwise non-zero. So it isnormally 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 pointerto the function, flags, a short description of the command and a longdescription of the command. Since the descriptions are used only forhelp messages interactively, you don't have to define them, if thecommand may not be called interactively (such as @command{title}).The table is finally registered in the table @var{builtin_table}, sothat @code{run_script} and @code{enter_cmdline} can find thecommand. See the files @file{cmdline.c} and @file{builtins.c}, for moredetails.@node Bootstrap tricks@section The bootstrap mechanism used in GRUBThe disk space can be used in a boot loader is very restricted becausea MBR (@pxref{MBR}) is only 512 bytes but it also contains a partitiontable (@pxref{Partition table}) and a BPB. So the question is how tomake 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, andplace Stage 2 in a filesystem. The optional Stage 1.5 can be installedin 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 smalland the sectors right after a MBR is normally an unused region. The sizeof 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 ifStage 1 needs not to support the user interface or the filesysteminterface, it is impossible to make Stage 1 less than 400 bytes, becauseGRUB should support both the CHS mode and the LBA mode (@pxref{Low-leveldisk I/O}).The solution used by GRUB is that Stage 1 loads only the first sector ofStage 2 (or Stage 1.5) and Stage 2 itself loads the rest. The flow ofStage 1 is:@enumerate@itemInitialize the system briefly.@itemDetect the geometry and the accessing mode of the @dfn{loading drive}.@itemLoad the first sector of Stage 2.@itemJump to the starting address of the Stage 2.@end enumerateThe flow of Stage 2 (and Stage 1.5) is:@enumerate@itemLoad the rest of itself to the real starting address, that is, thestarting address plus 512 bytes. The block lists are stored in the lastpart of the first sector.@itemLong jump to the real starting address.@end enumerateNote that Stage 2 (or Stage 1.5) does not probe the geometryor the accessing mode of the @dfn{loading drive}, since Stage 1 hasalready probed them.@node I/O ports detection@section How to probe I/O ports used by INT 13HFIXME: I will write this chapter after implementing the new technique.@node Memory detection@section How to detect all installed RAMFIXME: 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 interruptsFIXME: 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 RecordFIXME: Likewise.@node Partition table@section The format of partition tablesFIXME: Probably the original chapter is derived from "How It Works", soI will rewrite this chapter.@node Submitting patches@section Where and how you should send patchesWhen 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 youshould take care:@itemize @bullet@itemPlease make your patch as small as possible. Generally, it is not a goodthing to make one big patch which changes many things. Instead,segregate features and produce many patches.@itemUse as late code as possible, for the original code. The CVS repositoryalways has the current version (@pxref{Obtaining and Building GRUB}).@itemWrite ChangeLog entries. @xref{Change Logs, , Change Logs, standards,GNU Coding Standards}, if you don't know how to write ChangeLog.@itemMake patches in unified diff format. @samp{diff -urN} is appropriate inmost cases.@itemDon't make patches reversely. Reverse patches are difficult to read anduse.@itemBe careful enough of the license term and the copyright. Because GRUBis under GNU General Public License, you may not steal code fromsoftware whose license is incompatible against GPL. And, if you copycode written by others, you must not ignore their copyrights. Feel freeto ask GRUB maintainers, whenever you are not sure what you should do.@itemIf your patch is too large to send in e-mail, put it at somewhere we cansee. Usually, you shouldn't send e-mail over 20K.@end itemize

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -