Multiboot规范

一个启动载入器/OS映像接口主要是三个方面:

1          由启动载入器看到的一个OS映像的格式。

2          当启动载入器启动一个操作系统时,机器的状态。

3          由启动载入器传递给操作系统的信息的格式。

3.1.      OS映像的格式

一个OS映像可能是一个,对于这个特定的操作系统而言,标准格式的普通32位可执行文件,除了它可能被链到一个非缺省的载入地址,以避免载入到PC的I/O区域的顶部或其它的保留区域,同样它不应该使用共享库或其它花哨的特性。

一个OS映像,除了该OS映像所使用文件格式的头部外,必须包含一个称为Multiboot头的额外的头部。Multiboot头部必须被完整包含 在OS映像的前8192字节内,而必须与长字(32位)对齐。一般而言,它应该尽早出现,并可能嵌入在可执行文件头部后,代码段的开头。

3.1.1.        Multiboot头的布局

Multiboot头的布局必须如下:

偏移 类型              域名                     注意

0            u32              magic                  要求

4            u32              lags                     要求

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’定义在3.1.2节【头部魔数域】,4页,域 ‘header_addr’,‘load_addr’,‘load_end_addr’,‘bss_end_addr’及‘entry_addr’定义在 3.1.3节【头部地址域】,5页,而域‘mode_type’,‘width’,‘height’及 ‘depth’定义在3.1.4节【头部图形化域】,5页。

3.1.2.        Multiboot头部的魔数域

‘magic’ 域‘magic’是标识这个头的魔数,它必须是十六进制数0x1BADB002。

‘flags’   域‘flags’指定OS映像所要求的特性,或对启动载入器的要求。0-15位显示要求;如果启动载入器看到这些比特中有比特被设置,但不能理解这个标 志,或出于某些原因不能满足其代表的要求,它必须通知用户,并且这个OS映像载入失败。16-31位显示可选的特性;如果这个区域内有比特被设置,但启动 载入器不能理解,它可能只是忽略它们,并如常处理。理所当然,所有‘flags’中尚未定义的比特,必须在OS映像中设置为0。这样,‘flags’域, 除了选择简单特性外,还可用于版本控制。

如果‘flags’字中的第0位被设置,那么所有与操作系统一起载入的启动模块必须在页(4KB)边界上对齐。某些操作系统在启动期间,能够直接把包含启动模块的页面映射到一个页对齐的地址,因此要求启动模块页对齐。

如果‘flags’字中的第1位被设置,那么可用内存的信息,至少是Multiboot 消息结构(参考3.3节【启动信息格式】,7页)的 ‘mem_*’ 域,被包括。 如果启动载入器能够传递一个内存映射图(‘mmap_*’域),而且这样的域存在,它也可能被包括。

如果‘flags’字中的第2位被设置,关于视频模式表(参考3.3节【启动信息格式】,7页)的信息必须对内核可用。如果‘flags’字中的第 6位被设置,那么在Multiboot头偏移为12-28处的域有效,启动载入器应该使用它们,而不是在实际可执行头中的域,来计算何处载入OS映像。如 果内核映像是elf格式,这个信息不需要提供,但如果内核是a.out格式或其它格式,则必须提供。兼容的启动载入器必须能载入elf格式的映像,或在 Multiboot头中嵌入载入地址信息的映像;它们可能也直接支持其它可执行格式,比如特定的a.out变体,不过这不要求。

‘checksum’

域‘checksum’是一个32位无符号值,当加上其它魔数域(即,‘magic’及‘flags’)时,其和必须是无符号32位数0。

3.1.3.        Multiboot头的地址域

所有被flag第16位激活的地址域都是物理地址。每个的含义如下:

header_addr

包含对应于Multiboot头开始的地址——magic值被期望载入的物理内存位置。这个域用于同步OS映像偏移与物理内存地址间的映射。

load_addr

包含代码段开头的物理地址。在OS映像中,开始载入的偏移,由Multiboot头部所在偏移减去(header_addr – load_addr)来定义。Load_addr必须小于等于header_addr。

load_end_addr

