From 9fe2f551139d08c23d17bc94e1cde45076de4794 Mon Sep 17 00:00:00 2001 From: tkchia Date: Wed, 9 Nov 2022 18:13:52 +0000 Subject: [PATCH] [metal] Get examples/vga2.c serial output working for UEFI boot --- examples/vga2.c | 1 + libc/intrin/mman.greg.c | 5 ++- libc/runtime/efimain.greg.c | 86 +++++++++++++++++++++++++++---------- 3 files changed, 68 insertions(+), 24 deletions(-) diff --git a/examples/vga2.c b/examples/vga2.c index 0343cf211..c5e1de2b6 100644 --- a/examples/vga2.c +++ b/examples/vga2.c @@ -24,6 +24,7 @@ STATIC_YOINK("vga_console"); STATIC_YOINK("_idt"); +STATIC_YOINK("EfiMain"); int main(int argc, char *argv[]) { volatile int x = 1; diff --git a/libc/intrin/mman.greg.c b/libc/intrin/mman.greg.c index 024bd508c..286a1c2d9 100644 --- a/libc/intrin/mman.greg.c +++ b/libc/intrin/mman.greg.c @@ -44,6 +44,7 @@ #include "libc/runtime/runtime.h" #define INVERT(x) (BANE + PHYSICAL(x)) +#define NOPAGE ((uint64_t)-1) struct ReclaimedPage { uint64_t next; @@ -54,7 +55,7 @@ struct ReclaimedPage { */ noasan texthead uint64_t __new_page(struct mman *mm) { uint64_t p = mm->frp; - if (p) { + if (p != NOPAGE) { uint64_t q; struct ReclaimedPage *rp = (struct ReclaimedPage *)(BANE + p); _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->pdpi = 0; mm->e820n = n; - mm->frp = 0; + mm->frp = NOPAGE; } /** diff --git a/libc/runtime/efimain.greg.c b/libc/runtime/efimain.greg.c index 926deaa52..e3b12798e 100644 --- a/libc/runtime/efimain.greg.c +++ b/libc/runtime/efimain.greg.c @@ -62,27 +62,36 @@ static const EFI_GUID kEfiLoadedImageProtocol = LOADED_IMAGE_PROTOCOL; * * @see libc/dce.h */ -__msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, - EFI_SYSTEM_TABLE *SystemTable) { - int type, x87cw; +__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) { + int type, x87cw = 0x037f; struct mman *mm; uint32_t DescVersion; uintptr_t i, j, MapSize; struct EfiArgs *ArgBlock; EFI_LOADED_IMAGE *ImgInfo; - EFI_MEMORY_DESCRIPTOR *Map; + EFI_MEMORY_DESCRIPTOR *Map, *Desc; + uint64_t NewBase = 1024 * 1024; uintptr_t Args, MapKey, DescSize; 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. */ SystemTable->BootServices->AllocatePages( 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->CopyMem((void *)(1024 * 1024), _base, _end - _base); @@ -104,16 +113,19 @@ __msabi noasan EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, MapSize = 0; SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, &DescVersion); - SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, Map); + SystemTable->BootServices->AllocatePool(EfiLoaderData, MapSize, &Map); + MapSize *= 2; SystemTable->BootServices->GetMemoryMap(&MapSize, Map, &MapKey, &DescSize, &DescVersion); - asm("xor\t%0,%0" : "=r"(mm)); /* gcc assumes null isn't mapped */ - for (j = i = 0; i < MapSize / sizeof(EFI_MEMORY_DESCRIPTOR); ++i) { - if (Map[i].Type != EfiConventionalMemory) continue; - mm->e820[j].addr = Map[i].PhysicalStart; - mm->e820[j].size = Map[i].NumberOfPages * 4096; - mm->e820[j].type = kMemoryUsable; - ++j; + mm = (struct mman *)0x0500; + for (j = i = 0, Desc = Map; i < MapSize / DescSize; ++i) { + if (Desc->Type == EfiConventionalMemory) { + mm->e820[j].addr = Desc->PhysicalStart; + mm->e820[j].size = Desc->NumberOfPages * 4096; + mm->e820[j].type = kMemoryUsable; + ++j; + } + Desc = (EFI_MEMORY_DESCRIPTOR *)((char *)Desc + DescSize); } 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; pml4t[0] = (intptr_t)pdpt1 + 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? */ 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. */ 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_memsz\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%%eax,%%eax\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%%edi,%%edi\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%%r15d,%%r15d\n\t" ".weak\t_start\n\t" - "jmp\t_start" + "push\t%5\n\t" + "push\t$_start\n\t" + "lretq" : /* no outputs */ : "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"); unreachable;