mirror of
https://github.com/DragonOS-Community/DragonOS.git
synced 2025-06-20 01:46:31 +00:00
🆕 完成了系统信息的获取、屏幕大小切换、cpu模式切换
This commit is contained in:
@ -17,20 +17,37 @@ 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
|
||||
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位宽的处理器上
|
||||
@ -349,7 +366,7 @@ Label_Get_Mem_OK:
|
||||
mov ax, 0x1301
|
||||
mov bx, 0x000f
|
||||
mov dx, 0x0400 ; 在第5行显示
|
||||
mov cx, 39
|
||||
mov cx, 38
|
||||
push ax
|
||||
mov ax, ds
|
||||
mov es, ax
|
||||
@ -364,16 +381,290 @@ Label_Get_SVGA_Info:
|
||||
mov ax, 0x1301
|
||||
mov bx, 0x000f
|
||||
mov dx, 0x0500 ; 在第6行显示
|
||||
mov cx, 30
|
||||
mov cx, 34
|
||||
push ax
|
||||
mov ax, ds
|
||||
mov es, ax
|
||||
pop ax
|
||||
mov bp, Message_Start_Get_SVGA_Info
|
||||
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 ; 启用保护模式
|
||||
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自身相与,检测是否为0(test指令不会把结果赋值回去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
|
||||
|
||||
|
||||
; === 通过此条远跳转指令,处理器跳转到内核文件进行执行,正式进入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=读入的扇区数量
|
||||
@ -471,24 +762,75 @@ Label_Even_2:
|
||||
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] Successful to get memory struct."
|
||||
Message_Start_Get_SVGA_Info: db "[INFO] Try to get SVGA info..."
|
||||
|
||||
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
|
Reference in New Issue
Block a user