🆕 切换为grub2引导,能进入Start_Kernel函数(未能完成初始化)

This commit is contained in:
fslongjin 2022-02-21 14:39:48 +08:00
parent a2aea12510
commit 0b0cce9326
21 changed files with 1128 additions and 1377 deletions

1
.gitignore vendored
View File

@ -1,2 +1,3 @@
/cmake-build-debug/
/bin/
./DragonOS.iso

View File

@ -1,7 +1,8 @@
SUBDIRS = bootloader kernel
SUBDIRS = kernel
.PHONY: all
all:
mkdir -p bin/kernel/
@list='$(SUBDIRS)'; for subdir in $$list; do \
echo "make all in $$subdir";\
cd $$subdir;\

13
bochsrc
View File

@ -5,16 +5,17 @@ config_interface: textconfig
#memory: host=2048, guest=2048
romimage: file="/usr/local/share/bochs/BIOS-bochs-latest"
vgaromimage: file="/usr/local/share/bochs/VGABIOS-lgpl-latest"
boot: floppy
floppy_bootsig_check: disabled=0
floppya: type=1_44, 1_44="bin/boot.img", status=inserted, write_protected=0
# ata0-master: type=disk, path="/data/home/longjin/code/hd.img", mode=flat
boot: cdrom
# no floppyb
ata0: enabled=1, ioaddr1=0x1f0, ioaddr2=0x3f0, irq=14
ata0-master: type=none
ata0-slave: type=none
ata1: enabled=1, ioaddr1=0x170, ioaddr2=0x370, irq=15
ata1-master: type=none
ata1-slave: type=none
ata1-master: type=cdrom, path="DragonOS.iso", status=inserted
ata2: enabled=0
ata3: enabled=0
pci: enabled=1, chipset=i440fx

Binary file not shown.

View File

@ -1,11 +0,0 @@
all: boot.bin loader.bin
boot.bin: boot.asm
nasm boot.asm -o ../bin/bootloader/boot.bin
loader.bin: loader.asm
nasm loader.asm -o ../bin/bootloader/loader.bin
clean:
rm -rf *.asm~ Makefile~

View File

@ -1,299 +0,0 @@
;将程序开始位置设置为0x7c00处并给BaseOfStack赋值为0x7c00
org 0x7c00
BaseOfStack equ 0x7c00
BaseOfLoader equ 0x1000
OffsetOfLoader equ 0x00
RootDirSectors equ 14 ;根目录占用的扇区数
SectorNumOfRootDirStart equ 19 ; 根目录的起始扇区号
SectorNumOfFAT1Start equ 1 ; FAT1表的起始扇区号 (因为前面有一个保留扇区(引导扇区))
SectorBalance equ 17 ;平衡文件/目录的起始簇号与数据区域的起始簇号的差值。
jmp short Label_Start
nop
BS_OEMName db 'DragonOS'
BPB_BytesPerSec dw 512
BPB_SecPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw 224
BPB_TotSec16 dw 2880
BPB_Media db 0xf0
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 18
BPB_NumHeads dw 2
BPB_HiddSec dd 0
BPB_TotSec32 dd 0
BS_DrvNum db 0
BS_Reserved1 db 0
BS_BootSig db 0x29
BS_VolID dd 0
BS_VolLab db 'boot loader'
BS_FileSysType db 'FAT12 '
Label_Start:
;初始化寄存器
mov ax, cs
mov ds, ax
mov es, ax
mov ss, ax
mov sp, BaseOfStack
;清屏
mov ax, 0x0600 ;AL=0时清屏BX、CX、DX不起作用
mov bx, 0x0700 ;设置白色字体,不闪烁,字体正常亮度,黑色背景
mov cx, 0
mov dx, 0184fh
int 0x10
;设置屏幕光标位置为左上角(0,0)的位置
mov ax, 0x0200
mov bx, 0x0000
mov dx, 0x0000
int 10h
;在屏幕上显示Start Booting
mov ax, 0x1301 ;设置显示字符串,显示后,光标移到字符串末端
mov bx, 0x000a ;设置黑色背景,白色字体,高亮度,不闪烁
mov dx, 0x0000 ;设置游标行列号均为0
mov cx, 24 ;设置字符串长度为24
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, StartBootMessage
int 0x10
;软盘驱动器复位
xor ah, ah
xor dl, dl
int 0x13
; 在文件系统中搜索 loader.bin
mov word [SectorNo], SectorNumOfRootDirStart ;保存根目录起始扇区号
Label_Search_In_Root_Dir_Begin:
cmp word [RootDirSizeForLoop], 0 ; 比较根目录扇区数量和0的关系。 cmp实际上是进行了一个减法运算
jz Label_No_LoaderBin ; 等于0不存在Loader.bin
dec word [RootDirSizeForLoop]
mov ax, 0x00
mov es, ax
mov bx, 0x8000
mov ax, [SectorNo] ;向函数传入扇区号
mov cl, 1
call Func_ReadOneSector
mov si, LoaderFileName ;向源变址寄存器传入Loader文件的名字
mov di, 0x8000
cld ;由于LODSB的加载方向与DF标志位有关因此需要用CLD清零DF标志位
mov dx, 0x10 ; 每个扇区的目录项的最大条数是(512/32=16,也就是0x10)
Label_Search_For_LoaderBin:
cmp dx, 0
jz Label_Goto_Next_Sector_In_Root_Dir
dec dx
mov cx, 11 ; cx寄存器存储目录项的文件名长度 11B包括了文件名和扩展名但是不包括 分隔符'.'
Label_Cmp_FileName:
cmp cx, 0
jz Label_FileName_Found
dec cx
lodsb ; 把si对应的字节载入al寄存器中然后由于DF为0si寄存器自增
cmp al, byte [es:di] ; 间接取址[es+di]。 也就是进行比较当前文件的名字对应字节和loader文件名对应字节
jz Label_Go_On ; 对应字节相同
jmp Label_Different ; 字节不同,不是同一个文件
Label_Go_On:
inc di
jmp Label_Cmp_FileName
Label_Different:
and di, 0xffe0 ;将di恢复到当前目录项的第0字节
add di, 0x20 ;将di跳转到下一目录项的第0字节
mov si, LoaderFileName
jmp Label_Search_For_LoaderBin ;继续搜索下一目录项
Label_Goto_Next_Sector_In_Root_Dir:
add word [SectorNo], 1
jmp Label_Search_In_Root_Dir_Begin
Label_No_LoaderBin:
; 在屏幕上显示 [ERROR] No Loader Found.
mov ax, 0x1301
mov bx, 0x000c ; 红色闪烁高亮黑底
mov dx, 0x0100 ; 显示在第二行(前面已经显示过一行了)
mov cx, 24 ; 字符串长度
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, NoLoaderMessage
int 0x10
jmp $
;========== 找到了Loader.Bin
Label_FileName_Found:
mov ax, RootDirSectors
; 先取得目录项DIR_FstClus字段的值起始簇号
and di, 0xffe0
add di, 0x1a
mov cx, word [es:di]
push cx
add cx, ax
add cx, SectorBalance
mov ax, BaseOfLoader
mov es, ax ;配置es和bx指定loader.bin在内存中的起始地址
mov bx, OffsetOfLoader
mov ax, cx
Label_Go_On_Loading_File:
push ax
push bx
; 显示字符.
mov ah, 0x0e
mov al, "."
mov bl, 0x0f
int 0x10
pop bx
pop ax
; 每读取一个扇区就获取下一个表项然后继续读入下一个簇的数据直到返回的下一表项为0xfff为止表示loader.bin完全加载完成
mov cl, 1
call Func_ReadOneSector
pop ax
call Func_GetFATEntry
cmp ax, 0xfff
jz Label_File_Loaded
push ax
mov dx, RootDirSectors
add ax, dx
add ax, SectorBalance
add bx, [BPB_BytesPerSec]
jmp Label_Go_On_Loading_File
Label_File_Loaded:
; 跳转到loader
; 这个指令结束后目标段会复制到CS寄存器中
jmp BaseOfLoader:OffsetOfLoader
; 从软盘读取一个扇区
; AX=待读取的磁盘起始扇区号
; CL=读入的扇区数量
; ES:BX=>目标缓冲区起始地址
Func_ReadOneSector:
push bp
mov bp, sp
sub esp, 2
mov byte [bp-2], cl
push bx
mov bl, [BPB_SecPerTrk]
div bl ;用AX寄存器中的值除以BL得到目标磁道号(商AL)以及目标磁道内的起始扇区号(余数AH)
inc ah ; 由于磁道内的起始扇区号从1开始计数因此将余数+1
mov cl, ah
mov dh, al
shr al, 1 ;计算出柱面号
mov ch, al
and dh, 1;计算出磁头号
pop bx
mov dl, [BS_DrvNum]
;最终dh存储了磁头号dl存储驱动器号
; ch存储柱面号cl存储起始扇区号
Label_Go_On_Reading:
; 使用BIOS中断服务程序INT13h的主功能号AH=02h实现软盘读取操作
mov ah, 2
mov al, byte [bp-2]
int 0x13
jc Label_Go_On_Reading ;当CF标志位被复位时说明数据读取完成恢复调用现场
add esp, 2
pop bp
ret
; 解析FAT表项,根据当前FAT表项索引出下一个FAT表项
Func_GetFATEntry:
; AX=FAT表项号输入、输出参数
; 保存将要被修改的寄存器
push es
push bx
push ax
; 扩展段寄存器
mov ax, 00
mov es, ax
pop ax
mov byte [Odd], 0 ;将奇数标志位置0
; 将FAT表项号转换为总的字节号
mov bx, 3
mul bx
mov bx, 2
div bx
cmp dx, 0
jz Label_Even ; 偶数项
mov byte [Odd], 1
Label_Even:
xor dx, dx ;把dx置0
; 计算得到扇区号(商)和扇区内偏移(余数)
mov bx, [BPB_BytesPerSec]
div bx
push dx
; 读取两个扇区到[es:bx]
mov bx, 0x8000
add ax, SectorNumOfFAT1Start
mov cl, 2 ; 设置读取两个扇区解决FAT表项跨扇区的问题
call Func_ReadOneSector
pop dx
add bx, dx
mov ax, [es:bx]
cmp byte [Odd], 1
jnz Label_Even_2 ;若是偶数项,则跳转
shr ax, 4 ; 解决奇偶项错位问题
Label_Even_2:
and ax, 0x0fff ; 确保表项号在正确的范围内 0x0003~0x0fff
pop bx
pop es
ret
; 临时变量
RootDirSizeForLoop dw RootDirSectors
SectorNo dw 0
Odd db 0
; 显示的文本
StartBootMessage: db "[DragonOS] Start Booting"
NoLoaderMessage: db "[ERROR] No LOADER Found."
LoaderFileName: db "LOADER BIN",0 ;最后这个0是为了填满12字节的宽度
;填满整个扇区的512字节
times 510 - ( $ - $$ ) db 0
dw 0xaa55 ;===确保以0x55 0xaa为结尾

