Grub Multiboot规范

        因为自己最近在尝试着写一个简单的小型操作系统(跟着JamesM’skernel学习),所以没有自己写引导程序,而是用的grub作为引导来加载OS,所以在写程序的时候就要求代码符合Multiboot规范,然后就看了一下文档,感觉内容挺多的,就决定自己将规范简化一下(提前声明,这篇博客中只是介绍了我自己编程中用到的一些知识,可能不全面,如果大家还想看更多详细的,下面是网址: http://www.cnblogs.com/chio/archive/2008/01/01/1022430.html),总结一下。
1、Multiboot规范诞生的背景
    在机器上安装一个新的操作系统意味着要引入一套全新的引导机制,每种的安装和运行界面都不相同。使多个操作系统可以共存在一个机器上通常要借助链式结构,但是该机制你不能选择某个操作系统的引导或者说如果操作系统的引导不是你想要的,或者不能在你的机器上工作,那就不好了。所以开源社区的爱好者就来解决这个问题,提出了这个规范,指出了引导程序和操作系统之间的接口,这样符合引导规范的程序就可以引导任何符合规范的操作系统,所以这份规范只关心引导操作系统的接口。(当然这份规范主要面向自由操作系统设计)
2、Multiboot规范
    符合Multiboot规范的OS映象总是包含一个magicMultiboot头(参见OS映像格式),这样引导程序就不必理解种类繁多的a.out变体或者其他什么可执行格式。magic头不必位于可执行文件的最前面,这样OS 映象就可以在保持同a.out格式兼容的同时做到符合Multiboot规范。
(1)本Multiboot规范中所用术语的定义
术语“必须”表示引导程序或OS映像需要服从某一规则,否则的话,引导程序或者OS映像就不能称为符合Multiboot规范的。术语“应该”表示引导程序或OS映像最好服从某一规则,但如果没有服从也是可以的。术语“可以”表示引导程序或OS映像服从某一规则是允许的。
引导程序 
引导程序是负责载入最终的操作系统映像的一个或一组程序。引导程序本身可以由几个阶段组成,但是这属于实现细节而同本规范无关。只有引导程序最后的阶段——最终将控制权转交给操作系统的阶段——必须遵守本文中规定的规则,否则引导程序就不能称为符合Multiboot规范;在这之前的阶段可以怎么方便怎么设计。
OS映像
OS映像是引导程序载入到内存的初始二进制映像,随后引导程序会将控制权转移给它,这样就启动了操作系统。典型的OS映像是包含了操作系统内核的可执行文件。
引导模块 
引导模块是由引导程序同OS映像一同载入的其他起辅助作用的文件。引导程序并不理解这些文件,只会将它们的位置告知操作系统。
服从所有被标记为“必须”的引导程序或者OS映像被称为符合Multiboot规范。对于规范中那些被标记为“应该”或者“可以”的规则,符合Multiboot规范的引导程序或OS映像可以不必遵守。
u8 、u16、u32、 u64
无符号8位数据,无符号16位数据。因为目标架构是高位优先(little-endian)的,所以u16按照高位优先编码。无符号32位数据。因为目标架构是高位优先(little-endian)的,所以u32按照高位优先编码。无符号64位数据。因为目标架构是高位优先(little-endian)的,所以u64按照高位优先编码。
(2) Multiboot规范的精确定义
引导程序/OS映像接口主要包括三个方面:
1)引导程序看到的 OS 映像的格式。 
2)当引导程序启动操作系统时机器的状态。 
3)引导程序传递给操作系统的信息的格式。
(3)OS映像格式
一个OS映像可以是一个普通的某种操作系统使用的标准格式的32位可执行文件,不同之处是它可能被连接到一个非默认的载入地址以避开PC的I/O区域或者其它的保留区域,当然它也不能使用共享库.
除了OS映像所使用的格式需要的头之外,OS映像还必须额外包括一个Multiboot头。Multiboot头必须完整的包含在OS映像的前8192字节内,并且必须是longword(32位)对齐的。通常来说,它的位置越靠前越好,并且可以嵌入在text段的起始处,位于真正的可执行文件头之前。
(4) Multiboot的头分布
Multiboot 头的分布必须如下表所示:
偏移量 类型 域名 备注
0   u32  magic               必需
4   u32  flags                必需 
8   u32  checksum         必需 
12  u32 header_addr      如果flags[16]被置位 
16  u32 load_addr         如果flags[16]被置位 
20  u32 load_end_addr   如果flags[16]被置位 
24  u32 bss_end_addr    如果flags[16]被置位 
28  u32 entry_addr        如果flags[16]被置位 
32  u32 mode_type       如果flags[2]被置位 
36  u32 width                如果flags[2]被置位 
40  u32 height               如果flags[2]被置位 
44  u32 depth               如果flags[2]被置位
magic、flags和checksum域在头的magic域中定义,header_addr、load_addr、load_end_addr、bss_end_addr和entry_addr域在头的地址域中定义,mode_type、width、height和depth域则在头的图形域中定义。
(3) Multiboot头的 magic 域
magic 
magic域是标志头的魔数,它必须等于十六进制值0x1BADB002。
flags 
        flags域指出OS映像需要引导程序提供或支持的特性。0-15位指出需求:如果引导程序发现某些值被设置但出于某种原因不理解或不能不能满足相应的需求,它必须告知用户并宣告引导失败。16-31位指出可选的特性:如果引导程序不能支持某些位,它可以简单的忽略它们并正常引导。自然,所有flags字中尚未定义的位必须被置为0。这样,flags域既可以用于版本控制也可以用于简单的特性选择。 
