GRUB2启动和组成结构2011-11-05 21:07:48
分类: LINUX 1.1 GRUB2特色
本文所用GRUB2版本为1.99,GRUB2是为了取代GRUB而完全重写的第二版,引用:
GRUB2采用模块化动态加载的思想,相比GRUB来讲不用在构建时将所有功能都加入,这使得GRUB2的体积相比变得很小,整个GRUB2的内核映像可以控制在31KB以内(GRUB的映像在百KB级别),因此GRUB2完全可以移除GRUB中存在的stage 1.5阶段,而可以将整个映像放在GRUB中的stage1.5存放的位置。 1.2 X86 GRUB2启动流程 GRUB2在X86上的启动肯定也没什么独特的地方,此处再累述一下: 1) 上电 -> BIOS 上电后,硬件电路产生RESET信号并经复位引脚输入给CPU,CPU进入实模式,CS寄存器默认值为0xF000,IP寄存器默认值为0xFFF0,即跳转至0xFFFF0物理地址处执行第一条指令,0xFFFF0物理地址(ROM)存放的是BIOS执行代码,BIOS完成上电POST、BIOS中断调用等初始化,最终读取主引导扇区的512B的数据至0x7C00物理内存地址开始处,并跳转至0x7C00处执行代码;
主引导扇区512B数据格式: a) 0x000 ~ 0x1BD:占446B,为MBR引导代码; b) 0x1BE ~ 0x1FD:占64B,4组磁盘分区表信息(DPT),每组分区信息占16B(这也 是为什么最多有4个主分区);以第一个分区为例,16B大小的分区字段如下:
c) 0x1FE ~ 0x1FF:结束标志,0x55和0xAA;
早期的硬盘采用盘片和磁头组成,每个盘片有2个盘面,每个盘面对应有1个磁头,当硬盘访问数据时,磁头在盘面上移动来读取数据;每个盘面由很多同心圆组成,每1个同心圆称作一个磁道,每个磁道逻辑上划分为63个扇区(实际的物理存储不是这样的结构),磁盘访问数据以扇区为单位;所有面的相同位置的同心圆构成柱面,早期CHS(Cylinder柱面、Head磁头、扇区Sector)寻址就是根据这样的结构产生的;
硬盘在使用中,0面的0磁道的所有扇区即前63个扇区做为特殊用途,BIOS和操作系统不放置任何数据于此(例如,第一个引导扇区一般位于第64个扇区,一般做为bootloader使用,这也是为什么GRUB必须使用stage1.5的原因(因为其大小一般为100KB左右,超出了62个扇区的限制)。 2) BIOS -> MBR(GRUB2 boot.img) 此场景中MBR引导代码即GRUB2的boot/i386/pc/boot.S编译出来的代码,称为boot.img;代码执行位置即0x7C00,主要行为:设置堆栈指针为0x2000处,探测硬盘CHS/LBA工作模式,并加载第二个扇区最终至0x8000处,并跳至0x8000执行;
另附PC机的头1MB内存空间分布(摘自documentation/i386/boot.txt): | | 0A0000 +------------------------+ | Reserved for BIOS | Do not use. Reserved for BIOS EBDA. 09A000 +------------------------+ | Stack/heap/cmdline | For use by the kernel real-mode code. 098000 +------------------------+ | Kernel setup | The kernel real-mode code. 090200 +------------------------+ | Kernel boot sector | The kernel legacy boot sector. 090000 +------------------------+ | Protected-mode kernel | The bulk of the kernel image. 010000 +------------------------+ | Boot loader | <- Boot sector entry point 0000:7C00 001000 +------------------------+ | Reserved for MBR/BIOS | 000800 +------------------------+ | Typically used by MBR | 000600 +------------------------+ | BIOS use only | 000000 +------------------------+
由上述结构可知,bootloader约定使用0x1000~0x10000内存段; 3) GRUB2 boot.img-> GRUB2 diskboot.img (第2个扇区) 第二个扇区代码由boot/i386/pc/diskboot.S编译生成,称为diskboot.img; boot.img最终加载diskboot.img至0x8000处,并跳至0x8000处执行代码; 4) GRUB2 diskboot.img -> GRUB2 kernel.img(第3~ n个扇区, n<63) diskboot.img的作用是读取GRUB2的内核kernel.img(由kern\下的文件生成)至内存的某位置处;diskboot.img的组成: a) 0x0~0x147:共328B,指令; b) 0x148~0x1FF:共184B,用来保存数据集;每个数据集为12B,可以保存15个数据集;12B的数据集结构:其中0~7B表示起始扇区数,8~9B表示扇区数,10~11B表示目的段地址即kernel.img放在内存中的位置(通常都是0x8200),都在生成镜像(grub-mkimage)时确定;
这样diskboot.img会根据数据集的数据来确定kernel.img在硬盘上的存放位置和内存放置地址;kernel.img是经过压缩的,映像开头是i386/pc/startup.S和i386/pc/lzma_decode.S启动和lzma解压缩代码(7zip的压缩算法)代码以便用以解压缩(类似于bzImage的处理),进入保护模式,并解压至0x10000处,最终再将解压后的代码搬至0x8200处执行(0x8200~0x10000之间,不能超过0x10000内存地址),此时CPU已经是保护模式了,最终调用kern/main.c中的grub_main (),代码如下:
主要工作:初始化系统,加载模块,并进入normal或者rescue模式,GRUB2会根据配置文件或者用户输入,加载操作系统并运行;调用grub_load_modules()来加载所有的模块,这就是GRUB2扩展性能的体现之一。 1.3 GRUB2编译和安装编译: 进入grub-1.99/目录: 1) ./configure --prefix=/xlpang/grub_install --exec-prefix=/xlpang/grub_install/ CC=/opt/zte/x86_64_gcc4.1.2_glibc2.5.0/bin/x86_64-pc-linux-gnu-gcc CFLAGS=-static 2) make 3) make install 执行完毕后(注意用户权限),进入/xlpang/grub_install/就可以看到grub2的安装文件了。
安装: 登录目标PC机器,假设/dev/sda1已挂载到/目录, 1) 将grub_install/拷至/xlpang/中(安装时的放置路径需确保和编译时的路径一致;也可以 修改/xlpang/grub_install/sbin/ grub-install脚本文件开头的变量路径),执行: /xlpang/grub_install/sbin/grub-install --no-floppy /dev/sda命令将grub2安装到sda硬盘第一个分区的/boot目录下,并将boot.img, diskboot.img和kernel.img写入其相应扇区中,其它文件安装在/boot/grub/目录下。 2) 生成/boot/grub/grub.cfg文件(在/boot/目录下放置bzImage内核映像): 编辑/xlpang/grub_install/etc/grub.d/40_custom文件,增加: menuentry "linux_x86_64-2.6.21" { set root=(hd0,1) linux /boot/bzImage ro initrd /boot/initramfs } 3) 执行:/home/grub-mkconfig -o /boot/grub/grub.cfg
注:如果存在GRUB,将GRUB2安装至GRUB相同的目录,主机启动后仍然加载GRUB界面,即GRUB2兼容GRUB; 解决办法:将原来的GRUB安装目录移除或改名后再安装GRUB2至此目录。 1.4 GRUB2映像示例 安装好GRUB2后,可以验证下数据看看是否安装成功,有助于形成GRUB2更进一步的认识,以PC机为例: 1) 提取boot.img映像:dd if=/dev/sda of=boot.img bs=512 count=1
执行“cat boot.img”后发现有“GRUB GeomHard DiskRead Error”输出,见boot.S 2) 提取diskboot.img映像:dd if=/dev/sda of=boot.img bs=512 count=1 skip=1
执行“cat diskboot.img”后发现有“loading. ”和“GeomRead Error”输出,见diskboot.S; 另外,最后一行表示的含义: a) 起始扇区LBA地址: 0x0000 0000 0000 0002即第三个扇区开始存放的是kernel.img b) 扇区数: 0x003c即60*512=30KB c) 目的段地址: 0x0820即内存0x8200处(放置kernel.img)
3) 根据2)中的信息提取GRUB2的kernel.img映像: dd if=/dev/sda of=kernel.img bs=1k count=30 skip=1 |
|
来自: clover_xian > 《我的图书馆》