View File

@ -1,25 +0,0 @@
; === 这是FAT12文件系统的信息 ===
RootDirSectors equ 14 ;根目录占用的扇区数
SectorNumOfRootDirStart equ 19 ; 根目录的起始扇区号
SectorNumOfFAT1Start equ 1 ; FAT1表的起始扇区号 (因为前面有一个保留扇区(引导扇区))
SectorBalance equ 17 ;平衡文件/目录的起始簇号与数据区域的起始簇号的差值。
BS_OEMName db 'DragonOS'
BPB_BytesPerSec dw 512
BPB_SecPerClus db 1
BPB_RsvdSecCnt dw 1
BPB_NumFATs db 2
BPB_RootEntCnt dw 224
BPB_TotSec16 dw 2880
BPB_Media db 0xf0
BPB_FATSz16 dw 9
BPB_SecPerTrk dw 18
BPB_NumHeads dw 2
BPB_HiddSec dd 0
BPB_TotSec32 dd 0
BS_DrvNum db 0
BS_Reserved1 db 0
BS_BootSig db 0x29
BS_VolID dd 0
BS_VolLab db 'boot loader'
BS_FileSysType db 'FAT12 '

View File

@ -1,846 +0,0 @@
; |==================|
; | 这是loader程序 |
; |==================|
; Created by longjin, 2022/01/17
; 由于实模式下物理地址为CS<<4+IP而从boot的定义中直到loader的CS为0x1000 因此loader首地址为0x10000
org 0x10000
jmp Label_Start
%include 'fat12.inc' ; 将fat12文件系统的信息包含进来
Base_Of_Kernel_File equ 0x00
Offset_Of_Kernel_File equ 0x100000 ; 设置内核文件的地址空间从1MB处开始。大于实模式的寻址空间
Base_Tmp_Of_Kernel_Addr equ 0x00
Offset_Tmp_Of_Kernel_File equ 0x7e00 ; 内核程序的临时转存空间
Memory_Struct_Buffer_Addr equ 0x7e00 ; 内核被转移到最终的内存空间后,原来的临时空间就作为内存结构数据的存储空间
; ==== 临时的全局描述符表 =====
[SECTION gdt]
LABEL_GDT: dd 0,0
LABEL_DESC_CODE32: dd 0x0000FFFF,0x00CF9A00 ; 代码段和数据段的段基地址都设置在0x00000000处 把段限长设置为0xffffffff可以索引32位地址空间
LABEL_DESC_DATA32: dd 0x0000FFFF,0x00CF9200
GdtLen equ $ - LABEL_GDT
; GDTR寄存器是一个6B的结构低2B保存GDT的长度 高4B保存GDT的基地址
GdtPtr dw GdtLen - 1
dd LABEL_GDT
; 这是两个段选择子是段描述符在GDT表中的索引号
SelectorCode32 equ LABEL_DESC_CODE32 - LABEL_GDT
SelectorData32 equ LABEL_DESC_DATA32 - LABEL_GDT
; === IA-32e模式的临时gdt表
[SECTION gdt64]
LABEL_GDT64: dq 0x0000000000000000
LABEL_DESC_CODE64: dq 0x0020980000000000
LABEL_DESC_DATA64: dq 0x0000920000000000
GdtLen64 equ $ - LABEL_GDT64
GdtPtr64 dw GdtLen64-1,
dd LABEL_GDT64
SelectorCode64 equ LABEL_DESC_CODE64 - LABEL_GDT64
SelectorData64 equ LABEL_DESC_DATA64 - LABEL_GDT64
[SECTION .s16] ;定义一个名为.s16的段
[BITS 16] ; 通知nasm将要运行在16位宽的处理器上
Label_Start:
mov ax, cs
mov ds, ax ; 初始化数据段寄存器
mov es, ax ; 初始化附加段寄存器
mov ax, 0x00
mov ss, ax ;初始化堆栈段寄存器
mov sp, 0x7c00
;在屏幕上显示 start Loader
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0100 ;在第2行显示
mov cx, 26 ;设置消息长度
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Start_Loader
int 0x10
;jmp $
; 使用A20快速门来开启A20信号线
push ax
in al, 0x92 ; A20快速门使用I/O端口0x92来处理A20信号线
or al, 0x02 ; 通过将0x92端口的第1位置1开启A20地址线
out 0x92, al
pop ax
cli ; 关闭外部中断
db 0x66
lgdt [GdtPtr] ; LGDT/LIDT - 加载全局/中断描述符表格寄存器
; 置位CR0寄存器的第0位开启保护模式
mov eax, cr0
or eax, 1
mov cr0, eax
; 为fs寄存器加载新的数据段的值
mov ax, SelectorData32
mov fs, ax
; fs寄存器加载完成后立即从保护模式退出。 这样能使得fs寄存器在实模式下获得大于1MB的寻址能力。
mov eax, cr0
and al, 11111110b ; 将第0位置0
mov cr0, eax
sti ; 开启外部中断
; =========在文件系统中搜索 kernel.bin==========
mov word [SectorNo], SectorNumOfRootDirStart ;保存根目录起始扇区号
Label_Search_In_Root_Dir_Begin:
cmp word [RootDirSizeForLoop], 0 ; 比较根目录扇区数量和0的关系。 cmp实际上是进行了一个减法运算
jz Label_No_KernelBin ; 等于0不存在kernel.bin
dec word [RootDirSizeForLoop]
mov ax, 0x00
mov es, ax
mov bx, 0x8000
mov ax, [SectorNo] ;向函数传入扇区号
mov cl, 1
call Func_ReadOneSector
mov si, Kernel_FileName ;向源变址寄存器传入Loader文件的名字
mov di, 0x8000
cld ;由于LODSB的加载方向与DF标志位有关因此需要用CLD清零DF标志位
mov dx, 0x10 ; 每个扇区的目录项的最大条数是(512/32=16,也就是0x10)
Label_Search_For_LoaderBin:
cmp dx, 0
jz Label_Goto_Next_Sector_In_Root_Dir
dec dx
mov cx, 11 ; cx寄存器存储目录项的文件名长度 11B包括了文件名和扩展名但是不包括 分隔符'.'
Label_Cmp_FileName:
cmp cx, 0
jz Label_FileName_Found
dec cx
lodsb ; 把si对应的字节载入al寄存器中然后由于DF为0si寄存器自增
cmp al, byte [es:di] ; 间接取址[es+di]。 也就是进行比较当前文件的名字对应字节和loader文件名对应字节
jz Label_Go_On ; 对应字节相同
jmp Label_Different ; 字节不同,不是同一个文件
Label_Go_On:
inc di
jmp Label_Cmp_FileName
Label_Different:
and di, 0xffe0 ;将di恢复到当前目录项的第0字节
add di, 0x20 ;将di跳转到下一目录项的第0字节
mov si, Kernel_FileName
jmp Label_Search_For_LoaderBin ;继续搜索下一目录项
Label_Goto_Next_Sector_In_Root_Dir:
add word [SectorNo], 1
jmp Label_Search_In_Root_Dir_Begin
Label_No_KernelBin:
; 在屏幕上显示 [ERROR] No Kernel Found.
mov ax, 0x1301
mov bx, 0x000c ; 红色闪烁高亮黑底
mov dx, 0x0200 ; 显示在第3行前面已经显示过2行了
mov cx, 24 ; 字符串长度
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_No_Loader
int 0x10
jmp $
; ========= 找到了 kernel.bin ===========
; 将内核加载到内存中
Label_FileName_Found:
mov ax, RootDirSectors
; 先取得目录项DIR_FstClus字段的值起始簇号
and di, 0xffe0
add di, 0x1a
mov cx, word [es:di]
push cx
add cx, ax
add cx, SectorBalance
mov eax, Base_Tmp_Of_Kernel_Addr ; 内核放置的临时地址
mov es, eax ;配置es和bx指定kernel.bin在内存中的起始地址
mov bx, Offset_Tmp_Of_Kernel_File
mov ax, cx
Label_Go_On_Loading_File:
;push ax
;push bx
; 显示字符.
;mov ah, 0x0e
;mov al, "."
;mov bl, 0x0f
;int 0x10
;pop bx
;pop ax
; 读取一个扇区
mov cl, 1
call Func_ReadOneSector
pop ax
; ======逐字节将内核程序复制到临时空间,然后转存到内核空间===
push cx
push eax
push fs
push edi
push ds
push esi
mov cx, 0x0200 ; 指定计数寄存器的值为512 为后面循环搬运这个扇区的数据做准备
mov ax, Base_Of_Kernel_File
mov fs, ax ; 这样在物理机上是行不通的因为这样移动的话fs就失去了32位寻址能力
mov edi, dword [OffsetOfKernelFileCount] ; 指定目的变址寄存器
mov ax, Base_Tmp_Of_Kernel_Addr
mov ds, ax
mov esi, Offset_Tmp_Of_Kernel_File ; 指定来源变址寄存器
Label_Move_Kernel:
; 真正进行数据的移动
mov al, byte [ds:esi] ; 移动到临时区域
mov byte [fs:edi], al ; 再移动到目标区域
inc esi
inc edi
loop Label_Move_Kernel
; 当前扇区数据移动完毕
mov eax, 0x1000
mov ds, eax
mov dword [OffsetOfKernelFileCount], edi ; 增加偏移量
pop esi
pop ds
pop edi
pop fs
pop eax
pop cx
call Func_GetFATEntry
cmp ax, 0x0fff
jz Label_File_Loaded
push ax
mov dx, RootDirSectors
add ax, dx
add ax, SectorBalance
; 继续读取下一个簇
jmp Label_Go_On_Loading_File
Label_File_Loaded:
;在屏幕上显示 kernel loaded
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0200 ;在第3行显示
mov cx, 20 ;设置消息长度
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Kernel_Loaded
int 0x10
; ======直接操作显示内存=======
; 从内存的0x0B800开始是一段用于显示字符的内存空间。
; 每个字符占用2bytes低字节保存要显示的字符高字节保存样式
mov ax, 0xB800
mov gs, ax
mov ah, 0x0F ;黑底白字
mov al, '.'
mov [gs:((80 * 2 + 20) * 2)], ax ;在屏幕第0行39列
Label_Kill_Motor:
; =====关闭软驱的马达======
; 向IO端口0x03f2写入0关闭所有软驱
push dx
mov dx, 0x03F2
mov al, 0
out dx, al
pop dx
; =====获取物理地址空间====
; 显示 正在获取内存结构
mov ax, 0x1301
mov bx, 0x000F
mov dx, 0x0300 ; 在第四行显示
mov cx, 34
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Start_Get_Mem_Struct
int 0x10
mov ax, 0x00
mov es, ax
mov di, Memory_Struct_Buffer_Addr ; 设置内存结构信息存储的地址
mov ebx, 0 ;第一次调用0x15的时候ebx要置为0 ebx存储的是下一个待返回的ARDS Address Range Descriptor Structure
Label_Get_Mem_Struct:
;==== 获取内存物理地址信息
; 使用0x15中断程序的功能号0xe820来获取内存信息
; 返回信息在[es:di]指向的内存中
; 一共要分5次才能把20个字节的信息获取完成
; 这些信息在内核初始化内存管理单元的时候,会去解析它们。
mov eax, 0xe820
mov ecx, 20 ; 指定ARDS结构的大小是固定值20
mov edx, 0x534d4150 ; 固定签名标记是字符串“SMAP”的ASCII码
int 0x15
jc Label_Get_Mem_Fail ; 若调用出错则CF=1
add di, 20
cmp ebx, 0
jne Label_Get_Mem_Struct ; ebx不为0
jmp Label_Get_Mem_OK ; 获取内存信息完成
Label_Get_Mem_Fail:
; =====获取内存信息失败====
; 显示 正在获取内存结构
mov ax, 0x1301
mov bx, 0x000c
mov dx, 0x0400 ; 在第5行显示
mov cx, 33
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_Mem_Failed
int 0x10
jmp $
Label_Get_Mem_OK:
; ==== 成功获取内存信息 ===
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0400 ; 在第5行显示
mov cx, 38
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_Mem_Success
int 0x10
jmp Label_Get_SVGA_Info
Label_Get_SVGA_Info:
; ==== 获取SVGA芯片的信息
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0500 ; 在第6行显示
mov cx, 34
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Start_Get_SVGA_VBE_Info
int 0x10
; 使用INT0x10的主功能号0x4F00获取SVGA VBE信息
; For more information, please visit: https://longjin666.top/?p=1321
mov ax, 0x00
mov es, ax
mov di, 0x8000
mov ax, 0x4F00
int 0x10
cmp ax, 0x004F ; 获取成功
jz Label_Get_SVGA_VBE_Success
Label_Get_SVGA_VBE_Failed:
; 获取SVGA VBE信息失败
mov ax, 0x1301
mov bx, 0x008c
mov dx, 0x0600 ; 在第7行显示
mov cx, 33
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_SVGA_VBE_Failed
int 0x10
jmp $
Label_Get_SVGA_VBE_Success:
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0600 ; 在第7行显示
mov cx, 38
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_SVGA_VBE_Success
int 0x10
Label_Get_SVGA_Mode_Info:
; ====== 获取SVGA mode信息 ======
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0700 ; 在第8行显示
mov cx, 35
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Start_Get_SVGA_Mode_Info
int 0x10
mov ax, 0x00
mov es, ax
mov si, 0x800e ; 根据文档可知偏移量0Eh处 DWORD pointer to list of supported VESA and OEM video modes
;(list of words terminated with FFFFh)
mov esi, dword [es:si]
mov edi, 0x8200
Label_SVGA_Mode_Info_Get:
mov cx, word [es:esi]
; ===========显示SVGA mode的信息
;push ax
;mov ax, 0x00
;mov al, ch
;call Label_DispAL
;mov ax, 0x00
;mov al, cl
;call Label_DispAL
;pop ax
;============
; 判断是否获取完毕
cmp cx, 0xFFFF
jz Label_SVGA_Mode_Info_Finish
mov ax, 0x4f01 ; 使用4f01功能获取SVGA的模式
int 0x10
cmp ax, 0x004f ; 判断是否获取成功
jnz Label_SVGA_Mode_Info_Fail
add esi, 2
add edi, 0x100 ; 开辟一个 256-byte 的 buffer
jmp Label_SVGA_Mode_Info_Get
Label_SVGA_Mode_Info_Fail:
; === 获取信息失败 ===
mov ax, 0x1301
mov bx, 0x008c
mov dx, 0x0800 ; 在第9行显示
mov cx, 34
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_SVGA_Mode_Failed
int 0x10
jmp $
Label_SVGA_Mode_Info_Finish:
; === 成功获取SVGA mode信息 ===
mov ax, 0x1301
mov bx, 0x000f
mov dx, 0x0800 ; 在第9行显示
mov cx, 39
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Get_SVGA_Mode_Success
int 0x10
jmp Label_Set_SVGA_Mode
Label_SET_SVGA_Mode_VESA_VBE_FAIL:
; 设置SVGA显示模式失败
mov ax, 0x1301
mov bx, 0x008c
mov dx, 0x0800 ; 在第10行显示
mov cx, 29
push ax
mov ax, ds
mov es, ax
pop ax
mov bp, Message_Set_SVGA_Mode_Failed
int 0x10
jmp $
Label_Set_SVGA_Mode:
; ===== 设置SVGA芯片的显示模式(VESA VBE) ===
mov ax, 0x4f02 ; 使用int0x10 功能号AX=4f02设置SVGA芯片的显示模式
mov bx, 0x4180 ; 显示模式可以选择0x180(1440*900 32bit)或者0x143(800*600 32bit)
int 0x10
cmp ax, 0x004F
jnz Label_SET_SVGA_Mode_VESA_VBE_FAIL
; ===== 初始化GDT表切换到保护模式 =====
cli ; 关闭外部中断
db 0x66
lgdt [GdtPtr]
db 0x66
lidt [IDT_POINTER]
mov eax, cr0
or eax, 1 ; 启用保护模式
or eax, 0x22 ; 启用x87浮点运算单元
mov cr0, eax
; 跳转到保护模式下的第一个程序
jmp dword SelectorCode32:GO_TO_TMP_Protect
[SECTION .s32]
[BITS 32]
GO_TO_TMP_Protect:
; ==== 切换到长模式 =====
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov ss, ax
mov esp, 0x7e00 ; 将栈指针设置在实模式获取到的数据的基地址上
call support_long_mode ; 检测是否支持长模式
test eax, eax ; 将eax自身相与检测是否为0test指令不会把结果赋值回去eax
jz no_support ; 不支持长模式
; 初始化临时页表, 基地址设置为0x90000
; 设置各级页表项的值(页表起始地址与页属性组成)
mov dword [0x90000], 0x91007
mov dword [0x90004], 0x00000
mov dword [0x90800], 0x91007
mov dword [0x90804], 0x00000
mov dword [0x91000], 0x92007
mov dword [0x91004], 0x00000
mov dword [0x92000], 0x000083
mov dword [0x92004], 0x000000
mov dword [0x92008], 0x200083
mov dword [0x9200c], 0x000000
mov dword [0x92010], 0x400083
mov dword [0x92014], 0x000000
mov dword [0x92018], 0x600083
mov dword [0x9201c], 0x000000
mov dword [0x92020], 0x800083
mov dword [0x92024], 0x000000
mov dword [0x92028], 0xa00083
mov dword [0x9202c], 0x000000
; === 加载GDT ===
db 0x66
lgdt [GdtPtr64] ; 加载GDT
; 把临时gdt的数据段加载到寄存器中(cs除外)
mov ax, 0x10
mov ds, ax
mov es, ax
mov fs, ax
mov gs, ax
mov ss, ax
mov esp, 0x7e00
; ====== 开启物理地址扩展 =====
; 通过bts指令将cr4第5位置位开启PAE
mov eax, cr4
bts eax, 5
mov cr4, eax
; 将临时页目录的地址设置到CR3控制寄存器中
mov eax, 0x90000
mov cr3, eax
; ==== 启用长模式 ===
; 参见英特尔开发手册合集p4360 volume4, chapter2 页码2-60 Vol. 4
; IA32_EFER寄存器的第8位是LME标志位能启用IA-32e模式
mov ecx, 0xC0000080
rdmsr
bts eax, 8
wrmsr
; === 开启分页机制 ===
mov eax, cr0
bts eax, 0 ; 再次开启保护模式
bts eax, 31 ; 开启分页管理机制
mov cr0, eax
;now enable SSE and the like
mov eax, cr0
and ax, 0xFFFB ;clear coprocessor emulation CR0.EM
or ax, 0x2 ;set coprocessor monitoring CR0.MP
mov cr0, eax
mov eax, cr4
or ax, 3 << 9 ;set CR4.OSFXSR and CR4.OSXMMEXCPT at the same time
mov cr4, eax
; === 通过此条远跳转指令处理器跳转到内核文件进行执行正式进入IA-32e模式
jmp SelectorCode64:Offset_Of_Kernel_File
support_long_mode:
; ===== 检测是否支持长模式 ====
mov eax, 0x80000000
cpuid ; cpuid指令返回的信息取决于eax的值。当前返回到eax中的是最大的输入参数值。 详见英特尔开发人员手册卷2A Chapter3 (Page 304)
cmp eax, 0x80000001
setnb al ; 当cmp结果为不低于时置位al
jb support_long_mode_done ; 当eax小于0x80000001时跳转
mov eax, 0x80000001
cpuid ; 获取特定信息参照开发人员手册卷2A p304
bt edx, 29 ; 将edx第29位的值移到CF上。该位指示了CPU是否支持IA-32e模式
; Bit 29: Intel® 64 Architecture available if 1.
setc al ; 若支持则al置位
support_long_mode_done:
movzx eax, al ; 将al零扩展为32位赋值给eax
ret
no_support:
; 不支持长模式
jmp $
[SECTION .s16lib]
[BITS 16]
; 从软盘读取一个扇区
; AX=待读取的磁盘起始扇区号
; CL=读入的扇区数量
; ES:BX=>目标缓冲区起始地址
Func_ReadOneSector:
push bp
mov bp, sp
sub esp, 2
mov byte [bp-2], cl
push bx
mov bl, [BPB_SecPerTrk]
div bl ;用AX寄存器中的值除以BL得到目标磁道号(商AL)以及目标磁道内的起始扇区号(余数AH)
inc ah ; 由于磁道内的起始扇区号从1开始计数因此将余数+1
mov cl, ah
mov dh, al
shr al, 1 ;计算出柱面号
mov ch, al
and dh, 1;计算出磁头号
pop bx
mov dl, [BS_DrvNum]
;最终dh存储了磁头号dl存储驱动器号
; ch存储柱面号cl存储起始扇区号
Label_Go_On_Reading:
; 使用BIOS中断服务程序INT13h的主功能号AH=02h实现软盘读取操作
mov ah, 2
mov al, byte [bp-2]
int 0x13
jc Label_Go_On_Reading ;当CF标志位被复位时说明数据读取完成恢复调用现场
add esp, 2
pop bp
ret
; 解析FAT表项,根据当前FAT表项索引出下一个FAT表项
Func_GetFATEntry:
; AX=FAT表项号输入、输出参数
; 保存将要被修改的寄存器
push es
push bx
push ax
; 扩展段寄存器
mov ax, 00
mov es, ax
pop ax
mov byte [Odd], 0 ;将奇数标志位置0
; 将FAT表项号转换为总的字节号
mov bx, 3
mul bx
mov bx, 2
div bx
cmp dx, 0
jz Label_Even ; 偶数项
mov byte [Odd], 1
Label_Even:
xor dx, dx ;把dx置0
; 计算得到扇区号(商)和扇区内偏移(余数)
mov bx, [BPB_BytesPerSec]
div bx
push dx
; 读取两个扇区到[es:bx]
mov bx, 0x8000
add ax, SectorNumOfFAT1Start
mov cl, 2 ; 设置读取两个扇区解决FAT表项跨扇区的问题
call Func_ReadOneSector
pop dx
add bx, dx
mov ax, [es:bx]
cmp byte [Odd], 1
jnz Label_Even_2 ;若是偶数项,则跳转
shr ax, 4 ; 解决奇偶项错位问题
Label_Even_2:
and ax, 0x0fff ; 确保表项号在正确的范围内 0x0003~0x0fff
pop bx
pop es
ret
; ==== 显示AL中的信息 ===
Label_DispAL:
push ecx
push edx
push edi
mov edi, [DisplayPosition]
mov ah, 0x0F
mov dl, al ; 为了先显示al的高4位因此先将al暂存在dl中然后把al往右移动4位
shr al, 4
mov ecx, 2 ; 计数为2
.begin:
and al, 0x0F
cmp al, 9
ja .1 ; 大于9跳转到.1
add al, '0'
jmp .2
.1:
sub al, 0x0a
add al, 'A'
.2:
; 移动到显示内存中
mov [gs:edi], ax
add edi, 2
mov al, dl
loop .begin
mov [DisplayPosition], edi
pop edi
pop edx
pop ecx
ret
; === 临时的中断描述符表 ===
; 为临时的IDT开辟空间。
; 由于模式切换过程中已经关闭了外部中断只要确保模式切换过程中不产生异常就不用完整的初始化IDT。甚至乎只要没有异常产生没有IDT也可以。
IDT:
times 0x50 dq 0
IDT_END:
IDT_POINTER:
dw IDT_END - IDT - 1
dd IDT
;==== 临时变量 =====
RootDirSizeForLoop dw RootDirSectors
SectorNo dw 0
Odd db 0
OffsetOfKernelFileCount dd Offset_Of_Kernel_File
DisplayPosition dd 0
; 要显示的消息文本
Message_Start_Loader: db "[DragonOS] Start Loader..."
Message_No_Loader: db "[ERROR] No Kernel Found."
Message_Kernel_Loaded: db "[INFO] Kernel loaded"
Message_Start_Get_Mem_Struct: db "[INFO] Try to get memory struct..."
Message_Get_Mem_Failed: db "[ERROR] Get memory struct failed."
Message_Get_Mem_Success: db "[INFO] Successfully got memory struct."
Message_Start_Get_SVGA_VBE_Info: db "[INFO] Try to get SVGA VBE info..."
Message_Get_SVGA_VBE_Failed: db "[ERROR] Get SVGA VBE info failed."
Message_Get_SVGA_VBE_Success: db "[INFO] Successfully got SVGA VBE info."
Message_Start_Get_SVGA_Mode_Info: db "[INFO] Try to get SVGA mode info..."
Message_Get_SVGA_Mode_Failed: db "[ERROR] Get SVGA Mode info failed."
Message_Get_SVGA_Mode_Success: db "[INFO] Successfully got SVGA Mode info."
Message_Set_SVGA_Mode_Failed: db "[ERROR] Set SVGA Mode failed."
Kernel_FileName: db "KERNEL BIN", 0

