Grub2.04分析

您所在的位置:网站首页 vmlinuxz Grub2.04分析

Grub2.04分析

#Grub2.04分析| 来源: 网络整理| 查看: 265

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 -V

 

2.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模式下编译生成Grub

Grub使用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