包含数据段末尾的物理地址。(load_end_addr – load_addr)指出了要载入多少数据。这暗示在OS映像中代码段及数据段必须连续;对于现存的a.out可执行格式,这是成立的。如果这个域是0, 启动载入器就假定代码段与数据段占据了整个OS映像文件。

bss_end_addr

包含bss段末尾的物理地址。启动载入器初始化这个区域为0,并保留它所占据的内存,以避免在这个区域放入启动模块及与操作系统相关的其它数据。如果这个域是0,启动载入器就假定bss段没有出现。

entry_addr

为了开始运行操作系统,启动载入器应该跳转到的物理地址。

3.1.4.        Multiboot头的图形化域

所有的图形化域被flag的第2位所激活。它们指定了首选的图形化模式。注意到这仅是OS映像的一个建议的模式。如果该模式存在,当用户没有显式指定一个模式时,启动载入器应该设置它。否则,如果可能,启动载入器应该进入一个类似的模式。

每个域的含义如下:

mode_type

对于线性图形模式,包含‘0’,或‘1’对于EGA-标准文本模式。余下为未来扩展保留。注意到启动载入器可能设置一个文本模式,即便这个域包含‘0’。

width         包含列的个数。在一个图形化模式中,这以像素为单位,在一个文本模式中,以字符为单位。值0表示OS映像没有偏好。

height         包含行的个数。在一个图形化模式中,这以像素为单位,在一个文本模式中,以字符为单位。值0表示OS映像没有偏好。

depth         包含,在一个图形化模式下,每个像素的比特数;而在一个文本模式中,这为0。值0表示OS映像没有偏好。

3.2.      机器状态

当启动载入器调用32位操作系统时,机器必须具有如下状态:

‘EAX’   必须包含魔数‘0x2BADB002’;这个值的出现,向操作系统表示,它由一个Multiboot兼容的启动载入器载入(即,相对于可以载入该操作系统的,其它类型启动载入器)。

‘EBX’   必须包含由启动载入器提供的,Multiboot信息结构的32位物理地址(参考3.3节【启动信息格式】,7页)。

‘CS          必须是一个偏移为‘0’,限长为‘0xFFFFFFFF’的32位读/执行代码段。具体值没有定义。

‘DS’

‘ES’

‘FS’

‘GS’

‘SS’       必须是一个偏移为‘0’,限长为‘0xFFFFFFFF’的32位读/写数据段。具体值没有定义。

‘A20 gate’必须激活。

‘CR0’    第31位(PG)必须被清除。第0位(PE)必须被设置。其它位未定义。

‘EFLAGS’

第17位(VM)必须被清除。第9位(IF)必须被清除。其它位未定义。

所有其它处理器寄存器及标记位都未定义。这包括,特别是:

‘ESP’    一旦需要,OS映像必须构建自己的栈。

‘GDTR’    即便段寄存器如上所示那样设置,‘GDTR’可能是无效的,因此OS映像必须不加载任何段寄存器(就算只是重载相同的值!),直到它设立自己的‘GDT’。

‘IDTR’  OS映像必须保持禁止中断,直到它设立自己的IDT。

然而,在正常的工作次序中,启动载入器不应该改动其它机器状态,即,如BIOS初始化的那样(或DOS,如果那是启动载入器运行的地方)。换而言 之,操作系统在载入后,应该能够进行诸如BIOS调用的操作,只要在这样做之前,它不改写BIOS数据结构。同样,启动载入器必须不改动以正常 BIOS/DOS值编写的PIC,即便在切换到32位模式过程中,它改变了它们。

3.3.      启动信息格式

进入到操作系统,EBX寄存器包含Multiboot信息数据结构的物理地址,通过它,启动载入器向操作系统传递重要信息。操作系统可以使用或忽略,所选择的该结构体的任意部分;由启动载入器传入的所有信息仅供参考。

Multiboot信息结构体及其相关的子结构体,可能被启动载入器放在内存的任一处(当然,为内核及启动模块所保留的内存是例外)。避免改写这个内存,直到它没有使用价值,这是操作系统的责任。

Multiboot信息结构(就目前的定义)的格式如下:

+----------------------+

0           | flags                      | (要求)

+----------------------+

4           | mem_lower           | (如果设置了flags[0],出现)

