分类:
2007-08-08 17:43:38
1.1 Multiboot规范的背景
每一个操作系统一般都有自己的boot loader,由于这些boot loader安装与启动的用户接口都不同,所以要在同一台机器上使用多个操作系统不是容易的事情。该规范的目的定义了boot loader与操作系统之间统一的接口,任何遵循此规范的boot loader可以引导任何遵循此规范的操作系统。
1.2 Multiboot的实现
规范主要分成3个部分:
首先是关于操作系统的部分。遵循Multiboot规范的操作系统必须包括多重引导头文件(Multiboot header.h)。这个文件必须在操作系统的第一个8192字节内,这样Grub中通过:
#define MULTIBOOT_SEARCH 8192
#define MULTIBOOT_FOUND(addr, len) \
(! ((addr) & 0x3) \
&& (len) >= 12 \
&& *((int *) (addr)) == MULTIBOOT_MAGIC \
&& ! (*((unsigned *) (addr)) + *((unsigned *) (addr + 4)) \
+ *((unsigned *) (addr + 8))) \
&& (! (MULTIBOOT_AOUT_KLUDGE & *((int *) (addr + 4))) || (len) >= 32) \
&& (! (MULTIBOOT_VIDEO_MODE & *((int *) (addr + 4))) || (len) >= 48))
寻找该文件中关于操作系统的信息。文件中包括’magic’ ’flags’ ’checksum’、’header_addr’、’load_addr’、’load_end_addr’、’bss_end_addr’ 、’entry_addr’、’mode_type’、’ width’、‘height’、‘depth等字段。
其中magic用来标识多重引导头,值必须是0x1BADB002。
flagg(32位)表示操作系统需要boot loader具有的特性。
head_addr包含多重引导头的开始地址-在那里去寻找magic值的物理地址。这个字段用来同步OS Image偏移和物理地址之间的映射。
其他字段各具其作用,总之是向grub传递操作系统的相关信息和要求。
然后是Grub引导操作系统时必须设置机器状态为指定状态,例如:
在在asm.S中使用函数multi_boot()将魔数0x2BADB002放入eax中,来告诉操作系统目前是由兼容Multiboot的boot loader在进行引导;将0x8放入ebx中,0x8是boot loader即grub提供多重引导信息结构(struct multiboot_info)的32位物理地址。总之,grub按照规范来设置机器状态。
最后是grub初始化多和填充重引导信息结构(struct multiboot_info)中的结构变量,通过多重引导信息结构,grub可以与操作系统交换重要的信息,此工作在common.c中进行。
struct multiboot_info mbi定义了结构体变量mbi,然后在init_bios_info (void)函数中对其进行初始化和填充:
调用asm.S中的get_memsize()得到mbi.mem_lower(常规内存大小)和mbi.mem_upper(扩展内存大小)
gateA20(1)使gateA20由端口92或芯片组的特定程序控制,使系统速度更快。
调用get_code_end()得到mbi.mmap_addr(表示含有由BIOS提供的memory map的缓冲区的地址),得到mbi.mmap_length(表示含有由BIOS提供的memory map的缓冲区的长度),memory map列出所有可以用作正常用途的RAM。
然后得到驱动(drive)的信息,只有多重启动内核要求时才进行此操作,因为会降低启动速度。信息由mbi_drives_length(addr、number、mode)表示。
mbi.config_table = get_rom_config_table ()得到ROM配置表。
mbi.boot_loader_name = (unsigned long) "GNU GRUB " VERSION;表示boot_loader的名字(即grub)和grub的版本。
mbi.apm_table通过get_apm_info ()得到AMP(高级电源管理)表的信息。
Grub按照操作系统多重引导头文件中flag各个位的设置,将操作系统需要的信息传递给操作系统。
1.3 Multiboot流程
多重引导信息结构初始化工作由asm.S模块运行时调用init_bios_info (void)函数完成。