嗨我是k66,今天是系列文Day23,祝大家中秋節快樂!本篇延續前篇實作按B進入Boot Menu。前篇完成「按B」及「進入Boot Menu」,本篇要實作「選擇Kernel」功能。在進入程式碼前,先科普個小知識,Kernel可想像成OS的核心程式碼。常用的GRUB是Bootloader,它會讓使用者選擇要進入哪個作業系統(或哪個Kernel),因此,本篇BootMenu會設計成讓使用者輸入1或2進入Kernel1或Kernel2。
放碼上來!程式碼連結
static void BootMenu()
{
// 設定字為red(0x04),並且清除畫面
gST -> ConOut -> SetAttribute(gST->ConOut,0x4);
gST -> ConOut -> ClearScreen(gST->ConOut);
Print(L"*******************************\n");
Print(L"| Boot Menu |\n");
Print(L"|-----------------------------|\n");
Print(L"| |\n");
Print(L"| |\n");
Print(L"| |\n");
Print(L"| |\n");
Print(L"*******************************\n");
while(1)
{
Status = gST->ConIn->ReadKeyStroke(gST->ConIn, &key);
// 暫且設定僅兩種Kernel: Kernel1.bin及Kernel2.bin
if(key.UnicodeChar == L'1' || key.UnicodeChar == L'2' )
{
Kernel(key.UnicodeChar);
break;
}
}
}
static void Kernel(CHAR16 keyChar)
{
EFI_HANDLE ImageHandle;
EFI_STATUS Status = EFI_SUCCESS;
EFI_FILE_PROTOCOL *bin;
if (keyChar=='1')
{
Print(L"Enter 1 kernel...\n");
Status = GetFileHandle(ImageHandle, L"\\Kernel1.bin",&bin);
}
if (keyChar=='2')
{
Print(L"Enter 2 kernel...\n");
Status = GetFileHandle(ImageHandle, L"\\Kernel2.bin",&bin);
}
EFI_PHYSICAL_ADDRESS binAddr;
Status = ReadFile(bin, &binAddr);
asm("jmp %0"::"m"(binAddr)); // %0是第1個位址、%1是第2個位址,以此類推
}
Day20至今本篇Day23完成ASM開發Kernel.bin與BootMenu.c以asm()連結之。距離完成開機畫面僅剩一哩路,謝謝一路相伴,我們明天見!