Grub2.04分析 |
您所在的位置:网站首页 › vmlinuxz › Grub2.04分析 |
Grub第一阶段总结
一、Grub概念简介
GNU Grub(GRand Unified Bootloader简称“Grub”)是一个来自GNU项目的多操作系统启动程序,允许用户可以在计算机内同时拥有多个操作系统,并在计算机启动时选择希望运行的操作系统。引导加载程序是计算机启动时运行的第一个软件程序,它负责加载和传输控制操作系统内核软件,之后内核依次初始化操作系统的其余部分。 使用Grub启动时,可以使用命令行界面(参见命令行界面),也可以使用菜单界面(参见菜单界面)。在菜单中,可以切换到命令行模式,反之亦然。 使用命令行界面,可以手动输入内核的驱动器规范和文件名。 在菜单界面中,该菜单基于预先准备的配置文件(参见configuration),只需使用方向键选择操作系统。
图1 图形菜单界面
图2 命令行界面 Grub使用方法GNU GRUB 手册 2.06 Grub启动阶段,按c进行shell命令行阶段: www.gnu.org/software/grub/manual/grub/grub.html#Command_002dline-and-menu-entry-commands 2.1 Grub正常启动Grub正常启动后,将进入“普通模式”,一般是显示一个菜单(找到了'$prefix/Grub.cfg'),或者直接进入Grub SHELL(没找到'$prefix/Grub.cfg')。 在普通模式中,命令模块[command.lst]与加密模块[crypto.lst]会被自动按需载入(无需使用"insmod"命令),并且可使用完整的Grub脚本功能。但是其他模块则可能需要明确使用"insmod"命令来载入。 2.1.1 Grub在BIOS平台Grub默认安装在第一个硬盘hd0的MBR上,把引导程序boot.img写入硬盘的MBR,启动时根据MBR提示找到启动分区,加载分区内的Grub核心文件core.img和配置文件Grub.cfg。(hd0,mdsom1) BIOS --> boot.img[MBR] --> core.img --> 设置"prefix root cmdpath"环境变量 --> 加载"normal.mod"模块[同时还包括依赖的 terminal crypto extcmd boot gettext 模块] --> 执行"normal $prefix/Grub.cfg"命令。 2.1.2 Grub在UEFI平台UEFI --> core.img[BOOTX64.EFI/BOOTX86.EFI] --> 设置"prefix root cmdpath"环境变量 --> 加载"normal.mod"模块[同时还包括它所依赖的 terminal crypto extcmd boot gettext 模块] --> 执行"normal $prefix/Grub.cfg"命令。 2.2 Grub版本查询查询ubuntu的Grub版本号: Grub-install --versionGrub-install -V2.3 Grub菜单加上背景图 首先制作一张PNG格式的图片,分辨率最好是"1024x768"以保证较好的兼容性。然后将这张图片放到"$prefix/themes/1024x768.png"("$prefix"是Grub的安装目录)。然后在'Grub.cfg'中加入如下内容: set gfxmode=1024x768,auto insmod gfxterm insmod png terminal_output gfxterm background_image $prefix/themes/1024x768.png 2.4 Grub显示中文界面(包括显示中文菜单项)由于Grub在内部使用UTF-8编码,并且所有文本文件(包括'Grub.cfg')也都被假定为使用UTF-8编码,为了避免乱码,请务必以UTF-8编码保存'Grub.cfg'文件。 set gfxterm_font=unicode set lang=zh_CN set locale_dir=$prefix/locale insmod gfxterm terminal_output gfxterm loadfont unicode 2.5 更改Grub的字体如果默认的unicode字体在1024x768或更高分辨率的屏幕上显得太小,或者默认的字体不好看,可以使用"Grub-mkfont"工具。下面的示例展示了制作一个24px大小的pf2字体: Grub-mkfont -i1 -n WenQuanYiMicroHeiMono24px -o WenQuanYiMicroHeiMono24px.pf2 -s24 -v wqy-microhei.ttc 将制作好的字体文件(WenQuanYiMicroHeiMono24px.pf2)放到"$prefix/fonts"目录中,修改'Grub.cfg'文件中的两行: set gfxterm_font=WenQuanYiMicroHeiMono24px loadfont WenQuanYiMicroHeiMono24px 2.6 Grub-2.0.6版本官方模块模块间的依赖关系位于"moddep.lst"文件中。 2.6.1 命令模块[command.lst]提供了各种不同的功能,类似标准Unix命令。 insmod module:载入名为"module"的Grub模块。 set [envvar=value]:将环境变量"envvar"的值设为'value'。如果没有使用参数,则打印出所有环境变量及其值。 help [pattern …]:显示内建命令的帮助信息。如果没有指定"pattern",那么将显示所有可用命令的简短描述。如果指定了"pattern",那么将只显示名字以这些"pattern"开头的命令的详细帮助信息。 halt [--no-apm]:关闭计算机。如果指定了 --no-apm 选项,表示不执行APM BIOS调用。否则,计算机使用APM关闭。 boot:启动已经被载入的OS或链式加载器。仅在运行于交互式命令行的时候才是需要的。在一个菜单项结束时是隐含的。 cat [--dos] file:显示文件"file"的内容。如果使用了"--dos"选项,那么"回车/换行符"将被显示为一个简单的换行符。否则,回车符将被显示为一个控制符()。 ls [arg …]:如果不使用参数,那么列出所有对Grub已知的设备。 如果参数是包含在括号内的一个设备名,那么列出该设备根目录下的所有文件。 如果参数是以绝对路径给出的目录,那么列出这个目录的内容。 lsmod:列出已经加载的所有模块 normal_exit:退出当前的普通模式。如果这个普通模式实例不是嵌套在另一个普通模式里的话,就会返回到救援模式。 2.6.2 加密模块[crypto.lst]提供了各种数据完整性校验与密码算法支持,一共20多个。例如:gcry_rijndael crc64 gcry_md5 ... 2.6.3 文件系统模块[fs.lst]提供了访问各种文件系统的功能,一共30多个。例如:btrfs cpio exfat ext2 fat iso9660 ntfs tar xfs zfs ... 2.6.4 分区模块[partmap.lst]提供了识别各种分区格式的功能,一共10多个。例如:part_bsd part_gpt part_msdos ... 2.6.5 分区工具[parttool.lst]提供了操作各种分区格式的功能,目前只有 msdospart 这一个。 2.6.6 终端模块[terminal.lst]提供了各种不同终端的支持,一共不到10个。例如:serial gfxterm vga_text at_keyboard ... 2.6.7 视频模块[video.lst]提供了各种不同的视频模式支持,一共6个。例如:vga vbe efi_gop efi_uga ... 2.6.8 其他模块所有未在上述分类文件中列出的模块都归为这一类,一共将近100个。值得关注的有以下几个: "all_video"可用于一次性加载当前所有可用的视频模块; "gfxmenu"可用于提供主题支持; "jpeg png tga"可用于提供特定格式的背景图片支持; "xzio gzio lzopio"可用于提供特定压缩格式支持(常配合"initrd"命令使用); 2.7 Grub救援模式Rescue进入救援模式,这意味着Grub由于某种原因未能加载“模块”或者Grub没有在正确的位置读取。 # Inspect the current prefix (and other preset variables): set 可以输入set查看一下当前信息 # Find out which devices are available: ls 查看Grub位置 # Set to the correct value, which might be something like this: set prefix=(hd0)/Grub set root=(hd0) insmod normal normal 回到引导界面上 Grub配置文件 3.1 Grub配置文件生成与更新Grub-mkconfig脚本自动生成 /boot/Grub/Grub.cfg,不需要手动修改。 # Grub-mkconfig -o /boot/Grub/Grub.cfg /etc/Grub.d/脚本包含 Grub 菜单信息和操作系统引导脚本,运行 update-grub 命令时,它会读取 Grub 文件和 Grub.d 脚本的内容,并更新创建Grub.cfg文件。 3.2 Grub配置文件详解下图为在Linux系统下,/etc/default/Grub内包含的自定义Grub配置文件。
(1)Grub_DEFAULT 默认的菜单项,默认值为0。其值可为数值N,表示从0开始计算的第N项是默认菜单 也可以指定对应的title表示该项为默认的菜单项。使用数值比较好,因为使用的title可能包含了容易改变的设备名 (2)Grub_SAVEDEFAULT 默认该key的值未设置。如果该key的值设置为true时,如果选定了某菜单项,则该菜单项将被认为是新的默认菜单项。该key只有在设置了"Grub_DEFAULT=saved"时才有效。 (3)Grub_TIMEOUT 在开机选择菜单项的超时时间,超过该时间将使用默认的菜单项来引导对应的操作系统。 默认值为5秒。等待过程中,按下任意按键都可以中断等待。 设置为0时,将不列出菜单直接使用默认的菜单项引导与之对应的操作系统,设置为"-1"时将永久等待选择。 (4)Grub_TIMEOUT_STYLE 如果该key未设置值或者设置的值为"menu",则列出启动菜单项,并等待"Grub_TIMEOUT"指定的超时时间。 如果设置为"countdown"和"hidden",则不显示启动菜单项,而是直接等待"Grub_TIMEOUT"指定的超时时间。如果超时了则启动默认菜单项并引导对应的操作系统 (5)Grub_BACKGROUND 设置背景图片,背景图片必须是Grub可读的,图片文件名后缀必须是".png"、".tga"、".jpg"、".jpeg",在需要的时候,Grub会按比例缩小图片的大小以适配屏幕大小。 (6)Grub_THEME 设置Grub菜单的主题。 四、Grub源码分析 4.1 Grub源代码下载Grub源代码下载地址:https://ftp.gnu.org/gnu/Grub/,如下图所示根据系统编译环境选择需要的Grub源代码。 4.2 Grub源代码文件简介 本次选择下载Grub-2.06.tar.gz
在终端输入 tar zxvf Grub-2.06.tar.gz解压文件,进入Grub-2.06文件夹
asm-tests:这里面是几个汇编代码文件; build-aux:包含了编译时可能用到的脚本; conf:编译需要用的文件,make的时候会用到; docs:帮助文件,还有Grub.cfg示例模板; Grub-core:Grub的主体核心代码; include:Grub主体的头文件; m4:包含m4文件,configure的时候会使用到; po:这个目录下主要由两种文件,一种时.po文件,另一种时.gmo文件。它们是用来支持多语言的,这个文件夹内的东西不要管,只是对代码做一些基本的注释; tests:一些测试的脚本; themes:Grub界面的主题; unicode:Unicode数据; util:一些工具源的文件。 启动时运行的代码在' Grub-core '的子目录中,在启动完整操作系统后运行的代码在顶层的子目录中。 4.3 Grub核心代码详解Grub内核在' Grub -core/kern/ '中,它包含一些核心工具,比如设备、磁盘和文件框架、环境变量处理、列表处理等等。 Grub-2.06/Grub-core/kern/main.c 调用其它外部函数(没有在 main.c 中定义的); Grub-2.06/Grub-core/kern/ 目录下的其它源文件,分别提供这些外部函数的定义(实现了这些函数的具体功能); Grub-2.06/include/Grub/ 目录下的头文件,则对应这些外部函数的声明; Grub-2.06/Grub-core/kern/ 目录下的与这些头文件与同名的 C 源文件;定义main.c 包含的这 12 个头文件,全部位于Grub-2.06/include/Grub/ 目录下。 终端实现在' Grub-core/term/ '中。 磁盘访问代码分布在' Grub-core/ Disk / '(用于访问磁盘设备本身),' Grub-core/partmap/ '(用于解释分区表数据),和' Grub-core/fs/ '(用于访问文件系统)。注意,除了一些特殊的例外,Grub只包含从文件系统读取的代码,并试图避免包含任何要写入文件系统的代码;这让我们可以放心地向用户保证,Grub不会导致文件系统损坏。 PCI和USB总线处理在' Grub-core/bus/ '中。 视频处理代码在' Grub-core/ Video / '中,图形化菜单系统大量使用这个功能。 大多数命令都是通过' Grub-core/commands/ '中的文件实现的。 在Grub_main之前,有一段汇编代码: start: _start: movq %rcx, EXT_C(Grub_efi_image_handle)(%rip) movq %rdx, EXT_C(Grub_efi_system_table)(%rip) andq $~0xf, %rsp call EXT_C(Grub_main) 进入Grub源代码,执行Grub_main函数。 Grub编译与安装 5.1 卸载Grub卸载掉旧的Grub:apt-get purge Grub-pc。 5.2 UEFI模式下编译生成GrubGrub使用Autoconf和Automake,大部分Automake输入由Python脚本生成。顶级构建规则在' configuration .ac '中,‘Grub-core / Makefile.core.def’,‘Makefile.util.def’。' *.def '文件中的每个块代表一个构建目标,并指定用于在不同平台上构建该目标的源文件。' *.def '文件被' gentpl.py '处理成Automake输入。 使用configure工具生成Makefile文件时: ./autogen.sh 生成configure文件 ./configure --prefix=/usr(安装目录) --with-platform=efi(指定平台pc/uefi) --target=x86_64(指定目标的处理器架构类型,或i386) --sysconfdir=/etc(配置文件目录) --disable-werror(不把报警归结于错误) make -j4让make最多允许4个编译命令同时执行,这样可以更有效的利用CPU资源 make install 安装编译生成的文件 Grub-install /dev/sda 安装到启动盘 sudo update-Grub 更新grub配置文件 5.2.1 制作一个BOOT.EFI可启动镜像在make install之后 #grub-mkimage -O x86_64-efi -d ./grub-core/ -p /boot/EFI/BOOT/ -o bootx64.EFI boot reboot linux part_gpt part_msdos disk fat exfat ext2 ntfs xfs hfs iso9660 normal search_fs_file configfile chain loopback echo efi_gop file gfxterm gfxterm_background gfxterm_menu halt help ls png true UEFI启动是通过/boot/EFI/BOOT/xxxx.EFI来启动grub引导。 参数解析如下: -d 表示指定查找模块目录 -p 设置gurb目标文件的文件夹,cfg文件中会调用。 -o 表示生成的目标文件 bootx64.efi -O 表示集成的平台模块 写 i386-pc x86_64-efi BOOTx64.EFI后面全是命令模块,可以根据自己的需求进行添加。 拷贝到指定位置 # cp BOOTx64.EFI /boot/EFI/BOOT/ # reboot 重启就可以使用新编译的BOOTx64.EFI进行引导内核启动了。 grub.cfg修改启动主要配置项解析 配置项 解析 default 指grub启动时默认菜单项,表示默认从哪个菜单启动。默认配置为0。 timeout 指菜单到自动启动系统前停留时间,单位时间为sec。 title 指一个启动操作系统的名称。 root 指相应内核镜像所在目录boot所在的磁盘分区 如:root=‘hd0,msdos1’。 linux 指boot目录下内核镜像的名称。 initrd 指linux的initial ramdisk在boot目录下的名称。 boot 指引导内核进行启动。 gurb2命令说明 命令 说明 grub-editenv 编译环境块工具 grub-mkfont 设置grub使用的字体 grub-mkimage 生成一个gurb的可启动镜像 grub-mkrescue 生成一个适用于软盘的grub的可启动镜像 grub-install 在磁盘上安装grub grub-mkconfig 生成grub配置文件 grub-mkdevicemap 生成一个新的device map文件 grub-probe 扫描计算机收集磁盘和分区信息 grub-set-default 配置默认启动项 grub-reboot 配置重启之后的默认启动项 5.3 Grub中Makefile的指令 5.3.1 clean清除当前目录下在 make 过程中产生的文件。它不能删除软件包的配置文件,也不能删除 build 时创建的那些文件。 5.3.2 distclean类似于"clean",删除当前目录下的的配置文件、build 过程产生的文件。 5.3.3 info产生必要的 Info 文档。 5.3.4 check 或 test完成所有的自检功能。在执行检查之前,应确保所有程序已经被创建(但可以尚未安装)。为了进行测试,需要实现在程序没有安装的情况下被执行的测试命令。 5.3.5 install完成程序的编译并将最终的可执行程序、库文件等拷贝到指定的目录。此种安装一般不对可执行程序进行 strip 操作。 5.3.6 install-strip和"install"类似,但是会对复制到安装目录下的可执行文件进行 strip 操作。 5.3.7 uninstall删除所有由"install"安装的文件。 5.3.8 installcheck执行安装检查。在执行安装检查之前,需要确保所有程序已经被创建并且被安装。 5.3.9 installdirs创建安装目录及其子目录。它不能更改软件的编译目录,而仅仅是创建程序的安装目录。 5.4 Grub编译Grub源代码不需要修改makefile文件,添加新的.c和.h文件后,需要修改配置文件。如果添加一个新的模块遵循现有的模式,比如一个新的命令或一个新的文件系统,只需要修改两个文件内容。 此处修改Hello模块命令代码,新增对硬盘文件读取与SM3度量,文件内容为abc。 5.4.1 Grub-core/Makefile.core.am Platfor_PROGRAMS ************* *.marker:** 5.4.2 Grub-core/Makefile.core.def添加新的模块 Module = { Name = cmd; Common = cmd/cmd.c; }; 5.4.3 hello模块Grub源代码在发布时候,给出了一个测试指令模块,hello.mod。如果在Grub界面,按c进入命令模式,输入hello,会得到下图:
添加类似hello这类命令时,按照上述方式,在Grub-core/目录下添加ptest文件夹,加入ptest.c文件,修改Makefile文件即可添加命令模块。 5.4.4 在main函数中新增功能 需要在makefile.core.def中,在126行以后添加到kern中 common = kern/模块.c 会自动将文件与main.c一起编译 Grub文件介绍 6.1 /Boot目录vmlinuz是可引导的、压缩的内核。“vm”代表“Virtual Memory”。Linux支持虚拟内存, zImage(vmlinuz)和bzImage(vmlinuz)都是用gzip压缩的。它们不仅是一个压缩文件,而且在这两个文件的开头部分内嵌有 gzip解压缩代码。 vmlinux是未压缩的内核,vmlinuz是vmlinux的压缩文件。 initrd是文件系统,“initial ramdisk”的简写,initrd一般被用来临时地引导硬件到实际内核vmlinuz能够接管并继续引导的状态。 System.map是内核符号映射表,顾名思义就是将内核中的符号(也就是内核中的函数)和它的地址能联系起来的一个列表。 6.2 /Boot/Grub目录[root@study ~]# ls -l /boot/Grub -rw-r--r--. device.map |
今日新闻 |
推荐新闻 |
CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3 |