将Bootloader方式从Legacy改成UFEI之后,由于Bootloader的获取的信息存放在了不同的数据结构中,因此内核程序需要进行相应的调整。
一、内核头程序head.S
田宇老师的《一个UEFI引导程序的实现》一文提出:“由于数据段描述符在GDT表中的位置无法确定,从而就无法直接通过段选择子对段寄存器进行赋值。不过,好在栈段寄存器SS指向的段是可读写的,那么将此段作为数据段是可行的。”
基于此关键修改部分如下:
#include "linkage.h"
.section .text
ENTRY(_start)
mov %ss, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %ss
mov $0x7E00, %esp
movq $0x101000, %rax
movq %rax, %cr3
//======= load GDTR
lgdt GDT_POINTER(%rip)
//======= load IDTR
lidt IDT_POINTER(%rip)
mov $0x10, %ax
mov %ax, %ds
mov %ax, %es
mov %ax, %fs
mov %ax, %gs
mov %ax, %ss
movq _stack_start(%rip), %rsp
//======= load cr3
movq $0x101000, %rax
movq %rax, %cr3
movq switch_seg(%rip), %rax
pushq $0x08
pushq %rax
lretq
......
//======= init page
.align 8
.org 0x1000
__PML4E:
.quad 0x102007
.fill 255,8,0
.quad 0x102007
.fill 255,8,0
.org 0x2000
__PDPTE:
.quad 0x103007 /* 0x103003 */
.fill 511,8,0
.org 0x3000
__PDE:
.quad 0x000087
.quad 0x200087
.quad 0x400087
.quad 0x600087
.quad 0x800087
.quad 0xa00087 /*0x a00000*/
.quad 0xc00087
.quad 0xe00087
.quad 0x1000087
.quad 0x1200087 /*0x1000000*/
.quad 0x1400087
.quad 0x1600087
.quad 0x1800087
.fill 499,8,0
二、内存初始化函数init_memory
内存的信息如今放在了boot_para_info->E820_Info.E820_Entry
之中,因此需要对内存初始化函数init_memory进行相应的修改:
核心代码在于将
p = (struct E820 *)0xffff800000007e00;
修改为
p = (struct EFI_E820_MEMORY_DESCRIPTOR *)boot_para_info->E820_Info.E820_Entry;
三、帧缓存区地址重映射
此处也用到了bootloader获取的VBE信息,因此也需要进行相应的修改:
- FB_addr初始值:
unsigned int * FB_addr = (unsigned int *)Phy_To_Virt(boot_para_info->Graphics_Info.FrameBufferBase);
- 页表基地址:
unsigned long phy = boot_para_info->Graphics_Info.FrameBufferBase + i;
FB_addr更改值:
Pos.FB_addr = (unsigned int *)Phy_To_Virt(boot_para_info->Graphics_Info.FrameBufferBase);