View File

@ -7,11 +7,13 @@ DIR_LIB=lib
lib_patterns := *.a
LIB_FILES := $(foreach DIR,$(DIR_LIB),$(addprefix $(DIR)/,$(lib_patterns)))
all: kernel
objcopy -I elf64-x86-64 -S -R ".eh_frame" -R ".comment" -O binary kernel ../bin/kernel/kernel.bin
#objcopy -I elf64-x86-64 -S -R ".comment" -O elf64-x86-64 kernel ../bin/kernel/kernel.elf
cp kernel ../bin/kernel/kernel.elf
kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o exception/8259A.o mm/mm.o process/process.o syscall/syscall.o -T link.lds
kernel: head.o entry.o main.o printk.o trap.o mm.o irq.o 8259A.o process.o syscall.o multiboot2.o
ld -b elf64-x86-64 -z muldefs -o kernel head.o exception/entry.o main.o common/printk.o exception/trap.o exception/irq.o exception/8259A.o mm/mm.o process/process.o syscall/syscall.o driver/multiboot2/multiboot2.o \
-T link.lds
head.o: head.S
gcc -E head.S > head.s # 预处理
@ -49,5 +51,8 @@ process.o: process/process.c
syscall.o: syscall/syscall.c
gcc -mcmodel=large -fno-builtin -m64 -c syscall/syscall.c -o syscall/syscall.o
multiboot2.o: driver/multiboot2/multiboot2.c
gcc -mcmodel=large -fno-builtin -m64 -c driver/multiboot2/multiboot2.c -o driver/multiboot2/multiboot2.o
clean:
rm -rf $(GARBAGE)

