首先,这里有必要介绍一下grub工具项如何实现efi格式文件组装。
grub2源代码:https://ftp.gnu.org/gnu/grub
下面是grub工具箱的一些常见命令:
工具名称 | 工具主要作用 | 备注 |
|---|
grub-mkimage | 核心image生成器,负责将每个模块打包,统一封装成一个efi文件。这样的EFI文件将遵从另一篇文章中描述的msdos-->PE-->COFF->section的格式的头部,并最终在PE头中所描述的偏移位前往对应第一个.text段的程序开始执行。 mkimage首先会加载grub-main打头的一个core,这个core可以具体指代为经过makefile编译后保留在/grub-core目录下的kernel.exec文件,而具体的核心代码则在/grub-core/kern中。 在grub编译时,首先会将各个core中的代码功能段编译到core目录下,由makefile打包成module格式(此时可以使用readelf命令查看各module格式的段信息,此时的编译没有完全完成,段信息中还保留了很多内容)。 完成module的编译后,使用genmod脚本去除多余的段信息,相当于使用objcopy命令将二进制文件转成mod的格式。 最终,mkimage会加载后台的kernel.image文件与各个mod文件,形成一份最终的efi文件。 | UEFI固件在启用efi文件时,默认会传导一个handler的地址和一个system table的地址给主函数。 |
grub-install | 将编译完成生成的boot.img工具加载到本机的MBR或EFI系统分区。 | |
grub-mkconfig | 配置文件生成器,其实就是根据根目录下的00_header、10_linux等几个脚本生成对应的grub.cfg文件 | |
grub-mkrescue | 用于制作可启动的ISO镜像,可以让你直接把东西D进一块U盘后直接启动 | |
grub-mkmod | 这是一个与mkimage对应的功能,不同的是,mkimage是加载kernel.img后再合并各个mod,而mkmod则是单纯将c源文件编译为mod模块文件。这一过程其实你用makefile中的对应指令来做也是一样的 | |
grub-mkfont | 字体生成器 | |
grub-file | 文件类型检测器,用于检查内核文件是否为有效的Linux内核格式 | |
grub-script-check | 脚本语法检查器,用于检查grub.cfg是否正确 | |
grub-bios-set | 专门用于BIOS平台的引导代码安装工具,核心作用是将boot.img写入磁盘的主引导记录(MBR),并将core.img嵌入到MBR之后的保留扇区中。 | |
grub-editenv | 环境变量编辑器,主要用于管理GRUB的持久化环境变量 | |
grub-fs-tester;grub-fstest;grub-glue-efi;grub-kbdcomp;grub-macbless;grub-menulst2cfg;grub-mkconfig_lib;grub-mklayout;grub-mknetdir;grub-mkpasswd-pbkdf2;grub-mkrelpath;grub-mkstandalong;grub-ofpathname;grub-probe;grub-reboot;grub-render-label;grub-script-check;grub-set-default;grub-shell;grub-shell-luks-tester;grub-shell-tester;grub-sparc64-setup;grub-syslinux2cfg; | 这里放的是一大批grub工具,放了名字在这里,暂时就不介绍功能了 | |
由前文可知,mkimage的主要作用是将各个mod格式的二进制文件拼装为一个大文件,并且将大文件的入口指向main.c中的函数。
最终的efi文件中入口函数位置在/grub-core/kern/main.c文件的grub_main函数中。
grub_main函数的主要流程:
1、进行设备初始化——grub_machine_init函数
2、进行文件校验——grub_verifiers_init
3、进行config读取——grub_load_config
4、进行模块加载——grub_load_modules
5、进行环境变量设置——grub_set_prefix_and_root
6、重定位模块空间——reclaim_module_space
7、初始化core命令——grub_register_core_commands
8、加载normal模块——grub_load_normal_mode
9、如果normal模块失败,则进入救援模式——grub_rescue_run