转载时请注明出处和作者联系方式作者联系方式:diablo_work at 126 dot com
Grub为了减少内核的大小,采用了Module的设计。根据需要,动态导入的方法。Module的使用又可以分为两种,一种是在grub还没有文件系统知识时需要使用的,这部分Module是被“原模原样”、连续的写到磁盘上的,是紧跟在kernel.img后面的。该部分典型的就是文件系统Module,例如在linux系统上使用的ext2.mod。另一种是在grub已经具备文件系统知识的情况下,将module以文件的方式在保存在磁盘上的。典型的是normal.mod(关于这部分模块后面还会讲)。
现在grub的开始执行kernel.img中的内容。前面提到过,kernel.img中的内容是压缩后放到磁盘上的,但压缩的东西是不可执行的,需要解压缩后才能执行。但由谁来解压缩呢,grub是这样实现的:kernel.img的前0x 4A 0个字节是不进行压缩的,该部分不压缩的代码对应为kern/i386/pc/startup.S。startup.S的有两个主要任务,1.解压缩内核,将控制权交到grub的内核,也就是将是将控制权交到kern/main.c的grub_main函数。2.提供一些例程。主要是一些很难用c写的代码,比如实模式和保护模式的相互切换。
为便于说明,在原有的英文注释的基础上再增加一些注释。
_start:
/*
* Guarantee that "main" is loaded at 0x0:0x8200.
*/
ljmp $0, $ABS(codestart)
/* the real mode code continues... */
codestart:
cli /* we're not safe here! */
/* set up %ds, %ss, and %es */
/*寄存器ax,ds,ss,es清零*/
xorw %ax, %ax
movw %ax, %ds
movw %ax, %ss
movw %ax, %es
/* set up the real mode/BIOS stack */
movl $GRUB_MEMORY_MACHINE_REAL_STACK, %ebp
movl %ebp, %esp
sti /* we're safe again */
/* save boot drive reference */
/*dl保存当前的磁盘驱动器号,可参考boot.S中的代码*/
ADDR32 movb %dl, EXT_C(grub_boot_drive)
/* reset disk system (%ah = 0) */
int $0x13
/* transition to protected mode */
DATA32 call real_to_prot
/* The ".code32" directive takes GAS out of 16-bit mode. */
.code32
incl %eax
/*关于a20的问题,可在网上参考,有很多,肯定比我讲得好。*/
call EXT_C(grub_gate_a20)
/* decompress the compressed part and put the result at 1MB */
/* START_SYMBOL 的值应该等于_start ,也就是0x8200*/
/* GRUB_KERNEL_MACHINE_RAW_SIZE 的值代表Startup.S代码编译过后的大小*/
/*解压缩后的内容暂时放在0: 0x100000处*/
movl $0x100000, %esi
movl $(START_SYMBOL + GRUB_KERNEL_MACHINE_RAW_SIZE), %edi
/*参数压栈*/
pushl %esi
pushl EXT_C(grub_compressed_size)
pushl %edi
call lzo1x_decompress
/*调用者负责清理堆栈*/
addl $12, %esp
/* copy back the decompressed part */
/*查看函数的lzo1x_decompress实现,可以发现,在调用lzo1x_decompress 前后,寄存器ds:esi,es:edi的值不会发生改变,此处将解压缩后代码拷贝到startup.S的后面*/
movl %eax, %ecx
cld
rep
movsb
/* copy modules before cleaning out the bss */
/*将紧跟在解压缩后的module放到kernel的后面*/
movl EXT_C(grub_total_module_size), %ecx
movl EXT_C(grub_kernel_image_size), %esi
addl %ecx, %esi
addl $START_SYMBOL, %esi
decl %esi
movl $END_SYMBOL, %edi
addl %ecx, %edi
decl %edi
std
rep
movsb
/* clean out the bss */
movl $BSS_START_SYMBOL, %edi
/* compute the bss length */
movl $END_SYMBOL, %ecx
subl %edi, %ecx
/* clean out */
xorl %eax, %eax
cld
rep
stosb
/*
* Call the start of main body of C code.
*/
call EXT_C(grub_main)
待续。。。