8           | mem_upper           | (如果设置了flags[0],出现)

+----------------------+

12         | boot_device          |(如果设置了flags[1],出现)

+----------------------+

16         | cmdline                 | (如果设置了flags[2],出现)

+----------------------+

20         | mods_count          |(如果设置了flags[3],出现)

24         | mods_addr            | (如果设置了flags[3],出现)

+----------------------+

28 - 40 | syms                      | (如果设置了flags[4]或flags[5],出现)

+----------------------+

44         | mmap_length       |(如果设置了flags[6],出现)

48         | mmap_addr          |(如果设置了flags[6],出现)

+----------------------+

52         | drives_length        |(如果设置了flags[7],出现)

56         | drives_addr           |(如果设置了flags[7],出现)

+----------------------+

60         | config_table          |(如果设置了flags[8],出现)

+----------------------+

64         | boot_loader_name|(如果设置了flags[9],出现)

+----------------------+

68         | apm_table             |(如果设置了flags[10],出现)

+----------------------+

72         | vbe_control_info  |(如果设置了flags[11],出现)

76         | vbe_mode_info     |

80         | vbe_mode             |

82         | vbe_interface_seg |

84         | vbe_interface_off |

86         | vbe_interface_len |

+----------------------+

第一个长字显示在Multiboot信息结构体中其它域存在及有效性。所有尚未定义的比特位必须由启动载入器设为0。操作系统不能理解的任意比特组应该被忽略。这样,域‘flags’还起到版本指示器的作用,允许Multiboot信息结构体在将来进行无损害的扩展。

如果在‘flags’中设置了第0位,那么域‘mem_*’是有效的。‘mem_lower’及‘mem_upper’分别表示低位内存和高位内存 的数量,以KB(kilobyte)为单位。低位内存从地址0开始,而高位内存从地址1M开始。低位内存最大的可能值是640KB。为高位内存所返回的值 最大是第一个高位内存空洞的地址减去1M。但不保证就是这个值。

如果在‘flags’中设置了第1位,那么域‘boot_device’是有效的,并显示从哪个BIOS硬盘设备上启动载入器载入OS映像。如果 OS映像不从一个BIOS硬盘上载入,那么这个域必须不出现(第3位必须被清除)。操作系统可能使用这个域作为确定其自己根设备的一个暗示,但它不要求这 样做。域‘boot_device’在4个1字节子域中布置如下:

+-------+-------+-------+-------+

| part3  | part2 | part1  | drive |

+-------+-------+-------+-------+

第一个字节包含BIOS设备号,它可被BIOS的INT 0x13底层接口所理解:即,0x00对应软盘,0x80对应第一个硬盘。

余下3个字节指定了启动分区。‘part1’指定最上层的分区号,‘part2’指出在最上层分区的一个子分区等。分区号总是从0开始。没有设置的 分区字节必须被设置为0xFF。例如,如果硬盘使用单层DOS分区规划,那么‘part1’包含DOS分区号,而‘part2’及 ‘part3’都是0xFF。另一个例子,如果一个硬盘首先划分为DOS分区,然后其中一个DOS分区被进一步使用BSD硬盘标签(disklabel) 策略划分为几个BSD分区,那么‘part1’包含这个DOS分区号,‘part2’包含在这个DOS分区中的BSD子分区,而‘part3’是 0xFF。

DOS扩展分区由从4开始的分区号表示,而不是作为嵌套子分区,即便扩展分区所立足的硬盘布局本质上是分层的。例如,如果启动载入器从,一个以传统DOS形式分区的硬盘的第二个扩展分区启动,那么‘part1’将是5,而‘part2’及‘part3’都将是0xFF。

如果在‘flags’中设置了第2位,域‘cmdline’是有效的,它包含了要传递给内核的命令行的物理地址。这个命令行是一个普通C样式的,以0结尾的字符串。

如果在‘flags’中设置了第3位,那么域‘mods’向内核显示,什么启动模块会伴随内核映像载入,以及可以在何处找到它们。 ‘mods_count’包含了载入模块的个数;‘mods_addr’包含了第一个模块结构的物理地址。‘mods_count’可能是0,表示不载入 启动模块,就是设置了‘flags’的第一位比特。每个模块结构体的格式如下:

