适配GRUB Multiboot 规范笔记(一)

2019-01-11  本文已影响0人  Jason416

前言

用通用的GRUB/GRUB2来引导操作系统,可以跳过编写boot loader的步骤,达到简化编程的目的。还可以使得操作系统通用,不用烧写U盘等操作,只需要添加对Multiboot的支持即可。从上电到BIOS,再到搬移kernel.bin到1M地址等操作可以参阅作者的书籍。

说明

本次编译的东西只是基础deamon版本,并未支持64位环境。编译所用的都是32位elf文件,multiboot对32位elf支持较好。后面再记录引导64位OS的方法。

一、选择GRUB版本

要想使用GURB/GURB2引导系统,得遵循GURB的Multiboot/Multiboot2的规范(specification)。查阅了官方文档MultibootMultiboot2之后,发现GRUB2版本设计的版本功能更强大,支持直接到IA-32模式,对于学习操作系统来说,这部分工作还是手动实现,能学到更多;还支持UEFI规范的一些操作,为了减轻复杂性,暂时选择Multiboot规范(legacy)。

二、如何启动自己的elf

grub2中直接提供了multiboot和multiboot2命令,可分别用于引导符合multiboot v1规范和multiboot v2规范的内核。下面做个示例:

menuentry 'grub test'--class gnu --class os {
        load_video
        insmod gzio
   #    insmod part_msdos
   #    insmod xfs
   #    set root='hd0,msdos1'
        echo 'loading kernel.elf'
        multiboot /kernel.elf
}

Note: #注释的部分,每个主机都不同,具体多少可以参考系统中其它menuentry。

二、Multiboot Specification

对于GRUB这种通用的boot loader来说,与OS之间交互的主要设计实现接口有三,如下:

下面只记录最关键的部分,官方文档中对数据结构的定义做了很多说明,此处不再累述。详细信息查阅官方手册Multiboot

三、编写程序

官网所给的例程比较详细的说明了如何让自己的OS兼容Multiboot Specification,可以先理解,再拿来使用,测试。具体内容参见官方的:
4.3 Example OS code

四、链接脚本

下面给个简单示例,可自由发挥:

OUTPUT_FORMAT("elf32-i386")
OUTPUT_ARCH(i386)
ENTRY(_start)
SCTIONS
{
    . = 0x00100000;

    .text ALIGN (0x1000) :
    {
        *(.text)
    }

    .rodata ALIGN (0x1000) :
    {
        *(.rodata*)
    }

    .data ALIGN (0x1000) :
    {
        *(.data)
    }

    .bss :
    {
        sbss = .;
        *(COMMON)
        *(.bss)
        ebss = .;
    }
}

五、编译

笔者曾经尝试过很多中办法,因为grub老是提示无法找到Header,要么就是Magic Number不对,尝试过很多办法都无解。后来搜索和gcc编译相关的资料,发现了可能是编译参数未指定,导致编译出来的无法被grub识别。下面给出测试过的可以通过multiboot引导的编译参数:

gcc -m32 -march=i386 -I. -Wall -Wextra -fno-builtin -nostdlib  -nostartfiles -nodefaultlibs ...
ld -m elf_i386 ...

Note: 下面对几个重要的参数做说明

参数 含义
-nostartfiles 指定入口函数
-nodefaultlibs 不使用默认库文件
-nostdlib 不使用标准库函数
fno-builtin 不使用gcc的内建函数

六、结果

本次在虚拟机中模拟multiboot环境,可以使用,最后显示一条45°的斜线(cmain函数中最后一个功能),效果如下图:

效果图
上一篇下一篇

猜你喜欢

热点阅读