[metal] Get examples/vga2.c serial output working for UEFI boot

This commit is contained in:
tkchia 2022-11-09 18:13:52 +00:00
parent 36b06ab73e
commit 9fe2f55113
3 changed files with 68 additions and 24 deletions

View file

@ -24,6 +24,7 @@
STATIC_YOINK("vga_console"); STATIC_YOINK("vga_console");
STATIC_YOINK("_idt"); STATIC_YOINK("_idt");
STATIC_YOINK("EfiMain");
int main(int argc, char *argv[]) { int main(int argc, char *argv[]) {
volatile int x = 1; volatile int x = 1;

View file

@ -44,6 +44,7 @@
#include "libc/runtime/runtime.h" #include "libc/runtime/runtime.h"
#define INVERT(x) (BANE + PHYSICAL(x)) #define INVERT(x) (BANE + PHYSICAL(x))
#define NOPAGE ((uint64_t)-1)
struct ReclaimedPage { struct ReclaimedPage {
uint64_t next; uint64_t next;
@ -54,7 +55,7 @@ struct ReclaimedPage {
*/ */
noasan texthead uint64_t __new_page(struct mman *mm) { noasan texthead uint64_t __new_page(struct mman *mm) {
uint64_t p = mm->frp; uint64_t p = mm->frp;
if (p) { if (p != NOPAGE) {
uint64_t q; uint64_t q;
struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p); struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p);
_unassert(p == (p & PAGE_TA)); _unassert(p == (p & PAGE_TA));
@ -126,7 +127,7 @@ static noasan textreal void __normalize_e820(struct mman *mm, uint64_t top) {
mm->pdp = MAX(top, mm->e820[0].addr); mm->pdp = MAX(top, mm->e820[0].addr);
mm->pdpi = 0; mm->pdpi = 0;
mm->e820n = n; mm->e820n = n;
mm->frp = 0; mm->frp = NOPAGE;
} }
/** /**

View file

@ -62,27 +62,36 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL;
* *
* @see libc/dce.h * @see libc/dce.h
*/ */
__msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, __msabi noasan __attribute__((__naked__))
EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) {
asm volatile("mov\t$0f,%esp\n\t"
"and\t$-16,%esp\n\t"
"jmp\t_DoEfiMain\n\t"
".bss\n\t"
".space\t8192\n"
"0:\n\t"
".previous");
}
__msabi noasan EFI_STATUS _DoEfiMain(EFI_HANDLE ImageHandle,
EFI_SYSTEM_TABLE *SystemTable) { EFI_SYSTEM_TABLE *SystemTable) {
int type, x87cw; int type, x87cw = 0x037f;
struct mman *mm; struct mman *mm;
uint32_t DescVersion; uint32_t DescVersion;
uintptr_t i, j, MapSize; uintptr_t i, j, MapSize;
struct EfiArgs *ArgBlock; struct EfiArgs *ArgBlock;
EFI_LOADED_IMAGE *ImgInfo; EFI_LOADED_IMAGE *ImgInfo;
EFI_MEMORY_DESCRIPTOR *Map; EFI_MEMORY_DESCRIPTOR *Map, *Desc;
uint64_t NewBase = 1024 * 1024;
uintptr_t Args, MapKey, DescSize; uintptr_t Args, MapKey, DescSize;
uint64_t p, pe, cr4, *m, *pd, *sp, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2; uint64_t p, pe, cr4, *m, *pd, *sp, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2;
extern char __os asm("__hostos");
__os = _HOSTMETAL;
/* /*
* Allocates and clears PC-compatible memory and copies image. * Allocates and clears PC-compatible memory and copies image.
*/ */
SystemTable->BootServices->AllocatePages( SystemTable->BootServices->AllocatePages(
AllocateAddress, EfiConventionalMemory, AllocateAddress, EfiConventionalMemory,
MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, 0); MAX(2 * 1024 * 1024, 1024 * 1024 + (_end - _base)) / 4096, &NewBase);
SystemTable->BootServices->SetMem(0, 0x80000, 0); SystemTable->BootServices->SetMem(0, 0x80000, 0);
SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base, SystemTable->BootServices->CopyMem((void *)(1024 * 1024), _base,
_end - _base); _end - _base);
@ -104,17 +113,20 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
MapSize = 0; MapSize = 0;
SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize,
&DescVersion); &DescVersion);
SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, Map); SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, &Map);
MapSize *= 2;
SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize,
&DescVersion); &DescVersion);
asm("xor\t%0,%0" : "=r"(mm)); /* gcc assumes null isn't mapped */ mm = (struct mman *)0x0500;
for (j = i = 0; i < MapSize / sizeof(EFI_MEMORY_DESCRIPTOR); ++i) { for (j = i = 0, Desc = Map; i < MapSize / DescSize; ++i) {
if (Map[i].Type != EfiConventionalMemory) continue; if (Desc->Type == EfiConventionalMemory) {
mm->e820[j].addr = Map[i].PhysicalStart; mm->e820[j].addr = Desc->PhysicalStart;
mm->e820[j].size = Map[i].NumberOfPages * 4096; mm->e820[j].size = Desc->NumberOfPages * 4096;
mm->e820[j].type = kMemoryUsable; mm->e820[j].type = kMemoryUsable;
++j; ++j;
} }
Desc = (EFI_MEMORY_DESCRIPTOR *)((char *)Desc + DescSize);
}
SystemTable->BootServices->FreePool(Map); SystemTable->BootServices->FreePool(Map);
/* /*
@ -135,19 +147,46 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW; pdpt2[0] = (intptr_t)pdt2 + PAGE_V + PAGE_RW;
pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW; pml4t[0] = (intptr_t)pdpt1 + PAGE_V + PAGE_RW;
pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW; pml4t[256] = (intptr_t)pdpt2 + PAGE_V + PAGE_RW;
__map_phdrs(mm, pml4t, 1024 * 1024, 1024 * 1024 + (_end - _base));
__reclaim_boot_pages(mm, 0x79000, 0x7f000);
/* /*
* Asks UEFI to handover control? * Asks UEFI to handover control?
*/ */
SystemTable->BootServices->ExitBootServices(ImageHandle, MapKey); SystemTable->BootServices->ExitBootServices(ImageHandle, MapKey);
/*
* Switches to copied image.
*/
asm volatile("cli\n\t"
"add\t%1,%%rsp\n\t"
"lea\t0f(%1),%0\n\t"
"jmp\t*%0\n"
"0:\n\t"
"mov\t%2,%%cr3\n\t"
"add\t%3,%%rsp\n\t"
"lea\t1f(%1),%0\n\t"
"add\t%3,%0\n\t"
"jmp\t*%0\n"
"1:"
: "=&r"(p)
: "r"(1024 * 1024 - (uint64_t)_base), "r"(pml4t), "r"(BANE));
/*
* Sets up virtual memory mapping.
*/
__map_phdrs(mm, pml4t, 1024 * 1024, 1024 * 1024 + (_end - _base));
__reclaim_boot_pages(mm, 0x79000, 0x7f000);
/* /*
* Launches program. * Launches program.
*/ */
asm volatile("fldcw\t%3\n\t" asm volatile("fldcw\t%3\n\t"
"mov\t%4,%%cr3\n\t" ".weak\t_gdtr\n\t"
"lgdt\t_gdtr\n\t"
"mov\t%w6,%%ds\n\t"
"mov\t%w6,%%ss\n\t"
"mov\t%w6,%%es\n\t"
"mov\t%w6,%%fs\n\t"
"mov\t%w6,%%gs\n\t"
".weak\tape_stack_vaddr\n\t" ".weak\tape_stack_vaddr\n\t"
".weak\tape_stack_memsz\n\t" ".weak\tape_stack_memsz\n\t"
"movabs\t$ape_stack_vaddr,%%rsp\n\t" "movabs\t$ape_stack_vaddr,%%rsp\n\t"
@ -164,7 +203,7 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
"xor\t%%edi,%%edi\n\t" "xor\t%%edi,%%edi\n\t"
"xor\t%%eax,%%eax\n\t" "xor\t%%eax,%%eax\n\t"
"xor\t%%ebx,%%ebx\n\t" "xor\t%%ebx,%%ebx\n\t"
"xor\t%%ecx,%%ecx\n\t" "mov\t%4,%%ecx\n\t"
"xor\t%%edx,%%edx\n\t" "xor\t%%edx,%%edx\n\t"
"xor\t%%edi,%%edi\n\t" "xor\t%%edi,%%edi\n\t"
"xor\t%%esi,%%esi\n\t" "xor\t%%esi,%%esi\n\t"
@ -178,10 +217,13 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle,
"xor\t%%r14d,%%r14d\n\t" "xor\t%%r14d,%%r14d\n\t"
"xor\t%%r15d,%%r15d\n\t" "xor\t%%r15d,%%r15d\n\t"
".weak\t_start\n\t" ".weak\t_start\n\t"
"jmp\t_start" "push\t%5\n\t"
"push\t$_start\n\t"
"lretq"
: /* no outputs */ : /* no outputs */
: "a"(Args), "S"(ArgBlock->Args), "c"((Args + 1) * 8), : "a"(Args), "S"(ArgBlock->Args), "c"((Args + 1) * 8),
"m"(x87cw), "r"(pml4t) "m"(x87cw), "i"(_HOSTMETAL), "i"(GDT_LONG_CODE),
"r"(GDT_LONG_DATA)
: "memory"); : "memory");
unreachable; unreachable;