Hello world!让 grub2 引导自己的操作系统 Xos 内核

时间:2022-07-15 15:44:41

按照惯例,Xos 的第一步是在屏幕上打印 Hello world!第一步是神奇的一步,如果读者对 PC 不了解,将很难得到头绪。

PC 开机后,CS 和 IP 被初始化为 CS=0xFFFFh,IP=0x0000h,CPU 将从 0xFFFF0h 处读取第一条指令。这个地址正好位于主板上的一段 ROM 即 BIOS 中。BIOS 中的启动程序末尾会将硬盘 MBR 扇区加载到内存 0x7C00h ,并从此处执行。这时候 CPU 处于实模式,使用INT中断可调用 BIOS 程序在屏幕上打印字符。于渊的《自己动手写操作系统》中有详细描述。

但 Xos 不会从硬盘 MBR 加载到内存中,她将通过 grub2 引导。这样做的好处是不需要改动硬盘 MBR ,也不需要用汇编写大量代码,引导程序将完成实模式到保护模式的切换。

内核让 grub2 可引导的条件是符合 Multiboot 规范,在前 8192 字节内需要提供一个 Multiboot header 。grub2 将根据 flags 位初始化内核环境并从内核入口调用内核。

下面是Xos引导测试代码:

 1 typedef struct strMultiBootHeader{  2 unsigned long magic;  3 unsigned long flags;  4 unsigned long checksum;  5 }MultiBootHeader;  6  7 void mbprint(char* str);  8  9 unsigned long magic; 10 11 MultiBootHeader mbh __attribute__((section(".text"))) ={ 12 .magic = 0X1BADB002, 13 .flags = 0X00000003, 14 .checksum   = -(0X1BADB002 + 0X00000003), 15 }; 16 17 void KernelEntry(void) 18 { 19 __asm__("movl %%eax,%0":"=m"(magic)); 20 21 if( magic != 0X2BADB002 ) 22  { 23 mbprint("Kernel load errer!\n"); 24 return; 25  } 26 mbprint("Hello world!\n"); 27 while(1) 28  ; 29 return; 30 } 31 32 void mbprint(char* str) 33 { 34 char *pvideo = (char *)0xB8000; 35 while( *str != '\n' ) 36  { 37 *pvideo++ = *str++; 38 *pvideo++ = 0x04; 39  } 40 41 return; 42 }

用下面的命令生成内核:

1 gcc multiboot.c -c -fno-builtin 2 ld multiboot.o -o Xos -Ttext 0x10000 --entry=KernelEntry

在 grub2 配置文件 /boot/grub/grub.cfg 里添加启动项:

1 menuentry 'Xos0.01'{ 2 insmod part_msdos 3 insmod ext2 4 set root='hd0,msdos1' 5 multiboot /boot/Xos 6 }