65
kernel/common/boot_info.h Normal file
View File

@ -0,0 +1,65 @@
/**
* @file boot_info.h
* @brief
* @author Zone.N (Zone.Niuzh@hotmail.com)
* @version 1.0
* @date 2021-09-18
* @copyright MIT LICENSE
* https://github.com/Simple-XX/SimpleKernel
* @par change log:
* <table>
* <tr><th>Date<th>Author<th>Description
* <tr><td>2021-09-18<td>digmouse233<td> doxygen
* </table>
*/
#ifndef _BOOT_INFO_H_
#define _BOOT_INFO_H_
#include "stdint.h"
//#include "resource.h"
/**
* @brief
*
* grub2 multiboot2
* opensbi dtb
*
* dtb.h multiboot2.h
* dtb.cpp multiboot2.cpp
*/
namespace BOOT_INFO {
/// 声明,定义在具体的实现中
/// 地址
extern "C" uintptr_t boot_info_addr;
/// 长度
extern size_t boot_info_size;
/**
* @brief
* @return true
* @return false
*/
extern bool init(void);
/**
* @brief
* @return resource_t
*/
extern resource_t get_memory(void);
/**
* @brief clint
* @return resource_t clint
*/
extern resource_t get_clint(void);
/**
* @brief plic
* @return resource_t plic
*/
extern resource_t get_plic(void);
};
#endif /* _BOOT_INFO_H_ */