如果设置了flags字中的0位,所有的引导模块将按页(4KB)边界对齐。有些操作系统能够在启动时将包含引导模块的页直接映射到一个分页的地址空间,因此需要引导模块是页对齐的。
        如果设置了flags字中的1位,则必须通过Multiboot信息结构(参见引导信息格式)的mem_*域包括可用内存的信息。如果引导程序能够传递内存分布(mmap_*域)并且它确实存在,则也包括它。
       如果设置了flags字中的2位,有关视频模式表(参见引导信息格式)的信息必须对内核有效。
       如果设置了flags字中的16位,则Multiboot头中偏移量8-24的域有效,引导程序应该使用它们而不是实际可执行头中的域来计算将OS映象载入到那里。如果内核映象为ELF格式则不必提供这样的信息,但是如果映象是a.out格式或者其他什么格式的话就必须提供这些信息。兼容的引导程序必须既能够载入ELF格式的映象也能载入将载入地址信息嵌入Multiboot头中的映象;它们也可以直接支持其他的可执行格式,例如一个a.out的特殊变体,但这不是必须的。
checksum 
         域checksum是一个32位的无符号值,当与其他的magic域(也就是magic和flags)相加时,结果必须是32位的无符号值0(即magic+ flags + checksum = 0)。
(在此我只是介绍了OS镜像中必须遵循的规范,其它的读者可以自行了解!)
由于之前没有看过grub Multiboot规范,所以对于JamesM’s kernel学习中会有许多疑惑。
1、操作系统是如何从实模式切换到保护模式?
2、ELF 文件是如何加载到内存的?
3、如何启动分段机制?
4、A20地址线的设置?
5、因为操作系统在进入保护模式之前,都必须定义全局描述符表,但是在代码中都没有看见,不知道在什么地方定义的?
但是再看了GrubMultiboot后这些问题都解决了,因为对于上述的问题在程序中都没有看到实现过程,所以当时有点蒙.....
当引导程序调用32位操作系统时,机器状态必须如下:
1、EAX:必须包含魔数0x2BADB002;这个值指出操作系统是被一个符合Multiboot规范的引导程序载入的(这样就算是另一种引导程序也可以引导这个操作系统)。
2、EBX :必须包含由引导程序提供的Multiboot信息结构的物理地址(参见引导信息格式)。
3、CS :必须是一个偏移量位于0到0xFFFFFFFF之间的32位可读/可执行代码段。这里的精确值未定义。
4、DS 、ES 、FS 、GS 、SS:必须是一个偏移量位于0到0xFFFFFFFF之间的32位可读/可执行代码段。这里的精确值未定义。
5、A20 gate:必须已经开启。
6、CR0 :第31位(PG)必须为0。第0位(PE)必须为1。其他位未定义。(已经到了保护模式)
从上面可以看出,当grub调用OS镜像时,ELF可执行文件会被自动加载入内存,OS会自动从实模式到保护模式,打开A20地址线,启动分段机制。这里需要注意的是全局描述符表(GDT),因为操作系统在进入保护模式之前,都必须定义全局描述符表,但是当我知道我的OS进入了保护模式时,但是我发现我们有定义全局描述符表,但是程序可以运行,自己就感到很奇怪,原来GRUB自动为我建立了一个GDT,虽然我不知道GDT在什么地方,还有就是GDT中有什么,但是之后我自己可以从新写GDT来重新设置它

~~~~虽然在实验中没有自己动手去写bootloader,还有实模式到保护模式的切换,ELF文件的加载这一部分内容,似乎有点偷懒了,但是后续的博客中我还是会来整理这部分的理论知识~~。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值