+-------------------+

0   | mod_start          |

4   | mod_end           |

+-------------------+

8   | string                 |

+-------------------+

12 | reserved (0)       |

+-------------------+

头两个域包含了启动模块本身开头与结尾的地址。域‘string’提供了一个任意的字符串来关联这个特定的启动模块;它是一个0结尾的ASCII字 符串,就像内核命令行。域‘string’可能是0,如果没有字符串可关联这个模块。通常,这个字符串可能是一个命令行(比如,如果操作系统把启动模块处 理作可执行程序),或一个路径名(比如,如果操作系统把启动模块处理作在一个文件系统中的文件),不过它确切的使用,取决于操作系统。域 ‘reserved’必须被启动载入器设置为0,并且为操作系统所忽略。

警告:第4与第5比特位是互斥的。

如果在‘flags’中设置了第4位,那么在Multiboot信息结构体中,从第28个字节开始的以下域是有效的:

+-------------------+

28 | tabsize              |

32 | strsize               |

36 | addr                  |

40 | reserved (0)      |

+-------------------+

这些域表示何处可以找到,来自一个a.out内核映像的符号表。‘addr’是一个a.out格式的nlist结构体数组大小(4字节无符号长整 形)的物理地址,其后紧跟着这个数组本身,然后是一组以0结尾的ASCII字符串的大小(4字节无符号长整形,并加上sizeof(unsigned long)),最后是这组字符串本身。‘tabsize’是符号表大小的参数(在符号段开头找到),而‘strsize’是随后的符号表所引用的字符串表 大小的参数(在字符串段开头找到)。注意到‘tabsize’可能是0,表示没有符号,即便设置了‘flags’中的第4位。

如果在‘flags’中设置了第5位,那么在Multiboot信息结构体中,从第28个字节开始的以下域是有效的:

+-------------------+

28 | num                  |

32 | size                   |

36 | addr                  |

40 | shndx                |

+-------------------+

这些域表示何处是来自一个ELF内核的段头表(section header table),每个项的大小,项的个数,及用作名字索引的字符串表。它们对应于在可执行及可链接格式(ELF)规范的程序头(program header)中的‘shdr_*’项(‘shdr_num’,等)。所有的段被载入,然后ELF段头的物理地址域指向内存中的段(如何读出段头的细节, 参考i386 ELF 文档)。注意到‘shdr_num’可能是0,表示没有符号,即便设置了‘flags’中的第5位。

如果在‘flags’中设置了第5位,那么域‘mmap_*’是有效的,表示包含由BIOS提供的一个机器内存映射的缓存的地址及长度。其 中,‘mmap_addr’是这个地址,而‘mmap_length’是这个缓存的总体大小。这个缓存由以下一个或多个size/structure对组 成(‘size’实际上用于跳到下一对):

+-------------------+

-4 | size                   |

+------------------+

0   | base_addr         |

8   | length               |

16 | type                  |

+-------------------+

其中‘size’是关联结构体的字节大小,它至少是20。‘base_addr’是起始地址。‘length’是该内存区域的字节大小。‘type’是所代表的地址区域的种类,其中值1表示为可用的ram,而当前其它值表示一个保留区域。

该映射保证列出所有可以正常使用的标准ram。

如果在‘flags’中设置了第7位,那么域‘drives_*’是有效的,表示第一个drive结构体的物理地址,及drive结构体的大小。 ‘drives_addr’是这个地址,而‘drives_length’是drive结构体的总大小。注意到‘drives_length’可以是0。 每个drive结构体的格式如下:

+-------------------+

0          | size                    |

+-------------------+

4          | drive_number    |

+-------------------+

5          | drive_mode       |

+-------------------+

6          | drive_cylinders |

8          | drive_heads       |

9          |drive_sectors     |

+--------------------+

10 - xx | drive_ports        |

+--------------------+

域‘size’指定这个结构体的大小。这个大小,依赖于端口的数目,是可变的。注意到因为对齐的原因,这个大小可能不等于(10 + 2 * 端口的数目)。

域‘drive_number’包含了BIOS设备号。域‘drive_mode’代表由启动载入器使用的访问模式。当前,以下模式被定义:

‘0’ CHS 模式(传统的柱面/头/扇区(cylinder/head/sector)取址模式)。

‘1’ LBA 模式(逻辑块取址模式(Logical Block Addressing mode))。

‘drive_cylinders’,‘drive_heads’及‘drive_sectors’这三个域表示由BIOS检测出来的驱动的几何数 据。‘drive_cylinders’包含柱面数目。‘drive_heads’包含柱头个数。‘drive_sectors’包含每个磁道的扇区数。

域‘drive_ports’包含在BIOS代码中使用的I/O端口数组。这个数组由0个或以上的无符号2字节整数构成,以0结尾。注意到这个数组可能包含任意数目的,不与该驱动真正相关的I/O端口 (比如DMA控制器端口)。

如果在‘flags’中设置了第8位,那么域‘config_table’是有效的,它表示由GET CONFIGURATION BIOS调用返回的rom配置表的地址。如果这个BIOS调用失败,这个表的大小必须为0。

如果在‘flags’中设置了第9位,域‘boot_loader_name’是有效的,它包含了一个启动该内核的启动载入器名字的地址。这个名字是一个普通C-样式以0结尾的字符串。

如果在‘flags’中设置了第10位,域‘apm_table’是有效的,它包含了一个定义如下的APM表的物理地址:

+----------------------+

0   | version                 |

2   | cseg                      |

4   | offset                    |

8   | cseg_16                |

10 | dseg                      |

12 | flags                     |

14 | cseg_len               |

16 | cseg_16_len         |

18 | dseg_len               |

+----------------------+

域 ‘version’,‘cseg’,‘offset’,‘cseg_16’,‘dseg’,‘flags’,‘cseg_len’,‘cseg_16_len’,‘dseg_len’ 分别表示版本号,32位保护模式代码段,入口点的偏移,16位保护模式代码段,16位保护模式数据段,flags,32位保护模式代码段的长度,16位保 护模式代码段的长度,16位保护模式数据段的长度。只有域‘offset’是4个字节,其它的都是2个字节。更多信息,参考先进电源管理 (APM)BIOS接口规范。

如果在‘flags’中设置了第11位,表示图形化表可用。如果内核已经在‘Multiboot Header’中表示,它接受一个图形模式,它才能被设置。

域‘vbe_control_info’及‘vbe_mode_info’分别包含了由VBE Function 00h返回的VNE控制信息的物理地址,及由VBE Function 01h返回的VBE模式信息。

域‘vbe_mode’表示在VBE 3.0中所规定格式中的当前视频模式。

余下的域‘vbe_interface_seg’,‘vbe_interface_off’,及‘vbe_interface_len’包含了定义 在VBE 2.0+中的一个保护模式接口表。如果这个信息不可用,这些域包含0。注意VBE 3.0定义了另一个保护模式接口,它与旧的不兼容。如果你希望使用新的保护模式接口,你将不得不自己查找这个表。

用于图形化表的域是为VBE设计的,但Multiboot启动载入器可能在非-VBE模式上模拟 VBE,仿佛它们就是VBE 模式。

时间: 2024-10-05 05:18:16

Multiboot规范的相关文章

Day4 - 迭代器&生成器、装饰器、Json & pickle 数据序列化、软件目录结构规范

---恢复内容开始--- 本节内容 迭代器&生成器 装饰器 Json & pickle 数据序列化 软件目录结构规范 作业:ATM项目开发 1.列表生成式,迭代器&生成器 列表生成式 需求:列表a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9],要求把列表里的每个值加1 1 a = [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] 2 b = [] 3 for i in a: 4 b.append(i+1) 5 a = b 6 print(a) 普通青

java编码规范

右括号") "与其后面的关键字之间,关键字与其后面的左括号"("或"{"之间,以及"}"与"{"之间,要以一个空格隔开:除". "外,所有二元操作符的前.后要加空格:在逗号后边加一个空格. 说明: 一个紧跟着括号的关键词应该被空格分开: 空白应该位于参数列表中逗号的后面: 所有的二元运算符,除了".",应该使用空格将之与操作数分开.一元操作符和操作数之间不应该加空格,

