From 165ed28cd312cc12af98cf51032c39acc4193bd6 Mon Sep 17 00:00:00 2001 From: "Justin C. Miller" Date: Sat, 31 Mar 2018 17:32:10 -0700 Subject: [PATCH] Reduce dependency on efi library functions --- Makefile | 3 +- src/boot/console.c | 230 +++++++++++++++++++++++++++++++++++++-------- src/boot/console.h | 4 +- src/boot/loader.c | 29 +++--- src/boot/loader.h | 7 +- src/boot/main.c | 99 +++++++++++++++---- src/boot/memory.c | 26 ++--- src/boot/memory.h | 4 +- src/boot/utility.c | 48 +++++++++- src/boot/utility.h | 34 +++---- 10 files changed, 375 insertions(+), 109 deletions(-) diff --git a/Makefile b/Makefile index 5898ed1..6cbe67b 100644 --- a/Makefile +++ b/Makefile @@ -59,9 +59,10 @@ CFLAGS += -DGIT_VERSION="L\"$(VERSION)\"" CFLAGS += -DKERNEL_FILENAME="L\"$(KERNEL_FILENAME)\"" CFLAGS += -DEFI_DEBUG=0 -DEFI_DEBUG_CLEAR_MEMORY=0 CFLAGS += -DGNU_EFI_USE_MS_ABI -DHAVE_USE_MS_ABI -#CFLAGS += -DEFI_FUNCTION_WRAPPER BOOT_CFLAGS := -I src/boot $(CFLAGS) +#BOOT_CFLAGS += -DEFI_FUNCTION_WRAPPER + ifdef MAX_HRES BOOT_CFLAGS += -DMAX_HRES=$(MAX_HRES) endif diff --git a/src/boot/console.c b/src/boot/console.c index 0c6cfe0..72bdae5 100644 --- a/src/boot/console.c +++ b/src/boot/console.c @@ -1,24 +1,30 @@ #include #include +#include #include #include "console.h" #include "utility.h" -UINTN ROWS = 0; -UINTN COLS = 0; +size_t ROWS = 0; +size_t COLS = 0; + +static EFI_SIMPLE_TEXT_OUT_PROTOCOL *con_out = 0; + +const CHAR16 digits[] = {u'0', u'1', u'2', u'3', u'4', u'5', u'6', u'7', u'8', u'9', u'a', u'b', u'c', u'd', u'e', u'f'}; EFI_STATUS -con_initialize(const CHAR16 *version) +con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version) { EFI_STATUS status; - Print(L"Setting console display mode...\n"); + EFI_BOOT_SERVICES *bootsvc = system_table->BootServices; + con_out = system_table->ConOut; EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto; EFI_GUID gfx_out_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; - status = ST->BootServices->LocateProtocol(&gfx_out_guid, NULL, (void **)&gfx_out_proto); + status = bootsvc->LocateProtocol(&gfx_out_guid, NULL, (void **)&gfx_out_proto); CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx"); const uint32_t modes = gfx_out_proto->Mode->MaxMode; @@ -47,64 +53,210 @@ con_initialize(const CHAR16 *version) status = gfx_out_proto->SetMode(gfx_out_proto, best); CHECK_EFI_STATUS_OR_RETURN(status, "SetMode %d/%d", best, modes); - status = ST->ConOut->QueryMode(ST->ConOut, ST->ConOut->Mode->Mode, &COLS, &ROWS); + status = con_out->QueryMode(con_out, con_out->Mode->Mode, &COLS, &ROWS); CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); - status = ST->ConOut->ClearScreen(ST->ConOut); + status = con_out->ClearScreen(con_out); CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen"); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTCYAN); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"Popcorn loader "); + con_out->SetAttribute(con_out, EFI_LIGHTCYAN); + con_out->OutputString(con_out, (CHAR16 *)L"Popcorn loader "); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTMAGENTA); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)version); + con_out->SetAttribute(con_out, EFI_LIGHTMAGENTA); + con_out->OutputString(con_out, (CHAR16 *)version); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L" booting...\r\n\n"); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)L" booting...\r\n\n"); con_status_begin(L"Setting console display mode: "); - Print(L"\n %ux%u (%ux%u chars)", gfx_out_proto->Mode->Info->HorizontalResolution, - gfx_out_proto->Mode->Info->VerticalResolution, ROWS, COLS); + con_printf(L"\n %ux%u (%ux%u chars)", + gfx_out_proto->Mode->Info->HorizontalResolution, + gfx_out_proto->Mode->Info->VerticalResolution, + ROWS, COLS); + con_status_ok(); return status; } +size_t +con_wstrlen(const CHAR16 *s) +{ + size_t count = 0; + while (s && *s++) count++; + return count; +} + +size_t +con_print_hex(uint32_t n) +{ + CHAR16 buffer[9]; + CHAR16 *p = buffer; + for (int i = 7; i >= 0; --i) { + uint8_t nibble = (n & (0xf << (i*4))) >> (i*4); + *p++ = digits[nibble]; + } + *p = 0; + con_out->OutputString(con_out, buffer); + return 8; +} + +size_t +con_print_long_hex(uint64_t n) +{ + CHAR16 buffer[17]; + CHAR16 *p = buffer; + for (int i = 15; i >= 0; --i) { + uint8_t nibble = (n & (0xf << (i*4))) >> (i*4); + *p++ = digits[nibble]; + } + *p = 0; + con_out->OutputString(con_out, buffer); + return 16; +} + +size_t +con_print_dec(uint32_t n) +{ + CHAR16 buffer[11]; + CHAR16 *p = buffer + 10; + *p-- = 0; + do { + *p-- = digits[n % 10]; + n /= 10; + } while (n != 0); + + con_out->OutputString(con_out, ++p); + return 10 - (p - buffer); +} + +size_t +con_print_long_dec(uint64_t n) +{ + CHAR16 buffer[21]; + CHAR16 *p = buffer + 20; + *p-- = 0; + do { + *p-- = digits[n % 10]; + n /= 10; + } while (n != 0); + + con_out->OutputString(con_out, ++p); + return 20 - (p - buffer); +} + +size_t +con_printf(const CHAR16 *fmt, ...) +{ + CHAR16 buffer[256]; + const CHAR16 *r = fmt; + CHAR16 *w = buffer; + va_list args; + size_t count = 0; + + va_start(args, fmt); + + while (r && *r) { + if (*r != L'%') { + count++; + *w++ = *r++; + continue; + } + + *w = 0; + con_out->OutputString(con_out, buffer); + w = buffer; + + r++; // chomp the % + + switch (*r++) { + case L'%': + con_out->OutputString(con_out, L"%"); + count++; + break; + + case L'x': + count += con_print_hex(va_arg(args, uint32_t)); + break; + + case L'd': + case L'u': + count += con_print_dec(va_arg(args, uint32_t)); + break; + + case L's': + { + CHAR16 *s = va_arg(args, CHAR16*); + count += con_wstrlen(s); + con_out->OutputString(con_out, s); + } + break; + + case L'l': + switch (*r++) { + case L'x': + count += con_print_long_hex(va_arg(args, uint64_t)); + break; + + case L'd': + case L'u': + count += con_print_long_dec(va_arg(args, uint64_t)); + break; + + default: + break; + } + break; + + default: + break; + } + } + + *w = 0; + con_out->OutputString(con_out, buffer); + + va_end(args); +} + void con_status_begin(const CHAR16 *message) { - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)message); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)message); } void con_status_ok() { - UINTN row = ST->ConOut->Mode->CursorRow; - ST->ConOut->SetCursorPosition(ST->ConOut, 4, ++row); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"["); - ST->ConOut->SetAttribute(ST->ConOut, EFI_GREEN); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L" ok "); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"]\r"); - ST->ConOut->SetCursorPosition(ST->ConOut, 0, ++row + 1); + UINTN row = con_out->Mode->CursorRow; + con_out->SetCursorPosition(con_out, 4, ++row); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)L"["); + con_out->SetAttribute(con_out, EFI_GREEN); + con_out->OutputString(con_out, (CHAR16 *)L" ok "); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)L"]\r"); + + con_out->SetCursorPosition(con_out, 0, ++row + 1); } void con_status_fail(const CHAR16 *error) { - UINTN row = ST->ConOut->Mode->CursorRow; - ST->ConOut->SetCursorPosition(ST->ConOut, COLS - 8, row); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"["); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTRED); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"failed"); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)L"]\r"); - ST->ConOut->SetCursorPosition(ST->ConOut, 2, row + 1); - ST->ConOut->SetAttribute(ST->ConOut, EFI_RED); - ST->ConOut->OutputString(ST->ConOut, (CHAR16 *)error); - ST->ConOut->SetCursorPosition(ST->ConOut, 0, row + 2); - ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); + UINTN row = con_out->Mode->CursorRow; + con_out->SetCursorPosition(con_out, COLS - 8, row); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)L"["); + con_out->SetAttribute(con_out, EFI_LIGHTRED); + con_out->OutputString(con_out, (CHAR16 *)L"failed"); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); + con_out->OutputString(con_out, (CHAR16 *)L"]\r"); + + con_out->SetCursorPosition(con_out, 2, row + 1); + con_out->SetAttribute(con_out, EFI_RED); + con_out->OutputString(con_out, (CHAR16 *)error); + + con_out->SetCursorPosition(con_out, 0, row + 2); + con_out->SetAttribute(con_out, EFI_LIGHTGRAY); } diff --git a/src/boot/console.h b/src/boot/console.h index 83f7b8d..fdb3f05 100644 --- a/src/boot/console.h +++ b/src/boot/console.h @@ -1,7 +1,9 @@ #pragma once #include +#include -EFI_STATUS con_initialize(const CHAR16 *version); +EFI_STATUS con_initialize(EFI_SYSTEM_TABLE *system_table, const CHAR16 *version); void con_status_begin(const CHAR16 *message); void con_status_ok(); void con_status_fail(const CHAR16 *error); +size_t con_printf(const CHAR16 *fmt, ...); diff --git a/src/boot/loader.c b/src/boot/loader.c index a37712b..5975515 100644 --- a/src/boot/loader.c +++ b/src/boot/loader.c @@ -4,7 +4,12 @@ static CHAR16 kernel_name[] = KERNEL_FILENAME; EFI_STATUS -loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_data, uint64_t *data_length) +loader_load_kernel( + EFI_BOOT_SERVICES *bootsvc, + void **kernel_image, + uint64_t *kernel_length, + void **kernel_data, + uint64_t *data_length) { if (kernel_image == 0 || kernel_length == 0) CHECK_EFI_STATUS_OR_RETURN(EFI_INVALID_PARAMETER, "NULL kernel_image or length pointer"); @@ -17,13 +22,13 @@ loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_d EFI_HANDLE *handles = NULL; UINTN handleCount = 0; - status = ST->BootServices->LocateHandleBuffer(ByProtocol, &guid, NULL, &handleCount, &handles); + status = bootsvc->LocateHandleBuffer(ByProtocol, &guid, NULL, &handleCount, &handles); CHECK_EFI_STATUS_OR_RETURN(status, "LocateHandleBuffer"); for (unsigned i = 0; i < handleCount; ++i) { EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *fileSystem = NULL; - status = ST->BootServices->HandleProtocol(handles[i], &guid, (void **)&fileSystem); + status = bootsvc->HandleProtocol(handles[i], &guid, (void **)&fileSystem); CHECK_EFI_STATUS_OR_RETURN(status, "HandleProtocol"); EFI_FILE_PROTOCOL *root = NULL; @@ -39,7 +44,7 @@ loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_d EFI_GUID file_info_guid = EFI_FILE_INFO_ID; UINTN buffer_size = sizeof(EFI_FILE_INFO) + sizeof(kernel_name); - status = ST->BootServices->AllocatePool(EfiLoaderCode, buffer_size, &buffer); + status = bootsvc->AllocatePool(EfiLoaderCode, buffer_size, &buffer); CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel file info memory"); status = file->GetInfo(file, &file_info_guid, &buffer_size, buffer); @@ -47,20 +52,20 @@ loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_d buffer_size = ((EFI_FILE_INFO *)buffer)->FileSize; - status = ST->BootServices->FreePool(buffer); + status = bootsvc->FreePool(buffer); CHECK_EFI_STATUS_OR_RETURN(status, "Freeing kernel file info memory"); UINTN page_count = ((buffer_size - 1) / 0x1000) + 1; EFI_PHYSICAL_ADDRESS addr = KERNEL_PHYS_ADDRESS; EFI_MEMORY_TYPE mem_type = KERNEL_MEMTYPE; // Special value to tell the kernel it's here - status = ST->BootServices->AllocatePages(AllocateAddress, mem_type, page_count, &addr); + status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr); if (status == EFI_NOT_FOUND) { // couldn't get the address we wanted, try loading the kernel anywhere status = - ST->BootServices->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr); + bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr); } CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel pages"); - Print(L"\n Allocating %u pages at 0x%x", page_count, addr); + con_printf(L"\n Allocating %u pages at 0x%x", page_count, addr); buffer = (void *)addr; status = file->Read(file, &buffer_size, buffer); @@ -75,18 +80,18 @@ loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_d addr += page_count * 0x1000; // Get the next page after the kernel pages mem_type = KERNEL_DATA_MEMTYPE; // Special value for kernel data page_count = ((*data_length - 1) / 0x1000) + 1; - status = ST->BootServices->AllocatePages(AllocateAddress, mem_type, page_count, &addr); + status = bootsvc->AllocatePages(AllocateAddress, mem_type, page_count, &addr); if (status == EFI_NOT_FOUND) { // couldn't get the address we wanted, try loading anywhere status = - ST->BootServices->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr); + bootsvc->AllocatePages(AllocateAnyPages, mem_type, page_count, &addr); } CHECK_EFI_STATUS_OR_RETURN(status, "Allocating kernel data pages"); - Print(L"\n Allocating %u pages at 0x%x", page_count, addr); + con_printf(L"\n Allocating %u pages at 0x%x", page_count, addr); *data_length = page_count * 0x1000; *kernel_data = (void *)addr; - ST->BootServices->SetMem(*kernel_data, *data_length, 0); + bootsvc->SetMem(*kernel_data, *data_length, 0); return EFI_SUCCESS; } diff --git a/src/boot/loader.h b/src/boot/loader.h index 62089a7..79fa161 100644 --- a/src/boot/loader.h +++ b/src/boot/loader.h @@ -25,4 +25,9 @@ #define KERNEL_FILENAME L"kernel.bin" #endif -EFI_STATUS loader_load_kernel(void **kernel_image, uint64_t *kernel_length, void **kernel_data, uint64_t *data_length); +EFI_STATUS loader_load_kernel( + EFI_BOOT_SERVICES *bootsvc, + void **kernel_image, + uint64_t *kernel_length, + void **kernel_data, + uint64_t *data_length); diff --git a/src/boot/main.c b/src/boot/main.c index e30ff21..de4a2f8 100644 --- a/src/boot/main.c +++ b/src/boot/main.c @@ -48,26 +48,65 @@ struct popcorn_data { __attribute__((aligned(_Alignof(EFI_MEMORY_DESCRIPTOR)))); #pragma pack(pop) +int is_guid(EFI_GUID *a, EFI_GUID *b) +{ + uint64_t *ai = (uint64_t *)a; + uint64_t *bi = (uint64_t *)b; + return ai[0] == bi[0] && ai[1] == bi[1]; +} EFI_STATUS -efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) +efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) { EFI_STATUS status; + EFI_BOOT_SERVICES *bootsvc = system_table->BootServices; - - InitializeLib(ImageHandle, SystemTable); - - // When checking the console initialization error, - // use CHECK_EFI_STATUS_OR_RETURN because we can't - // be sure if the console was fully set up - status = con_initialize(GIT_VERSION); + // When checking the console initialization error, use + // CHECK_EFI_STATUS_OR_RETURN because we can't be sure + // if the console was fully set up + status = con_initialize(system_table, GIT_VERSION); CHECK_EFI_STATUS_OR_RETURN(status, "con_initialize"); + // From here on out, use CHECK_EFI_STATUS_OR_FAIL instead // because the console is now set up + EFI_GUID acpi1_guid = ACPI_TABLE_GUID; + EFI_GUID acpi2_guid = {0x8868e871,0xe4f1,0x11d3,{0xbc,0x22,0x00,0x80,0xc7,0x3c,0x88,0x81}}; + + con_status_begin(L"Reading configuration tables..."); + con_printf(L" %d found.\n", system_table->NumberOfTableEntries); + + for (size_t i=0; iNumberOfTableEntries; ++i) { + EFI_CONFIGURATION_TABLE *efi_table = &system_table->ConfigurationTable[i]; + + con_printf(L" %d. ", i); + + if (is_guid(&efi_table->VendorGuid, &acpi2_guid)) { + char *table = efi_table->VendorTable; + con_printf(L" ACPI 2.0 Table."); + } else if (is_guid(&efi_table->VendorGuid, &acpi1_guid)) { + char *table = efi_table->VendorTable; + con_printf(L" ACPI 1.0 Table."); + /* + } else if (is_guid(&efi_table->VendorGuid, &MpsTableGuid)) { + con_printf(L" MPS."); + } else if (is_guid(&efi_table->VendorGuid, &SMBIOSTableGuid)) { + con_printf(L" SMBIOS."); + } else if (is_guid(&efi_table->VendorGuid, &SalSystemTableGuid)) { + con_printf(L" SAL."); + */ + } else { + con_printf(L" Other."); + } + + con_printf(L"\n"); + } + con_status_ok(); + + con_status_begin(L"Computing needed data pages..."); UINTN data_length = 0; - status = memory_get_map_length(&data_length); + status = memory_get_map_length(bootsvc, &data_length); size_t header_size = sizeof(struct popcorn_data); const size_t header_align = alignof(struct popcorn_data); @@ -77,23 +116,47 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) data_length += header_size; con_status_ok(); + con_status_begin(L"Looking for devices...\n"); + EFI_GUID serial_guid = EFI_SERIAL_IO_PROTOCOL_GUID; + size_t num_serial = 0; + EFI_HANDLE *serial_handles; + status = bootsvc->LocateHandleBuffer(ByProtocol, &serial_guid, NULL, &num_serial, &serial_handles); + CHECK_EFI_STATUS_OR_FAIL(status); + con_printf(L" %d found.\n", num_serial); + + EFI_GUID ptt_guid = EFI_DEVICE_PATH_TO_TEXT_PROTOCOL_GUID; + EFI_DEVICE_PATH_TO_TEXT_PROTOCOL *ptt = NULL; + status = bootsvc->LocateProtocol(&ptt_guid, NULL, (void **)&ptt); + CHECK_EFI_STATUS_OR_FAIL(status); + + EFI_GUID path_guid = EFI_DEVICE_PATH_PROTOCOL_GUID; + for (size_t i=0; iHandleProtocol(handle, &path_guid, (void **)&path); + CHECK_EFI_STATUS_OR_FAIL(status); + con_printf(L" %s\n", ptt->ConvertDevicePathToText(path, 1, 0)); + } + + con_status_ok(); + con_status_begin(L"Loading kernel into memory..."); void *kernel_image = NULL, *kernel_data = NULL; uint64_t kernel_length = 0; - status = loader_load_kernel(&kernel_image, &kernel_length, &kernel_data, &data_length); + status = loader_load_kernel(bootsvc, &kernel_image, &kernel_length, &kernel_data, &data_length); CHECK_EFI_STATUS_OR_FAIL(status); - Print(L"\n %u bytes at 0x%x", kernel_length, kernel_image); - Print(L"\n %u data bytes at 0x%x", data_length, kernel_data); + con_printf(L"\n %u bytes at 0x%x", kernel_length, kernel_image); + con_printf(L"\n %u data bytes at 0x%x", data_length, kernel_data); struct kernel_header *version = (struct kernel_header *)kernel_image; if (version->magic != KERNEL_HEADER_MAGIC) { - Print(L"\n bad magic %x", version->magic); + con_printf(L"\n bad magic %x", version->magic); CHECK_EFI_STATUS_OR_FAIL(EFI_CRC_ERROR); } - Print(L"\n Kernel version %d.%d.%d %x%s", version->major, version->minor, version->patch, + con_printf(L"\n Kernel version %d.%d.%d %x%s", version->major, version->minor, version->patch, version->gitsha & 0x0fffffff, version->gitsha & 0xf0000000 ? "*" : ""); - Print(L"\n Entrypoint 0x%x", version->entrypoint); + con_printf(L"\n Entrypoint 0x%x", version->entrypoint); void (*kernel_main)() = version->entrypoint; @@ -107,7 +170,7 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) data_header->_reserverd = 0; data_header->flags = 0; data_header->memory_map = (EFI_MEMORY_DESCRIPTOR *)(data_header + 1); - data_header->runtime = SystemTable->RuntimeServices; + data_header->runtime = system_table->RuntimeServices; con_status_begin(L"Exiting boot services..."); @@ -115,10 +178,10 @@ efi_main(EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) map.entries = data_header->memory_map; map.length = (data_length - header_size); - status = memory_get_map(&map); + status = memory_get_map(bootsvc, &map); CHECK_EFI_STATUS_OR_FAIL(status); - status = ST->BootServices->ExitBootServices(ImageHandle, map.key); + status = bootsvc->ExitBootServices(image_handle, map.key); CHECK_EFI_STATUS_OR_ASSERT(status, 0); kernel_main(data_header); diff --git a/src/boot/memory.c b/src/boot/memory.c index 8cf7576..4fd1863 100644 --- a/src/boot/memory.c +++ b/src/boot/memory.c @@ -50,7 +50,7 @@ copy_desc(EFI_MEMORY_DESCRIPTOR *src, EFI_MEMORY_DESCRIPTOR *dst, size_t len) } EFI_STATUS -memory_get_map_length(size_t *size) +memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size) { if (size == NULL) return EFI_INVALID_PARAMETER; @@ -59,7 +59,7 @@ memory_get_map_length(size_t *size) size_t key, desc_size; uint32_t desc_version; *size = 0; - status = ST->BootServices->GetMemoryMap(size, 0, &key, &desc_size, &desc_version); + status = bootsvc->GetMemoryMap(size, 0, &key, &desc_size, &desc_version); if (status != EFI_BUFFER_TOO_SMALL) { CHECK_EFI_STATUS_OR_RETURN(status, "Failed to get memory map size"); } @@ -67,7 +67,7 @@ memory_get_map_length(size_t *size) } EFI_STATUS -memory_get_map(struct memory_map *map) +memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map) { EFI_STATUS status; @@ -75,13 +75,13 @@ memory_get_map(struct memory_map *map) return EFI_INVALID_PARAMETER; size_t needs_size = 0; - status = memory_get_map_length(&needs_size); + status = memory_get_map_length(bootsvc, &needs_size); if (EFI_ERROR(status)) return status; if (map->length < needs_size) return EFI_BUFFER_TOO_SMALL; - status = ST->BootServices->GetMemoryMap(&map->length, map->entries, &map->key, &map->size, &map->version); + status = bootsvc->GetMemoryMap(&map->length, map->entries, &map->key, &map->size, &map->version); CHECK_EFI_STATUS_OR_RETURN(status, "Failed to load memory map"); return EFI_SUCCESS; } @@ -94,19 +94,19 @@ memory_dump_map(struct memory_map *map) const size_t count = map->length / map->size; - Print(L"Memory map:\n"); - Print(L"\t Descriptor Count: %d (%d bytes)\n", count, map->length); - Print(L"\t Descriptor Size: %d bytes\n", map->size); - Print(L"\t Type offset: %d\n\n", offsetof(EFI_MEMORY_DESCRIPTOR, Type)); + con_printf(L"Memory map:\n"); + con_printf(L"\t Descriptor Count: %d (%d bytes)\n", count, map->length); + con_printf(L"\t Descriptor Size: %d bytes\n", map->size); + con_printf(L"\t Type offset: %d\n\n", offsetof(EFI_MEMORY_DESCRIPTOR, Type)); EFI_MEMORY_DESCRIPTOR *end = INCREMENT_DESC(map->entries, map->length); EFI_MEMORY_DESCRIPTOR *d = map->entries; while (d < end) { int runtime = (d->Attribute & EFI_MEMORY_RUNTIME) == EFI_MEMORY_RUNTIME; - Print(L"%23s%s ", memory_type_name(d->Type), runtime ? L"*" : L" "); - Print(L"%016llx ", d->PhysicalStart); - Print(L"%016llx ", d->VirtualStart); - Print(L"[%4d]\n", d->NumberOfPages); + con_printf(L"%s%s ", memory_type_name(d->Type), runtime ? L"*" : L" "); + con_printf(L"%lx ", d->PhysicalStart); + con_printf(L"%lx ", d->VirtualStart); + con_printf(L"[%4d]\n", d->NumberOfPages); d = INCREMENT_DESC(d, map->size); } diff --git a/src/boot/memory.h b/src/boot/memory.h index 625e832..0f2bf49 100644 --- a/src/boot/memory.h +++ b/src/boot/memory.h @@ -9,6 +9,6 @@ struct memory_map { EFI_MEMORY_DESCRIPTOR *entries; }; -EFI_STATUS memory_get_map_length(size_t *size); -EFI_STATUS memory_get_map(struct memory_map *map); +EFI_STATUS memory_get_map_length(EFI_BOOT_SERVICES *bootsvc, size_t *size); +EFI_STATUS memory_get_map(EFI_BOOT_SERVICES *bootsvc, struct memory_map *map); EFI_STATUS memory_dump_map(struct memory_map *map); diff --git a/src/boot/utility.c b/src/boot/utility.c index f35f029..9526eee 100644 --- a/src/boot/utility.c +++ b/src/boot/utility.c @@ -1,11 +1,49 @@ #include -struct ErrorCode { - EFI_STATUS code; - const CHAR16 *desc; -}; +struct { + EFI_STATUS code; + CHAR16 *desc; +} ErrorCodeTable[] = { + { EFI_SUCCESS, L"Success"}, + { EFI_LOAD_ERROR, L"Load Error"}, + { EFI_INVALID_PARAMETER, L"Invalid Parameter"}, + { EFI_UNSUPPORTED, L"Unsupported"}, + { EFI_BAD_BUFFER_SIZE, L"Bad Buffer Size"}, + { EFI_BUFFER_TOO_SMALL, L"Buffer Too Small"}, + { EFI_NOT_READY, L"Not Ready"}, + { EFI_DEVICE_ERROR, L"Device Error"}, + { EFI_WRITE_PROTECTED, L"Write Protected"}, + { EFI_OUT_OF_RESOURCES, L"Out of Resources"}, + { EFI_VOLUME_CORRUPTED, L"Volume Corrupt"}, + { EFI_VOLUME_FULL, L"Volume Full"}, + { EFI_NO_MEDIA, L"No Media"}, + { EFI_MEDIA_CHANGED, L"Media changed"}, + { EFI_NOT_FOUND, L"Not Found"}, + { EFI_ACCESS_DENIED, L"Access Denied"}, + { EFI_NO_RESPONSE, L"No Response"}, + { EFI_NO_MAPPING, L"No mapping"}, + { EFI_TIMEOUT, L"Time out"}, + { EFI_NOT_STARTED, L"Not started"}, + { EFI_ALREADY_STARTED, L"Already started"}, + { EFI_ABORTED, L"Aborted"}, + { EFI_ICMP_ERROR, L"ICMP Error"}, + { EFI_TFTP_ERROR, L"TFTP Error"}, + { EFI_PROTOCOL_ERROR, L"Protocol Error"}, + { EFI_INCOMPATIBLE_VERSION, L"Incompatible Version"}, + { EFI_SECURITY_VIOLATION, L"Security Policy Violation"}, + { EFI_CRC_ERROR, L"CRC Error"}, + { EFI_END_OF_MEDIA, L"End of Media"}, + { EFI_END_OF_FILE, L"End of File"}, + { EFI_INVALID_LANGUAGE, L"Invalid Languages"}, + { EFI_COMPROMISED_DATA, L"Compromised Data"}, -extern struct ErrorCode ErrorCodeTable[]; + // warnings + { EFI_WARN_UNKOWN_GLYPH, L"Warning Unknown Glyph"}, + { EFI_WARN_DELETE_FAILURE, L"Warning Delete Failure"}, + { EFI_WARN_WRITE_FAILURE, L"Warning Write Failure"}, + { EFI_WARN_BUFFER_TOO_SMALL, L"Warning Buffer Too Small"}, + { 0, NULL} +} ; const CHAR16 * util_error_message(EFI_STATUS status) diff --git a/src/boot/utility.h b/src/boot/utility.h index c6d5dfd..5df0a09 100644 --- a/src/boot/utility.h +++ b/src/boot/utility.h @@ -6,27 +6,27 @@ const CHAR16 *util_error_message(EFI_STATUS status); -#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \ - if (EFI_ERROR((s))) { \ - Print(L"EFI_ERROR: " msg L": %s\n", ##__VA_ARGS__, util_error_message(s)); \ - return (s); \ +#define CHECK_EFI_STATUS_OR_RETURN(s, msg, ...) \ + if (EFI_ERROR((s))) { \ + con_printf(L"EFI_ERROR: " msg L": %s\n", ##__VA_ARGS__, util_error_message(s)); \ + return (s); \ } -#define CHECK_EFI_STATUS_OR_FAIL(s) \ - if (EFI_ERROR((s))) { \ +#define CHECK_EFI_STATUS_OR_FAIL(s) \ + if (EFI_ERROR((s))) { \ con_status_fail(util_error_message(s)); \ - while (1) __asm__("hlt"); \ + while (1) __asm__("hlt"); \ } -#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \ - if (EFI_ERROR((s))) { \ - __asm__ __volatile__( \ - "movq %0, %%r8;" \ - "movq %1, %%r9;" \ - "movq %2, %%r10;" \ - "movq $0, %%rdx;" \ - "divq %%rdx;" \ - : \ +#define CHECK_EFI_STATUS_OR_ASSERT(s, d) \ + if (EFI_ERROR((s))) { \ + __asm__ __volatile__( \ + "movq %0, %%r8;" \ + "movq %1, %%r9;" \ + "movq %2, %%r10;" \ + "movq $0, %%rdx;" \ + "divq %%rdx;" \ + : \ : "r"((uint64_t)s), "r"((uint64_t)d), "r"((uint64_t)__LINE__) \ - : "rax", "rdx", "r8", "r9", "r10"); \ + : "rax", "rdx", "r8", "r9", "r10"); \ }