View File

@ -0,0 +1,225 @@
// multiboot2
// How many bytes from the start of the file we search for the header.
#define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
// The magic field should contain this.
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
// This should be in %eax.
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
// Alignment of multiboot modules.
#define MULTIBOOT_MOD_ALIGN 0x00001000
// Alignment of the multiboot info structure.
#define MULTIBOOT_INFO_ALIGN 0x00000008
// Flags set in the 'flags' member of the multiboot header.
#define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
#define MULTIBOOT_TAG_TYPE_EFI32 11
#define MULTIBOOT_TAG_TYPE_EFI64 12
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
#define MULTIBOOT_TAG_TYPE_NETWORK 16
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
#define MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
// -m64 64
// 32 32 64
// 64 -m32 long -m64
// x86_64(IA32E)
// See https://wiki.osdev.org/Creating_a_64-bit_kernel:
// With a 32-bit bootstrap in your kernel
// long
// 32bit
// 32
.code32
// multiboot2
//
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
//
.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH)
// 8
.align MULTIBOOT_HEADER_ALIGN
//
.section .multiboot_header
multiboot_header:
//
.long MULTIBOOT2_HEADER_MAGIC
//
.long MULTIBOOT_ARCHITECTURE_I386
//
.long HEADER_LENGTH
//
.long CHECKSUM
// Multiboot2 Specification version 2.0.pdf
.short MULTIBOOT_HEADER_TAG_END
//
.short 0
.long 8
multiboot_header_end:
// 4KB/
.section .data
.align 0x1000
pml4:
.skip 0x1000
pdpt:
.skip 0x1000
pd:
.skip 0x1000
pt:
.skip 0x1000
// GDT
.align 16
gdt64:
null_desc:
.short 0xFFFF
.short 0
.byte 0
.byte 0
.byte 0
.byte 0
code_desc:
.short 0
.short 0
.byte 0
.byte 0x9A
.byte 0x20
.byte 0
data_desc:
.short 0
.short 0
.byte 0
.byte 0x92
.byte 0
.byte 0
user_code_desc:
.short 0
.short 0
.byte 0
.byte 0xFA
.byte 0x20
.byte 0
user_data_desc:
.short 0
.short 0
.byte 0
.byte 0xF2
.byte 0
.byte 0
gdt64_pointer:
.short gdt64_pointer-gdt64-1
.quad gdt64
gdt64_pointer64:
.short gdt64_pointer-gdt64-1
.quad gdt64
.section .text
.global _start
.type _start, @function
# multiboot2.cpp
.extern boot_info_addr
.extern multiboot2_magic
_start:
//
cli
// multiboot2_info
//mov %ebx, boot_info_addr
//
// mov %eax, multiboot2_magic
//
// 1. PAE
mov %cr4, %eax
or $(1<<5), %eax
mov %eax, %cr4
// 2.
//
mov $pml4, %eax
mov $pdpt, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
mov $pdpt, %eax
mov $pd, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
mov $pd, %eax
mov $pt, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
// 512
mov $512, %ecx
mov $pt, %eax
mov $0x3, %ebx
.fill_pt:
mov %ebx, 0(%eax)
add $0x1000, %ebx
add $8, %eax
loop .fill_pt
// CR3
mov $pml4, %eax
mov %eax, %cr3
// 3. long
mov $0xC0000080, %ecx
rdmsr
or $(1<<8), %eax
wrmsr
// 4.
mov %cr0, %eax
or $(1<<31), %eax
mov %eax, %cr0
// 5. GDT
mov $gdt64_pointer, %eax
lgdt 0(%eax)
// 6. 64
jmp $0x8, $_start64
hlt
ret

View File

@ -0,0 +1,3 @@
int *boot_info_addr;
int *multiboot2_magic;

View File

