在软盘中安装grub
昨天在这一步出了点问题,很难受,今天来解决一下
我发现问题可能跟我使用的是腾讯云的vps有关,后来我换了一台vultr的centos的vps之后就没问题了,接着昨天的
用loop0把floppy.img虚拟成块设备
1
| sudo losetup /dev/loop0 floppy.img
|
进入grub命令行
然后输入下面的命令
1 2 3
| device (fd0) /dev/loop0 root (fd0) setup (fd0)
|
然后解除loop0和floppy.img的关联,解除挂载
1 2
| sudo losetup -d /dev/loop0 sudo umount /mnt/kernel
|
现在软盘镜像就做好了,不过还没有内核,先来测试一下
1
| qemu -fda floppy.img -boot a
|
看到grub的菜单界面就成功了
注意:如果用的是vps,那么ssh客户端一定要支持x11,不然虚拟机运行不了,因为虚拟机需要图形化界面,今天grub命令行和x11花了我大量的时间,摸索Google了半天,总算解决了2333,所以昨天就没更新bolg,内容太少了233
内核的入口
boot/boot.s
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73
| ; ---------------------------------------------------------------- ; ; boot.s -- 内核从这里开始 ; ; ----------------------------------------------------------------
; Multiboot 魔数,由规范决定的 MBOOT_HEADER_MAGIC equ 0x1BADB002
; 0 号位表示所有的引导模块将按页(4KB)边界对齐 MBOOT_PAGE_ALIGN equ 1 << 0
; 1 号位通过 Multiboot 信息结构的 mem_* 域包括可用内存的信息 ; 告诉(把内存空间的信息包含在信息结构中GRUBMultiboot) MBOOT_MEM_INFO equ 1 << 1
; 定义我们使用的 Multiboot 的标记 MBOOT_HEADER_FLAGS equ MBOOT_PAGE_ALIGN | MBOOT_MEM_INFO
; 域是一个位的无符号值,当与其他的域checksum32magic也就是(和magicflags) ; 相加时,要求其结果必须是位的无符号值32 0 即(magic+flags+checksum = 0) MBOOT_CHECKSUM equ -(MBOOT_HEADER_MAGIC+MBOOT_HEADER_FLAGS)
; 符合规范的Multiboot OS 映象需要这样一个 magic Multiboot 头 ; Multiboot 头的分布必须如下表所示: ; ---------------------------------------------------------- ; 偏移量类型域名备注 ; ; 0 u32 magic 必需 ; 4 u32 flags 必需 ; 8 u32 checksum 必需 ; ; 我们只使用到这些就够了,更多的详细说明请参阅 GNU 相关文档 ;-----------------------------------------------------------
;-----------------------------------------------------------------------------
[BITS 32] ; 所有代码以 32-bit 的方式编译 section .text ; 代码段从这里开始
; 在代码段的起始位置设置符合 Multiboot 规范的标记
dd MBOOT_HEADER_MAGIC ; GRUB 会通过这个魔数判断该映像是否支持 dd MBOOT_HEADER_FLAGS ; GRUB 的一些加载时选项,其详细注释在定义处 dd MBOOT_CHECKSUM ; 检测数值,其含义在定义处
[GLOBAL start] ; 向外部声明内核代码入口,此处提供该声明给链接器 [GLOBAL glb_mboot_ptr] ; 向外部声明 struct multiboot * 变量 [EXTERN kern_entry] ; 声明内核 C 代码的入口函数
start: cli ; 此时还没有设置好保护模式的中断处理,要关闭中断 ; 所以必须关闭中断 mov esp, STACK_TOP ; 设置内核栈地址 mov ebp, 0 ; 帧指针修改为 0 and esp, 0FFFFFFF0H ; 栈地址按照字节对齐16 mov [glb_mboot_ptr], ebx ; 将 ebx 中存储的指针存入全局变量 call kern_entry ; 调用内核入口函数 stop: hlt ; 停机指令,可以降低 CPU 功耗 jmp stop ; 到这里结束,关机什么的后面再说
;-----------------------------------------------------------------------------
section .bss ; 未初始化的数据段从这里开始 stack: resb 32768 ; 这里作为内核栈 glb_mboot_ptr: ; 全局的 multiboot 结构体指针 resb 4
STACK_TOP equ $-stack-1 ; 内核栈顶,$ 符指代是当前地址
;-----------------------------------------------------------------------------
|
上面这段是汇编的代码,分号后面的是注释
7-22行定义了Multiboot规范要用到的一些值,Multiboot定义的Multiboot 头的分布必须如下表所示:
1 2 3 4 5 6 7 8 9 10 11 12 13
| 偏移量 类型 域名 备注 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]被置位
|
这里只用到了前三个,MBOOT_HEADER_MAGIC 就是标志头的魔数,必须等于0x1BADB002
MBOOT_HEADER_FLAGS 就是flag,一共32位,不同位置1有不同的含义,这里将0和1位置1了,代表的意义在注释上
MBOOT_CHECKSUM 就是checksum ,域checksum是一个32位的无符号值,当与其他的magic域(也就是magic和flags)相加时,结果必须是32位的无符号值0(即magic + flags + checksum = 0)。
43-45行定义了这三个数为32位,即4字节
51行的start就是链接器脚本定义的内核入口函数
start干的事情就是关中断,设置栈,然后将grub提供的信息的指针放到全局变量里面((按照协议,GRUB把一些计算机硬件和我们内核文件相关的信息放在了一个结构
体中,并且将这个结构体指针放在了ebx寄存器中)
最后调用c语言写的函数kern_entry,这个函数返回后就是hlt待机了
65行到最后定义了未初始化的一些空间,定义了栈大小为32768字节,glb_mboot_ptr指针为4字节,定义了栈顶的地址
init/entry.c
汇编写完了,现在可以来写c语言啦
1 2 3 4
| int kern_entry() { return 0; }
|
这个就是上面汇编调用的c的函数,函数啥也没干233
include/types.h
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
| #ifndef INCLUDE_TYPES_H_ #define INCLUDE_TYPES_H_
#ifndef NULL #define NULL 0 #endif
#ifndef TRUE #define TRUE 1 #define FALSE 0 #endif
typedef unsigned int uint32_t; typedef int int32_t; typedef unsigned short uint16_t; typedef short int16_t; typedef unsigned char uint8_t; typedef char int8_t;
#endif // INCLUDE_TYPES_H_
|
这个就是做了一些宏定义,并且把c语言的一些类型名字做了重命名
现在的目录结构是这样的:
现在我们来启动试试看
先看到grub的菜单,然后选择操作系统之后就啥也不干了,毕竟我们啥也没写233
今天就先结束了,成完成了一个啥也不做的内核2333