dos命令-环境变量-数据类型-命名规范

JAVA第一天笔记--dos命令-环境变量-数据类型-命名规范 1.能够阐述JDK和JRE之间区别 JDK(Java Development Kit)是提供给开发人员使用的JAVA开发工具包(javac.exe;java.exe),包含JRE(Java Runtime Environment). JRE(Java Runtime Environment)是Java程序运行环境,包含JVM(Java Virtual Machine)及核心类库. 总结为:开发人员使用JDK开发的程序,在JRE中运行

Atitit 数据库view视图使用推荐规范与最佳实践与方法

1. 视图的优点:1 1.1. **提升可读性  定制用户数据,聚焦特定的数据1 1.2. 使用视图,可以简化数据操作.       1 1.3. **提升扩展性 屏蔽底层表的重构变动,免编译免部署热更新2 1.4. B.查询简单化. 2 1.5. C.逻辑数据独立性. 2 1.6. 提高数据安全性,可以不让用户看到表中的某个字段.2 1.7. 合并分离的数据,创建分区视图       2 1.8. 模拟索引列3 2. 缺点3 2.1. 小部分场景下,复杂视图可能会有性能问题,可以使用带参数的s

浅析JS模块规范:AMD,CMD,CommonJS

随着JS模块化编程的发展,处理模块之间的依赖关系成为了维护的关键. 模块化 AMD,CMD,CommonJS是目前最常用的三种模块化书写规范. CommonJS CommonJS规范是诞生比较早的.NodeJS就采用了CommonJS.是这样加载模块: var clock = require('clock'); clock.start(); 这种写法适合服务端,因为在服务器读取模块都是在本地磁盘,加载速度很快.但是如果在客户端,加载模块的时候有可能出现"假死"状况.比如上面的例子中cl

Zabbix 使用规范和生成报表

一.软件版本 操作系统:CentOS-6.5-x86_64 zabbix版本:3.0.3 二.zabbix标准:   1.  主机命名规范: BJ-monitor-h-zabbix-01 **命名规范是,我们看一台主机能够知道主机位于哪里:BJ:做什么的:monitor:虚拟化还是实体机:h:跑什么服务:zabbix  第几台:01 2.  一台主机直接关联多个模板:不用创建多个分组(可以结合CMDB平台) Memcached :192.168.10.100 Php Linux:192.168.

触发器使用教程和命名规范

目  录 触发器使用教程和命名规范 1 1,触发器简介 1 2,触发器示例 2 3,触发器语法和功能 3 4,例一:行级触发器之一 4 5,例二:行级触发器之二 4 6,例三:INSTEAD OF触发器 6 7,例四:语句级触发器之一 8 8,例五:语句级触发器之二 9 9,例六:用包封装触发器代码 10 10,触发器命名规范 11 1,触发器简介 触发器(Trigger)是数据库对象的一种,编码方式类似存储过程,与某张表(Table)相关联,当有DML语句对表进行操作时,可以引起触发器的执 行

作业三: 代码规范、代码复审、PSP

(1) 是否需要有代码规范         1.这些规范都是官僚制度下产生的浪费大家的编程时间.影响人们开发效率, 浪费时间的东西.(反对) 答:首先编码规范 包括了编码风格和其它规范 一个团队遵守一些规范有很多的好处! (1). 遵守编码风格使代码更容易维护 (2). 编码风格使形成代码集体所有制(集体所有制的作用很大,它能有效的增大巴士因子——一个项目能承受多少个程序员被车撞了而不影响项目的正常进行) (3). 编码风格能消除那些长久的纷争(你不需要喜欢这种编码风格.如果你不喜欢里面的某条规

百度Baidu EFE team的前端规范——项目目录结构规范

项目目录结构规范 简介 该文档主要的设计目标是项目开发的目录结构保持一致,使容易理解并方便构建与管理. 编撰 李玉北.erik.黄后锦.王杨.张立理.赵雷.陈新乐.刘恺华. 本文档由商业运营体系前端技术组审校发布. 要求 在本文档中,使用的关键字会以中文+括号包含的关键字英文表示:必须(MUST).关键字"MUST", "MUST NOT", "REQUIRED", "SHALL", "SHALL NOT"