@ -0,0 +1,104 @@
/**
* @file multiboot2.cpp
* @brief multiboot2
* @author Zone.N (Zone.Niuzh@hotmail.com)
* @version 1.0
* @date 2021-09-18
* @copyright MIT LICENSE
* https://github.com/Simple-XX/SimpleKernel
* @par change log:
* <table>
* <tr><th>Date<th>Author<th>Description
* <tr><td>2021-09-18<td>digmouse233<td> doxygen
* </table>
*/
#include "assert.h"
#include "stdio.h"
//#include "common.h"
#include "multiboot2.h"
#include "boot_info.h"
//#include "resource.h"
//#include "pmm.h"
/// @todo 优化
void MULTIBOOT2::multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
void *_data) {
uintptr_t addr = BOOT_INFO::boot_info_addr;
// 下一字节开始为 tag 信息
iter_data_t *tag = (iter_data_t *)(addr + 8);
for (; tag->type != MULTIBOOT_TAG_TYPE_END;
tag = (iter_data_t *)((uint8_t *)tag + COMMON::ALIGN(tag->size, 8))) {
if (_fun(tag, _data) == true) {
return;
}
}
return;
}
bool MULTIBOOT2::multiboot2_init(void) {
uintptr_t addr = BOOT_INFO::boot_info_addr;
// 判断魔数是否正确
assert(BOOT_INFO::multiboot2_magic == MULTIBOOT2_BOOTLOADER_MAGIC);
assert((reinterpret_cast<uintptr_t>(addr) & 7) == 0);
// addr+0 保存大小
BOOT_INFO::boot_info_size = *(uint32_t *)addr;
return true;
}
// 读取 grub2 传递的物理内存信息,保存到 e820map_t 结构体中
// 一般而言是这样的
// 地址(长度) 类型
// 0x00(0x9F000) 0x1
// 0x9F000(0x1000) 0x2
// 0xE8000(0x18000) 0x2
// 0x100000(0x7EF0000) 0x1
// 0x7FF0000(0x10000) 0x3
// 0xFFFC0000(0x40000) 0x2
bool MULTIBOOT2::get_memory(const iter_data_t *_iter_data, void *_data) {
if (_iter_data->type != MULTIBOOT2::MULTIBOOT_TAG_TYPE_MMAP) {
return false;
}
resource_t *resource = (resource_t *)_data;
resource->type = resource_t::MEM;
resource->name = (char *)"available phy memory";
resource->mem.addr = 0x0;
resource->mem.len = 0;
MULTIBOOT2::multiboot_mmap_entry_t *mmap =
((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)->entries;
for (; (uint8_t *)mmap < (uint8_t *)_iter_data + _iter_data->size;
mmap = (MULTIBOOT2::multiboot_mmap_entry_t
*)((uint8_t *)mmap +
((MULTIBOOT2::multiboot_tag_mmap_t *)_iter_data)
->entry_size)) {
// 如果是可用内存或地址小于 1M
// 这里将 0~1M 的空间全部算为可用,在 c++ 库可用后进行优化
if (mmap->type == MULTIBOOT_MEMORY_AVAILABLE ||
mmap->addr < 1 * COMMON::MB) {
// 长度+
resource->mem.len += mmap->len;
}
}
return true;
}
namespace BOOT_INFO {
// 地址
uintptr_t boot_info_addr;
// 长度
size_t boot_info_size;
// 魔数
uint32_t multiboot2_magic;
bool init(void) {
auto res = MULTIBOOT2::multiboot2_init();
info("BOOT_INFO init.\n");
return res;
}
resource_t get_memory(void) {
resource_t resource;
MULTIBOOT2::multiboot2_iter(MULTIBOOT2::get_memory, &resource);
return resource;
}
};

View File

@ -0,0 +1,334 @@
/**
* @file multiboot2.h
* @brief multiboot2
* @author Zone.N (Zone.Niuzh@hotmail.com)
* @version 1.0
* @date 2021-09-18
* @copyright MIT LICENSE
* https://github.com/Simple-XX/SimpleKernel
* @par change log:
* <table>
* <tr><th>Date<th>Author<th>Description
* <tr><td>2021-09-18<td>digmouse233<td> doxygen
* </table>
*/
#ifndef _MULTIBOOT2_H_
#define _MULTIBOOT2_H_
#include "stdint.h"
#include "stdbool.h"
#include "boot_info.h"
/// @see Multiboot2 Specification version 2.0.pdf
// 启动后,在 32 位内核进入点,机器状态如下:
// 1. CS 指向基地址为 0x00000000限长为4G 1的代码段描述符。
// 2. DSSSESFS 和 GS 指向基地址为0x00000000限长为4G
// 1的数据段描述符。
// 3. A20 地址线已经打开。
// 4. 页机制被禁止。
// 5. 中断被禁止。
// 6. EAX = 0x2BADB002
// 7. 系统信息和启动信息块的线性地址保存在 EBX中相当于一个指针
// 以下即为这个信息块的结构
/**
* @brief MULTIBOOT2
*/
class MULTIBOOT2 {
private:
/* How many bytes from the start of the file we search for the header. */
static constexpr const uint32_t MULTIBOOT_SEARCH = 32768;
static constexpr const uint32_t MULTIBOOT_HEADER_ALIGN = 8;
/* The magic field should contain this. */
static constexpr const uint32_t MULTIBOOT2_HEADER_MAGIC = 0xe85250d6;
/* This should be in %eax. */
static constexpr const uint32_t MULTIBOOT2_BOOTLOADER_MAGIC = 0x36d76289;
/* Alignment of multiboot modules. */
static constexpr const uint32_t MULTIBOOT_MOD_ALIGN = 0x00001000;
/* Alignment of the multiboot info structure. */
static constexpr const uint32_t MULTIBOOT_INFO_ALIGN = 0x00000008;
/* Flags set in the 'flags' member of the multiboot header. */
static constexpr const uint32_t MULTIBOOT_TAG_ALIGN = 8;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_END = 0;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_CMDLINE = 1;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME = 2;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_MODULE = 3;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BASIC_MEMINFO = 4;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_BOOTDEV = 5;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_MMAP = 6;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_VBE = 7;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_FRAMEBUFFER = 8;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ELF_SECTIONS = 9;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_APM = 10;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI32 = 11;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI64 = 12;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_SMBIOS = 13;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ACPI_OLD = 14;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_ACPI_NEW = 15;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_NETWORK = 16;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI_MMAP = 17;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI_BS = 18;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI32_IH = 19;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_EFI64_IH = 20;
static constexpr const uint32_t MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR = 21;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_END = 0;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST =
1;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ADDRESS = 2;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS = 3;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS = 4;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_FRAMEBUFFER = 5;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_MODULE_ALIGN = 6;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_EFI_BS = 7;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 =
8;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 =
9;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_RELOCATABLE = 10;
static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_I386 = 0;
static constexpr const uint32_t MULTIBOOT_ARCHITECTURE_MIPS32 = 4;
static constexpr const uint32_t MULTIBOOT_HEADER_TAG_OPTIONAL = 1;
static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_NONE = 0;
static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_LOW = 1;
static constexpr const uint32_t MULTIBOOT_LOAD_PREFERENCE_HIGH = 2;
static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED =
1;
static constexpr const uint32_t MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED =
2;
struct multiboot_header_t {
// Must be MULTIBOOT_MAGIC - see above.
uint32_t magic;
// ISA
uint32_t architecture;
// Total header length.
uint32_t header_length;
// The above fields plus this one must equal 0 mod 2^32.
uint32_t checksum;
};
struct multiboot_header_tag_t {
uint16_t type;
uint16_t flags;
uint32_t size;
};
struct multiboot_header_tag_information_request_t : multiboot_header_tag_t {
uint32_t requests[0];
};
struct multiboot_header_tag_address_t : multiboot_header_tag_t {
uint32_t header_addr;
uint32_t load_addr;
uint32_t load_end_addr;
uint32_t bss_end_addr;
};
struct multiboot_header_tag_entry_address_t : multiboot_header_tag_t {
uint32_t entry_addr;
};
struct multiboot_header_tag_console_flags_t : multiboot_header_tag_t {
uint32_t console_flags;
};
struct multiboot_header_tag_framebuffer_t : multiboot_header_tag_t {
uint32_t width;
uint32_t height;
uint32_t depth;
};
struct multiboot_header_tag_module_align_t : multiboot_header_tag_t {
;
};
struct multiboot_header_tag_relocatable_t : multiboot_header_tag_t {
uint32_t min_addr;
uint32_t max_addr;
uint32_t align;
uint32_t preference;
};
struct multiboot_color_t {
uint8_t red;
uint8_t green;
uint8_t blue;
};
static constexpr const uint32_t MULTIBOOT_MEMORY_AVAILABLE = 1;
static constexpr const uint32_t MULTIBOOT_MEMORY_RESERVED = 2;
static constexpr const uint32_t MULTIBOOT_MEMORY_ACPI_RECLAIMABLE = 3;
static constexpr const uint32_t MULTIBOOT_MEMORY_NVS = 4;
static constexpr const uint32_t MULTIBOOT_MEMORY_BADRAM = 5;
struct multiboot_mmap_entry_t {
uint64_t addr;
uint64_t len;
uint32_t type;
uint32_t zero;
};
struct multiboot_tag_t {
uint32_t type;
uint32_t size;
};
struct multiboot_tag_string_t : multiboot_tag_t {
char string[0];
};
struct multiboot_tag_module_t : multiboot_tag_t {
uint32_t mod_start;
uint32_t mod_end;
char cmdline[0];
};
struct multiboot_tag_basic_meminfo_t : multiboot_tag_t {
uint32_t mem_lower;
uint32_t mem_upper;
};
struct multiboot_tag_bootdev_t : multiboot_tag_t {
uint32_t biosdev;
uint32_t slice;
uint32_t part;
};
struct multiboot_tag_mmap_t : multiboot_tag_t {
uint32_t entry_size;
uint32_t entry_version;
multiboot_mmap_entry_t entries[0];
};
struct multiboot_vbe_info_block_t {
uint8_t external_specification[512];
};
struct multiboot_vbe_mode_info_block_t {
uint8_t external_specification[256];
};
struct multiboot_tag_vbe_t : multiboot_tag_t {
uint16_t vbe_mode;
uint16_t vbe_interface_seg;
uint16_t vbe_interface_off;
uint16_t vbe_interface_len;
multiboot_vbe_info_block_t vbe_control_info;
multiboot_vbe_mode_info_block_t vbe_mode_info;
};
struct multiboot_tag_elf_sections_t : multiboot_tag_t {
uint32_t num;
uint32_t entsize;
// 段字符串表索引
uint32_t shndx;
char sections[0];
};
struct multiboot_tag_apm_t : multiboot_tag_t {
uint16_t version;
uint16_t cseg;
uint32_t offset;
uint16_t cseg_16;
uint16_t dseg;
uint16_t flags;
uint16_t cseg_len;
uint16_t cseg_16_len;
uint16_t dseg_len;
};
struct multiboot_tag_efi32_t : multiboot_tag_t {
uint32_t pointer;
};
struct multiboot_tag_efi64_t : multiboot_tag_t {
uint64_t pointer;
};
struct multiboot_tag_smbios_t : multiboot_tag_t {
uint8_t major;
uint8_t minor;
uint8_t reserved[6];
uint8_t tables[0];
};
struct multiboot_tag_old_acpi_t : multiboot_tag_t {
uint8_t rsdp[0];
};
struct multiboot_tag_new_acpi_t : multiboot_tag_t {
uint8_t rsdp[0];
};
struct multiboot_tag_network_t : multiboot_tag_t {
uint8_t dhcpack[0];
};
struct multiboot_tag_efi_mmap_t : multiboot_tag_t {
uint32_t descr_size;
uint32_t descr_vers;
uint8_t efi_mmap[0];
};
struct multiboot_tag_efi32_ih_t : multiboot_tag_t {
uint32_t pointer;
};
struct multiboot_tag_efi64_ih_t : multiboot_tag_t {
uint64_t pointer;
};
struct multiboot_tag_load_base_addr_t : multiboot_tag_t {
uint32_t load_base_addr;
};
// 迭代变量
// 与 multiboot_tag_t 相同
struct iter_data_t {
uint32_t type;
uint32_t size;
};
public:
/**
* @brief
* @return true
* @return false
*/
static bool multiboot2_init(void);
/**
* @brief
* @param _fun
* @param _data
*/
static void multiboot2_iter(bool (*_fun)(const iter_data_t *, void *),
void *_data);
/**
* @brief
* @param _iter_data
* @param _data
* @return true
* @return false
*/
static bool get_memory(const iter_data_t *_iter_data, void *_data);
};
namespace BOOT_INFO {
/// 魔数
extern "C" uint32_t multiboot2_magic;
};
#endif /* _MULTIBOOT2_H_ */

View File

@ -4,11 +4,247 @@
#include "common/asm.h"
// multiboot2
// How many bytes from the start of the file we search for the header.
#define MULTIBOOT_SEARCH 32768
#define MULTIBOOT_HEADER_ALIGN 8
// The magic field should contain this.
#define MULTIBOOT2_HEADER_MAGIC 0xe85250d6
// This should be in %eax.
#define MULTIBOOT2_BOOTLOADER_MAGIC 0x36d76289
// Alignment of multiboot modules.
#define MULTIBOOT_MOD_ALIGN 0x00001000
// Alignment of the multiboot info structure.
#define MULTIBOOT_INFO_ALIGN 0x00000008
// Flags set in the 'flags' member of the multiboot header.
#define MULTIBOOT_TAG_ALIGN 8
#define MULTIBOOT_TAG_TYPE_END 0
#define MULTIBOOT_TAG_TYPE_CMDLINE 1
#define MULTIBOOT_TAG_TYPE_BOOT_LOADER_NAME 2
#define MULTIBOOT_TAG_TYPE_MODULE 3
#define MULTIBOOT_TAG_TYPE_BASIC_MEMINFO 4
#define MULTIBOOT_TAG_TYPE_BOOTDEV 5
#define MULTIBOOT_TAG_TYPE_MMAP 6
#define MULTIBOOT_TAG_TYPE_VBE 7
#define MULTIBOOT_TAG_TYPE_FRAMEBUFFER 8
#define MULTIBOOT_TAG_TYPE_ELF_SECTIONS 9
#define MULTIBOOT_TAG_TYPE_APM 10
#define MULTIBOOT_TAG_TYPE_EFI32 11
#define MULTIBOOT_TAG_TYPE_EFI64 12
#define MULTIBOOT_TAG_TYPE_SMBIOS 13
#define MULTIBOOT_TAG_TYPE_ACPI_OLD 14
#define MULTIBOOT_TAG_TYPE_ACPI_NEW 15
#define MULTIBOOT_TAG_TYPE_NETWORK 16
#define MULTIBOOT_TAG_TYPE_EFI_MMAP 17
#define MULTIBOOT_TAG_TYPE_EFI_BS 18
#define MULTIBOOT_TAG_TYPE_EFI32_IH 19
#define MULTIBOOT_TAG_TYPE_EFI64_IH 20
#define MULTIBOOT_TAG_TYPE_LOAD_BASE_ADDR 21
#define MULTIBOOT_HEADER_TAG_END 0
#define MULTIBOOT_HEADER_TAG_INFORMATION_REQUEST 1
#define MULTIBOOT_HEADER_TAG_ADDRESS 2
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS 3
#define MULTIBOOT_HEADER_TAG_CONSOLE_FLAGS 4
#define MULTIBOOT_HEADER_TAG_FRAMEBUFFER 5
#define MULTIBOOT_HEADER_TAG_MODULE_ALIGN 6
#define MULTIBOOT_HEADER_TAG_EFI_BS 7
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI32 8
#define MULTIBOOT_HEADER_TAG_ENTRY_ADDRESS_EFI64 9
#define MULTIBOOT_HEADER_TAG_RELOCATABLE 10
#define MULTIBOOT_ARCHITECTURE_I386 0
#define MULTIBOOT_ARCHITECTURE_MIPS32 4
#define MULTIBOOT_HEADER_TAG_OPTIONAL 1
#define MULTIBOOT_LOAD_PREFERENCE_NONE 0
#define MULTIBOOT_LOAD_PREFERENCE_LOW 1
#define MULTIBOOT_LOAD_PREFERENCE_HIGH 2
#define MULTIBOOT_CONSOLE_FLAGS_CONSOLE_REQUIRED 1
#define MULTIBOOT_CONSOLE_FLAGS_EGA_TEXT_SUPPORTED 2
// -m64 64
// 32 32 64
// 64 -m32 long -m64
// x86_64(IA32E)
// See https://wiki.osdev.org/Creating_a_64-bit_kernel:
// With a 32-bit bootstrap in your kernel
// long
// 32bit
// 32
.code32
// multiboot2
//
.SET HEADER_LENGTH, multiboot_header_end - multiboot_header
//
.SET CHECKSUM, -(MULTIBOOT2_HEADER_MAGIC + MULTIBOOT_ARCHITECTURE_I386 + HEADER_LENGTH)
// 8
.align MULTIBOOT_HEADER_ALIGN
//
.section .multiboot_header
multiboot_header:
//
.long MULTIBOOT2_HEADER_MAGIC
//
.long MULTIBOOT_ARCHITECTURE_I386
//
.long HEADER_LENGTH
//
.long CHECKSUM
// Multiboot2 Specification version 2.0.pdf
.short MULTIBOOT_HEADER_TAG_END
//
.short 0
.long 8
multiboot_header_end:
// 4KB/
.section .data
.align 0x1000
pml4:
.skip 0x1000
pdpt:
.skip 0x1000
pd:
.skip 0x1000
pt:
.skip 0x1000
// GDT
.align 16
gdt64:
null_desc:
.short 0xFFFF
.short 0
.byte 0
.byte 0
.byte 0
.byte 0
code_desc:
.short 0
.short 0
.byte 0
.byte 0x9A
.byte 0x20
.byte 0
data_desc:
.short 0
.short 0
.byte 0
.byte 0x92
.byte 0
.byte 0
user_code_desc:
.short 0
.short 0
.byte 0
.byte 0xFA
.byte 0x20
.byte 0
user_data_desc:
.short 0
.short 0
.byte 0
.byte 0xF2
.byte 0
.byte 0
gdt64_pointer:
.short gdt64_pointer-gdt64-1
.quad gdt64
gdt64_pointer64:
.short gdt64_pointer-gdt64-1
.quad gdt64
.section .text
.global _start
.type _start, @function
# multiboot2.cpp
.extern boot_info_addr
.extern multiboot2_magic
_start:
//
cli
// multiboot2_info
//mov %ebx, boot_info_addr
//
//mov %eax, multiboot2_magic
/
// 1. PAE
mov %cr4, %eax
or $(1<<5), %eax
mov %eax, %cr4
// 2.
//
mov $pml4, %eax
mov $pdpt, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
mov $pdpt, %eax
mov $pd, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
mov $pd, %eax
mov $pt, %ebx
or $0x3, %ebx
mov %ebx, 0(%eax)
//
// 512
mov $512, %ecx
mov $pt, %eax
mov $0x3, %ebx
.fill_pt:
mov %ebx, 0(%eax)
add $0x1000, %ebx
add $8, %eax
loop .fill_pt
// CR3
mov $pml4, %eax
mov %eax, %cr3
// 3. long
mov $0xC0000080, %ecx
rdmsr
or $(1<<8), %eax
wrmsr
// 4.
mov %cr0, %eax
or $(1<<31), %eax
mov %eax, %cr0
// 5. GDT
mov $gdt64_pointer, %eax
lgdt 0(%eax)
// 6. 64
jmp $0x8, $_start64
hlt
ret
.section .text
.global _start
_start:
.code64
.global _start64
.type _start64, @function
.extern Start_Kernel
ENTRY(_start64)
//
mov $0x10, %ax
mov %ax, %ds
@ -28,14 +264,26 @@ _start:
mov %ax, %fs
mov %ax, %ss
mov %ax, %gs
movq $0x7e00, %rsp
// 2.
//
mov $__PML4E, %eax
mov $__PDPTE, %ebx
or $0x7, %ebx
mov %ebx, 0(%eax)
//
mov $__PDPTE, %eax
mov $__PDE, %ebx
or $0x7, %ebx
mov %ebx, 0(%eax)
// ==== CR3
movq $0x101000, %rax //
movq $__PML4E, %rax //
movq %rax, %cr3
movq switch_seg(%rip), %rax
movq switch_seg(%rip), %rax
// ljmplcallGASlretcs
// Amazing
pushq $0x08 //
@ -44,9 +292,11 @@ _start:
// 64
switch_seg:
.quad entry64
entry64:
movq $0x10, %rax
movq %rax, %ds
movq %rax, %es
@ -119,11 +369,8 @@ SetUp_TSS64:
// mov $0x50, %ax // 80
// ltr %ax
//
movq go_to_kernel(%rip), %rax
pushq $0x08
pushq %rax
lretq
call Start_Kernel
go_to_kernel:
.quad Start_Kernel
@ -148,13 +395,14 @@ ENTRY(_stack_start)
//
.align 8 //8byte
.align 0x1000 //8byte
.org 0x1000 //0x1000
__PML4E:
.quad 0x102007 // 访 31~12
.fill 255,8,0
.quad 0x102007
.quad 0x102007
.fill 255,8,0
.org 0x2000
@ -185,6 +433,7 @@ __PDE:
// GDT
.section .data
.align 16
.global GDT_Table // 使GDT访
GDT_Table:

View File

@ -5,10 +5,14 @@ ENTRY(_start)
SECTIONS
{
. = 0xffff800000000000 + 0x100000;
. = 0;
. = 1M;
.text :
{
_text = .;
*(.multiboot_header)
*(.text)
_etext = .;
@ -19,6 +23,7 @@ SECTIONS
_data = .;
*(.data)
*(.eh_frame)
_edata = .;
}
.rodata :

View File

@ -13,10 +13,10 @@
#include "syscall/syscall.h"
unsigned int *FR_address = (unsigned int *)0xffff800000a00000; //帧缓存区的地址
// char fxsave_region[512] __attribute__((aligned(16)));
// char fxsave_region[512] __attribute__((aligned(16)));
struct memory_desc memory_management_struct = {{0}, 0};
//struct Global_Memory_Descriptor memory_management_struct = {{0}, 0};
struct memory_desc memory_management_struct = {{0}, 0};
// struct Global_Memory_Descriptor memory_management_struct = {{0}, 0};
void show_welcome()
{
@ -37,7 +37,6 @@ void show_welcome()
printk_color(0x00e0ebeb, 0x00e0ebeb, " \n\n");
}
// 测试内存管理单元
/*
void test_mm()
@ -63,18 +62,16 @@ void test_mm()
// 初始化系统各模块
void system_initialize()
{
// 初始化printk
init_printk(1440, 900, FR_address, 1440 * 900 * 4, 8, 16);
// 初始化printk
init_printk(1024, 768, FR_address, 1024 * 768 * 4, 8, 16);
printk("11111\n");
load_TR(10); // 加载TR寄存器
while(1);
// 初始化任务状态段表
ul tss_item_addr = 0xffff800000007c00;
set_TSS64(_stack_start, _stack_start, _stack_start, tss_item_addr, tss_item_addr,
tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr, tss_item_addr);
// 初始化中断描述符表
init_sys_vector();
@ -96,12 +93,10 @@ void Start_Kernel(void)
{
system_initialize();
// show_welcome();
// test_mm();
while (1)
;
}

View File

@ -264,6 +264,8 @@ unsigned long do_fork(struct pt_regs *regs, unsigned long clone_flags, unsigned
thd->rbp = (ul)tsk + STACK_SIZE;
thd->rip = regs->rip;
thd->rsp = (ul)tsk + STACK_SIZE - sizeof(struct pt_regs);
thd->fs = KERNEL_DS;
thd->gs = KERNEL_DS;
// 若进程不是内核层的进程则跳转到ret from system call
if (!(tsk->flags & PF_KTHREAD))

100
run.sh Normal file
View File

@ -0,0 +1,100 @@
# ======检查是否以sudo运行=================
#uid=`id -u`
#if [ ! $uid == "0" ];then
# echo "请以sudo权限运行"
# exit
#fi
# 第一个参数如果是--notbuild 那就不构建,直接运行
if [ ! "$1" == "--nobuild" ]; then
echo "开始构建..."
make all -j 16
make clean
fi
IA32_USE_QEMU=1
bochsrc="./bochsrc"
ARCH="x86_64"
# 内核映像
kernel='./bin/kernel/kernel.elf'
iso_boot_grub='./iso/boot/grub'
iso_boot='./iso/boot/'
iso='./DragonOS.iso'
iso_folder='./iso/'
# toolchain
OS=`uname -s`
if [ "${OS}" == "Linux" ]; then
GRUB_PATH="$(dirname $(which grub-file))"
elif [ "${OS}" == "Darwin" ]; then
GRUB_PATH="$(pwd)/tools/grub-2.04/build/grub/bin"
fi
export PATH="${GRUB_PATH}:$PATH"
# ==============检查文件是否齐全================
bins[0]=${kernel}
for file in ${bins[*]};do
if [ ! -x $file ]; then
echo "$file 不存在!"
exit
fi
done
# ===============文件检查完毕===================
# 如果是 i386/x86_64需要判断是否符合 multiboot2 标准
if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
if ${GRUB_PATH}/grub-file --is-x86-multiboot2 ${kernel}; then
echo Multiboot2 Confirmed!
else
echo NOT Multiboot2!
exit
fi
fi
# 检测路径是否合法,发生过 rm -rf -f /* 的惨剧
if [ "${iso_boot}" == "" ]; then
echo iso_boot path error.
else
mkdir -p ${iso_boot}
rm -rf -f ${iso_boot}/*
fi
# 设置 grub 相关数据
if [ ${ARCH} == "i386" ] || [ ${ARCH} == "x86_64" ]; then
cp ${kernel} ${iso_boot}
mkdir ${iso_boot_grub}
touch ${iso_boot_grub}/grub.cfg
echo 'set timeout=15
set default=0
menuentry "DragonOS" {
multiboot2 /boot/kernel.elf "KERNEL_ELF"
}' >${iso_boot_grub}/grub.cfg
fi
${GRUB_PATH}/grub-mkrescue -o ${iso} ${iso_folder}
rm -rf ${iso_folder}
# 进行启动前检查
flag_can_run=0
if [ -d "${iso_folder}" ]; then
flag_can_run=0
echo "${iso_folder} 文件夹未删除!"
else
flag_can_run=1
fi
if [ $flag_can_run -eq 1 ]; then
if [ ${IA32_USE_QEMU} == 0 ]; then
bochs -q -f ${bochsrc} -rc ./tools/bochsinit
else
qemu-system-x86_64 -cdrom ${iso} -m 128M \
-monitor telnet::2333,server,nowait -serial stdio
fi
else
echo "不满足运行条件"
fi

View File

@ -1,80 +0,0 @@
# ======检查是否以sudo运行=================
uid=`id -u`
if [ ! $uid == "0" ];then
echo "请以sudo权限运行"
exit
fi
# 第一个参数如果是--notbuild 那就不构建,直接运行
if [ ! "$1" == "--nobuild" ]; then
echo "开始构建..."
make all -j 16
make clean
fi
# ==============检查文件是否齐全================
bins[0]=bin/bootloader/boot.bin
bins[1]=bin/bootloader/loader.bin
bins[2]=bin/boot.img
bins[3]=bin/kernel/kernel.bin
for file in ${bins[*]};do
if [ ! -x $file ]; then
echo "$file 不存在!"
exit
fi
done
# ===============文件检查完毕===================
# =========将引导程序写入boot.img=============
dd if=bin/bootloader/boot.bin of=bin/boot.img bs=512 count=1 conv=notrunc
# =========创建临时文件夹==================
# 判断临时文件夹是否存在,若不存在则创建新的
if [ ! -d "tmp/" ]; then
mkdir tmp/
echo "创建了tmp文件夹"
fi
# ==============挂载boot.img=============
mkdir tmp/boot
mount bin/boot.img tmp/boot -t vfat -o loop
# 检查是否挂载成功
if mountpoint -q tmp/boot
then
echo "成功挂载 boot.img 到 tmp/boot"
# ========把loader.bin复制到boot.img==========
cp bin/bootloader/loader.bin tmp/boot
# ========把内核程序复制到boot.img======
cp bin/kernel/kernel.bin tmp/boot
sync
# 卸载磁盘
umount tmp/boot
else
echo "挂载 boot.img 失败!"
fi
# 运行结束后删除tmp文件夹
rm -rf tmp
# 进行启动前检查
flag_can_run=0
if [ -d "tmp/" ]; then
flag_can_run=0
echo "tmp文件夹未删除"
else
flag_can_run=1
fi
if [ $flag_can_run -eq 1 ]; then
bochs -f ./bochsrc -q
else
echo "不满足运行条件"
fi

View File

@ -1,78 +0,0 @@
# ======检查是否以sudo运行=================
uid=`id -u`
if [ ! $uid == "0" ];then
echo "请以sudo权限运行"
exit
fi
# 第一个参数如果是--notbuild 那就不构建,直接运行
if [ ! "$1" == "--nobuild" ]; then
echo "开始构建..."
make all
make clean
fi
# ==============检查文件是否齐全================
bins[0]=bin/bootloader/boot.bin
bins[1]=bin/bootloader/loader.bin
bins[2]=bin/boot.img
bins[3]=bin/kernel/kernel.bin
for file in ${bins[*]};do
if [ ! -x $file ]; then
echo "$file 不存在!"
exit
fi
done
# ===============文件检查完毕===================
# =========将引导程序写入boot.img=============
dd if=bin/bootloader/boot.bin of=bin/boot.img bs=512 count=1 conv=notrunc
# =========创建临时文件夹==================
# 判断临时文件夹是否存在,若不存在则创建新的
if [ ! -d "tmp/" ]; then
mkdir tmp/
echo "创建了tmp文件夹"
fi
# ==============挂载boot.img=============
mkdir tmp/boot
mount bin/boot.img tmp/boot -t vfat -o loop
# 检查是否挂载成功
if mountpoint -q tmp/boot
then
echo "成功挂载 boot.img 到 tmp/boot"
# ========把loader.bin复制到boot.img==========
cp bin/bootloader/loader.bin tmp/boot
# ========把内核程序复制到boot.img======
cp bin/kernel/kernel.bin tmp/boot
sync
# 卸载磁盘
umount tmp/boot
else
echo "挂载 boot.img 失败!"
fi
# 运行结束后删除tmp文件夹
rm -rf tmp
# 进行启动前检查
flag_can_run=0
if [ -d "tmp/" ]; then
flag_can_run=0
echo "tmp文件夹未删除"
else
flag_can_run=1
fi
if [ $flag_can_run -eq 1 ]; then
qemu-system-x86_64 -s -S -m 2048 -fda bin/boot.img
else
echo "不满足运行条件"
fi