From eea601f346029e5bb219448fd6eebffac6afdcd6 Mon Sep 17 00:00:00 2001 From: tkchia Date: Wed, 15 Nov 2023 07:26:59 +0800 Subject: [PATCH] [metal] Some minor fixes and tweaks (#933) * [metal] Ensure DF is clear when calling C from exception handler * [metal] Mark some internal routines and declarations as `@internal` * [metal] Fix crash under UEFI when command line string is NULL * [metal] Fix argc & argv[] setting, & VM page freeing, for UEFI Part of the memory occupied by the argv[] contents was erroneously used for page tables & then later erroneously freed. The symptom was that argv[0] would show up as an empty string (""). --- libc/intrin/interrupts.S | 1 + libc/intrin/mman.greg.c | 12 ++++++++++++ libc/irq/acpi.internal.h | 23 ++++++++++++++--------- libc/runtime/efimain.greg.c | 11 +++++++---- libc/vga/tty-graph.c | 1 + libc/vga/tty-graph.inc | 1 + libc/vga/tty.greg.c | 18 +++++++++++++++--- libc/vga/vga.internal.h | 29 +++++++++++++++++++++++++---- 8 files changed, 76 insertions(+), 20 deletions(-) diff --git a/libc/intrin/interrupts.S b/libc/intrin/interrupts.S index fe8cf5f9c..99e6cc1b4 100644 --- a/libc/intrin/interrupts.S +++ b/libc/intrin/interrupts.S @@ -92,6 +92,7 @@ __excep0_isr: mov %eax,%ss mov %eax,%ds mov %eax,%es + cld # make sure DF is reset, for C code ezlea .excep_msg,di # stack should be 16-byte aligned now xor %eax,%eax # kprintf is variadic, remember to # pass no. of vector regs. used (= 0) diff --git a/libc/intrin/mman.greg.c b/libc/intrin/mman.greg.c index 3998d0c1c..064804134 100644 --- a/libc/intrin/mman.greg.c +++ b/libc/intrin/mman.greg.c @@ -59,6 +59,7 @@ struct ReclaimedPage { }; /** + * @internal * Allocates new page of physical memory. */ texthead uint64_t __new_page(struct mman *mm) { @@ -85,6 +86,7 @@ texthead uint64_t __new_page(struct mman *mm) { } /** + * @internal * Returns pointer to page table entry for page at virtual address. * Additional page tables are allocated if needed as a side-effect. */ @@ -106,6 +108,7 @@ textreal uint64_t *__get_virtual(struct mman *mm, uint64_t *t, int64_t vaddr, } /** + * @internal * Sorts, rounds, and filters BIOS memory map. */ static textreal void __normalize_e820(struct mman *mm, uint64_t top) { @@ -139,6 +142,7 @@ static textreal void __normalize_e820(struct mman *mm, uint64_t top) { } /** + * @internal * Identity maps an area of physical memory to its negative address. */ textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t, @@ -157,6 +161,7 @@ textreal uint64_t *__invert_memory_area(struct mman *mm, uint64_t *pml4t, } /** + * @internal * Increments the reference count for a page of physical memory. */ void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) { @@ -172,6 +177,7 @@ void __ref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) { } /** + * @internal * Increments the reference counts for an area of physical memory. */ void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps, uint64_t size) { @@ -183,6 +189,7 @@ void __ref_pages(struct mman *mm, uint64_t *pml4t, uint64_t ps, uint64_t size) { } /** + * @internal * Reclaims a page of physical memory for later use. */ static void __reclaim_page(struct mman *mm, uint64_t p) { @@ -193,6 +200,7 @@ static void __reclaim_page(struct mman *mm, uint64_t p) { } /** + * @internal * Decrements the reference count for a page of physical memory. Frees the * page if there are no virtual addresses (excluding the negative space) * referring to it. @@ -211,6 +219,7 @@ void __unref_page(struct mman *mm, uint64_t *pml4t, uint64_t p) { } /** + * @internal * Identity maps all usable physical memory to its negative address. */ static textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) { @@ -224,6 +233,7 @@ static textreal void __invert_memory(struct mman *mm, uint64_t *pml4t) { } /** + * @internal * Exports information about the offset of a field within a structure type, * so that assembly language routines can use it. This macro can be invoked * from inside a function whose code is known to be emitted. @@ -284,6 +294,7 @@ static textreal uint64_t __map_phdr(struct mman *mm, uint64_t *pml4t, } /** + * @internal * Maps APE-defined ELF program headers into memory and clears BSS. */ textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b, @@ -315,6 +326,7 @@ textreal void __map_phdrs(struct mman *mm, uint64_t *pml4t, uint64_t b, } /** + * @internal * Reclaims memory pages which were used at boot time but which can now be * made available for the application. */ diff --git a/libc/irq/acpi.internal.h b/libc/irq/acpi.internal.h index d0e594a1b..61b53bfc6 100644 --- a/libc/irq/acpi.internal.h +++ b/libc/irq/acpi.internal.h @@ -5,6 +5,17 @@ #include "libc/log/color.internal.h" /** + * @internal + * @fileoverview Declarations for bare metal code to interact with ACPI + * + * @see UEFI Forum, Inc. Advanced Configuration and Power Interface (ACPI) + * Specification, Version 6.5, 2022. https://uefi.org/specifications + * @see Intel Corporation. ACPI Component Architecture: User Guide and + * Programmer Reference, Revision 6.2, 2017. https://acpica.org + */ + +/** + * @internal * AcpiStatus values. */ #define kAcpiOk 0x0000 @@ -13,11 +24,13 @@ #define kAcpiExBadChecksum 0x2003 /** + * @internal * Flags for AcpiTableMadt::Flags. */ #define kAcpiMadtPcAtCompat 0x0001 /** + * @internal * Flags for AcpiTableFadt::BootFlags. */ #define kAcpiFadtLegacyDevices 0x0001 @@ -28,6 +41,7 @@ #define kAcpiFadtNoCmosRtc 0x0020 /** + * @internal * Values for AcpiSubtableHeader::Type under an AcpiTableMadt. */ #define kAcpiMadtLocalApic 0 @@ -36,15 +50,6 @@ #if !(__ASSEMBLER__ + __LINKER__ + 0) -/** - * @fileoverview Declarations for bare metal code to interact with ACPI - * - * @see UEFI Forum, Inc. Advanced Configuration and Power Interface (ACPI) - * Specification, Version 6.5, 2022. https://uefi.org/specifications - * @see Intel Corporation. ACPI Component Architecture: User Guide and - * Programmer Reference, Revision 6.2, 2017. https://acpica.org - */ - COSMOPOLITAN_C_START_ /** diff --git a/libc/runtime/efimain.greg.c b/libc/runtime/efimain.greg.c index cee4fcff0..e71704e2e 100644 --- a/libc/runtime/efimain.greg.c +++ b/libc/runtime/efimain.greg.c @@ -173,6 +173,7 @@ __msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, uint64_t Address; uintptr_t Args, MapKey, DescSize; uint64_t *pd, *pml4t, *pdt1, *pdt2, *pdpt1, *pdpt2; + const char16_t *CmdLine; extern char os asm("__hostos"); os = _HOSTMETAL; @@ -194,7 +195,7 @@ __msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, Address = 0x79000; SystemTable->BootServices->AllocatePages( AllocateAddress, EfiRuntimeServicesData, - (0x7e000 - 0x79000 + sizeof(struct EfiArgs) + 4095) / 4096, &Address); + (0x7f000 - 0x79000 + sizeof(struct EfiArgs) + 4095) / 4096, &Address); Address = IMAGE_BASE_PHYSICAL; SystemTable->BootServices->AllocatePages( AllocateAddress, EfiRuntimeServicesData, @@ -202,7 +203,7 @@ __msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, mm = __get_mm_phy(); SystemTable->BootServices->SetMem(mm, sizeof(*mm), 0); SystemTable->BootServices->SetMem( - (void *)0x79000, 0x7e000 - 0x79000 + sizeof(struct EfiArgs), 0); + (void *)0x79000, 0x7f000 - 0x79000 + sizeof(struct EfiArgs), 0); SystemTable->BootServices->CopyMem((void *)IMAGE_BASE_PHYSICAL, __executable_start, _end - __executable_start); @@ -210,10 +211,12 @@ __msabi EFI_STATUS EfiMain(EFI_HANDLE ImageHandle, /* * Converts UEFI shell arguments to argv. */ - ArgBlock = (struct EfiArgs *)0x7e000; + ArgBlock = (struct EfiArgs *)0x7f000; SystemTable->BootServices->HandleProtocol(ImageHandle, &kEfiLoadedImageProtocol, &ImgInfo); - Args = GetDosArgv(ImgInfo->LoadOptions, ArgBlock->ArgBlock, + CmdLine = (const char16_t *)ImgInfo->LoadOptions; + if (!CmdLine || !CmdLine[0]) CmdLine = u"BOOTX64.EFI"; + Args = GetDosArgv(CmdLine, ArgBlock->ArgBlock, sizeof(ArgBlock->ArgBlock), ArgBlock->Args, ARRAYLEN(ArgBlock->Args)); diff --git a/libc/vga/tty-graph.c b/libc/vga/tty-graph.c index 1c751ea1c..aea360ca0 100644 --- a/libc/vga/tty-graph.c +++ b/libc/vga/tty-graph.c @@ -30,6 +30,7 @@ #include "libc/vga/vga.internal.h" /** + * @internal * @fileoverview Instantiation of routines for normal console output in * graphical video modes. * diff --git a/libc/vga/tty-graph.inc b/libc/vga/tty-graph.inc index e5688d832..2aa6ef7f4 100644 --- a/libc/vga/tty-graph.inc +++ b/libc/vga/tty-graph.inc @@ -31,6 +31,7 @@ #include "libc/vga/vga.internal.h" /** + * @internal * @fileoverview Template for routines to support output in graphical video * modes for bare metal VGA. * diff --git a/libc/vga/tty.greg.c b/libc/vga/tty.greg.c index daa9d9a30..4f411872a 100644 --- a/libc/vga/tty.greg.c +++ b/libc/vga/tty.greg.c @@ -33,6 +33,7 @@ #ifdef __x86_64__ /** + * @internal * @fileoverview ECMA-48 / VT100 video terminal implementation for bare * metal VGA. * @@ -325,6 +326,7 @@ static void TtySetCodepage(struct Tty *tty, char id) { } /** + * @internal * Map the given direct color value to one of the 16 basic foreground colors * or one of the 16 background colors. * @@ -344,6 +346,7 @@ static uint8_t TtyGetTextColor(TtyCanvasColor color) { } /** + * @internal * Map the currently active foreground & background colors & terminal * configuration to a VGA text character attribute byte. * @@ -794,12 +797,18 @@ static void TtyCsiN(struct Tty *tty) { } } -/** Create a direct color pixel value. */ +/** + * @internal + * Create a direct color pixel value. + */ static TtyCanvasColor TtyMapTrueColor(uint8_t r, uint8_t g, uint8_t b) { return (TtyCanvasColor){.bgr.r = r, .bgr.g = g, .bgr.b = b, .bgr.x = 0xff}; } -/** Map the given 256-color code to a direct color. */ +/** + * @internal + * Map the given 256-color code to a direct color. + */ static TtyCanvasColor TtyMapXtermColor(uint8_t color) { uint8_t r, g, b; if (color < 8) { @@ -822,7 +831,10 @@ static TtyCanvasColor TtyMapXtermColor(uint8_t color) { return TtyMapTrueColor(r, g, b); } -/** Map the given ECMA-48 / VT100 SGR color code to a direct color. */ +/** + * @internal + * Map the given ECMA-48 / VT100 SGR color code to a direct color. + */ static TtyCanvasColor TtyMapEcma48Color(uint8_t color) { return TtyMapXtermColor(color % 16); } diff --git a/libc/vga/vga.internal.h b/libc/vga/vga.internal.h index 24098657a..f08a5ce66 100644 --- a/libc/vga/vga.internal.h +++ b/libc/vga/vga.internal.h @@ -2,11 +2,20 @@ #define COSMOPOLITAN_LIBC_VGA_VGA_INTERNAL_H_ #include "libc/runtime/mman.internal.h" -/** Preferred width of the video screen, in character units. */ +/** + * @internal + * Preferred width of the video screen, in character units. + */ #define VGA_PREFER_TTY_HEIGHT 30 -/** Preferred width of the video screen, in character units. */ +/** + * @internal + * Preferred width of the video screen, in character units. + */ #define VGA_PREFER_TTY_WIDTH 80 -/** Assumed height of each character in pixels, in graphics modes. */ +/** + * @internal + * Assumed height of each character in pixels, in graphics modes. + */ #define VGA_ASSUME_CHAR_HEIGHT_PX 16 /** Assumed width of each character in pixels, in graphics modes. */ #define VGA_ASSUME_CHAR_WIDTH_PX 8 @@ -18,6 +27,7 @@ */ /** + * @internal * If VGA_USE_WCS is defined, the tty code can maintain an array of the * Unicode characters "underlying" the 8-bit (or 9-bit) characters that are * actually displayed on the text screen. This Unicode character @@ -33,6 +43,7 @@ */ #undef VGA_USE_WCS /** + * @internal * The VGA hardware can be configured — via the IBM BIOS, or via port I/O — * to either support blinking characters, or support the use of bright * background colors, but not both. There is a hardware setting that @@ -67,6 +78,7 @@ */ #undef VGA_USE_BLINK /** + * @internal * If VGA_PERSNICKETY_STATUS is defined, then when deciding how to return * status response codes (e.g. "\e[0n"), the tty code will pay attention to * the terminal's termios mode (TODO). If undefined, the tty code will @@ -75,7 +87,10 @@ */ #undef VGA_PERSNICKETY_STATUS -/* Flags which are passed to _StartTty(). */ +/** + * @internal + * Flags which are passed to _StartTty(). + */ #define kTtyAllocWcs \ 0x01 /* allocate Unicode character array \ (if VGA_USE_WCS also defined) */ @@ -85,6 +100,7 @@ to show system messages */ /** + * @internal * Flags for Tty::pr. These govern properties of individual character cells. */ #define kTtyFg 0x0001 @@ -102,6 +118,7 @@ #define kTtyConceal 0x1000 /** + * @internal * Flags for Tty::conf. These govern the current state of the teletypewriter * as a whole. */ @@ -153,6 +170,10 @@ typedef union { typedef TtyBgrxColor TtyCanvasColor; struct Tty; +/** + * @internal + * Video console object type. + */ struct Tty { /** * Cursor position. (y, x) = (0, 0) means the cursor is on the top left