diff --git a/Makefile b/Makefile index ec3e3a2..eb8c952 100644 --- a/Makefile +++ b/Makefile @@ -47,10 +47,14 @@ ASFLAGS ?= CFLAGS ?= CFLAGS += $(INCLUDES) $(DEPENDFLAGS) $(BASEFLAGS) $(WARNFLAGS) -CFLAGS += -DGIT_VERSION="\"$(VERSION)\"" +CFLAGS += -DGIT_VERSION="L\"$(VERSION)\"" CFLAGS += -std=c11 -fno-stack-protector -fpic -fshort-wchar -mno-red-zone CFLAGS += -DEFI_DEBUG=0 -DEFI_DEBUG_CLEAR_MEMORY=0 -DGNU_EFI_USE_MS_ABI -DHAVE_USE_MS_ABI #-DEFI_FUNCTION_WRAPPER +ifdef MAX_HRES +CFLAGS += -DMAX_HRES=$(MAX_HRES) +endif + LDFLAGS ?= LDFLAGS += -L $(BUILD_D) -ggdb LDFLAGS += -nostdlib -znocombreloc -shared -Bsymbolic -fPIC -nostartfiles @@ -76,7 +80,7 @@ QEMU ?= qemu-system-x86_64 GDBPORT ?= 27006 CPUS ?= 2 OVMF ?= assets/ovmf/x64/OVMF.fd -QEMUOPTS := -bios $(OVMF) -hda $(BUILD_D)/fs.img -smp $(CPUS) -m 512 -nographic $(QEMUEXTRA) +QEMUOPTS := -bios $(OVMF) -hda $(BUILD_D)/fs.img -smp $(CPUS) -m 512 $(QEMUEXTRA) all: $(BUILD_D)/fs.img @@ -150,6 +154,9 @@ $(BUILD_D)/fs.iso: $(BUILD_D)/fs.img xorriso -as mkisofs -R -f -e fs.img -no-emul-boot -o $@ $(BUILD_D)/iso qemu: $(BUILD_D)/fs.img + "$(QEMU)" $(QEMUOPTS) -nographic + +qemu-window: $(BUILD_D)/fs.img "$(QEMU)" $(QEMUOPTS) qemu-gdb: $(BUILD_D)/fs.img $(BUILD_D)/kernel.debug.efi diff --git a/src/arch/x86_64/console.c b/src/arch/x86_64/console.c new file mode 100644 index 0000000..7fab44e --- /dev/null +++ b/src/arch/x86_64/console.c @@ -0,0 +1,116 @@ +#include +#include +#include + +#include "console.h" +#include "utility.h" + +UINTN ROWS = 0; +UINTN COLS = 0; + +EFI_STATUS +con_initialize (const CHAR16 *version) +{ + EFI_STATUS status; + + Print(L"Setting console display mode...\n"); + + 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); + CHECK_EFI_STATUS_OR_RETURN(status, "LocateProtocol gfx"); + + const uint32_t modes = gfx_out_proto->Mode->MaxMode; + uint32_t res = + gfx_out_proto->Mode->Info->HorizontalResolution * + gfx_out_proto->Mode->Info->VerticalResolution; + uint32_t best = gfx_out_proto->Mode->Mode; + + for (uint32_t i = 0; i < modes; ++i) { + UINTN size = 0; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info = NULL; + status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info); + CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); + +#ifdef MAX_HRES + if (info->HorizontalResolution > MAX_HRES) + continue; +#endif + + const uint32_t new_res = + info->HorizontalResolution * + info->VerticalResolution; + + if (new_res > res) { + best = i; + res = new_res; + } + } + + 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); + CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); + + status = ST->ConOut->ClearScreen(ST->ConOut); + CHECK_EFI_STATUS_OR_RETURN(status, "ClearScreen"); + + ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTCYAN); + ST->ConOut->OutputString(ST->ConOut, (CHAR16*)L"Popcorn OS "); + + ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTMAGENTA); + ST->ConOut->OutputString(ST->ConOut, (CHAR16*)version); + + ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); + ST->ConOut->OutputString(ST->ConOut, (CHAR16*)L" booting...\r\n"); + + con_status_begin(L"Setting console display mode: "); + Print(L"%ux%u (%ux%u chars)\n", + gfx_out_proto->Mode->Info->HorizontalResolution, + gfx_out_proto->Mode->Info->VerticalResolution, + ROWS, COLS); + con_status_ok(); + + return status; +} + +void +con_status_begin (const CHAR16 *message) +{ + ST->ConOut->SetAttribute(ST->ConOut, EFI_LIGHTGRAY); + ST->ConOut->OutputString(ST->ConOut, (CHAR16*)message); +} + +void +con_status_ok () +{ + UINTN row = ST->ConOut->Mode->CursorRow; + ST->ConOut->SetCursorPosition(ST->ConOut, COLS - 8, row - 1); + 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"); +} + +void +con_status_fail (const CHAR16 *error) +{ + UINTN row = ST->ConOut->Mode->CursorRow; + ST->ConOut->SetCursorPosition(ST->ConOut, COLS - 8, row - 1); + 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\n"); + ST->ConOut->SetAttribute(ST->ConOut, EFI_RED); + ST->ConOut->OutputString(ST->ConOut, (CHAR16*)error); +} \ No newline at end of file diff --git a/src/arch/x86_64/console.h b/src/arch/x86_64/console.h new file mode 100644 index 0000000..4e4129a --- /dev/null +++ b/src/arch/x86_64/console.h @@ -0,0 +1,7 @@ +#pragma once +#include + +EFI_STATUS con_initialize (const CHAR16 *version); +void con_status_begin (const CHAR16 *message); +void con_status_ok (); +void con_status_fail (const CHAR16 *error); diff --git a/src/arch/x86_64/graphics.c b/src/arch/x86_64/graphics.c deleted file mode 100644 index 12ed3f6..0000000 --- a/src/arch/x86_64/graphics.c +++ /dev/null @@ -1,53 +0,0 @@ -#include -#include - -#include "utility.h" - -EFI_STATUS -set_graphics_mode (EFI_SYSTEM_TABLE *SystemTable) -{ - EFI_STATUS status; - - Print(L"Setting console display mode... "); - - EFI_GRAPHICS_OUTPUT_PROTOCOL *gfx_out_proto; - EFI_GUID gfx_out_guid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; - - status = SystemTable->BootServices->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; - uint32_t res = - gfx_out_proto->Mode->Info->HorizontalResolution * - gfx_out_proto->Mode->Info->VerticalResolution; - uint32_t best = (uint32_t)-1; - - for (uint32_t i = 0; i < modes; ++i) { - UINTN size = 0; - EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info = NULL; - status = gfx_out_proto->QueryMode(gfx_out_proto, i, &size, &info); - CHECK_EFI_STATUS_OR_RETURN(status, "QueryMode"); - - const uint32_t new_res = - info->HorizontalResolution * - info->VerticalResolution; - - if (new_res > res) { - best = i; - res = new_res; - } - } - - if (best != (uint32_t)-1) { - status = gfx_out_proto->SetMode(gfx_out_proto, best); - CHECK_EFI_STATUS_OR_RETURN(status, "SetMode"); - Print(L"*"); - } - Print(L"%ux%u\n", - gfx_out_proto->Mode->Info->HorizontalResolution, - gfx_out_proto->Mode->Info->VerticalResolution); - - return status; -} - diff --git a/src/arch/x86_64/graphics.h b/src/arch/x86_64/graphics.h deleted file mode 100644 index c5a07a3..0000000 --- a/src/arch/x86_64/graphics.h +++ /dev/null @@ -1,4 +0,0 @@ -#pragma once -#include - -EFI_STATUS set_graphics_mode (EFI_SYSTEM_TABLE *SystemTable); diff --git a/src/arch/x86_64/main.c b/src/arch/x86_64/main.c index 6ba1e8c..e582301 100644 --- a/src/arch/x86_64/main.c +++ b/src/arch/x86_64/main.c @@ -1,9 +1,13 @@ #include #include -#include "graphics.h" +#include "console.h" #include "utility.h" +#ifndef GIT_VERSION + #define GIT_VERSION L"no version" +#endif + EFI_STATUS efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) { @@ -11,10 +15,14 @@ efi_main (EFI_HANDLE ImageHandle, EFI_SYSTEM_TABLE *SystemTable) InitializeLib(ImageHandle, SystemTable); - Print(L"Popcorn OS " GIT_VERSION L" booting...\n"); + // 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); + CHECK_EFI_STATUS_OR_RETURN(status, "con_initialize"); - status = set_graphics_mode(SystemTable); - CHECK_EFI_STATUS_OR_RETURN(status, "set_graphics_mode"); + // From here on out, use CHECK_EFI_STATUS_OR_FAIL instead + // because the console is now set up Print(L" SystemTable: %x\n", SystemTable); if (SystemTable) diff --git a/src/arch/x86_64/utility.c b/src/arch/x86_64/utility.c new file mode 100644 index 0000000..604c534 --- /dev/null +++ b/src/arch/x86_64/utility.c @@ -0,0 +1,18 @@ +#include + +struct ErrorCode { + EFI_STATUS code; + const CHAR16 *desc; +}; + +extern struct ErrorCode ErrorCodeTable[]; + +const CHAR16 *util_error_message(EFI_STATUS status) { + int32_t i = -1; + while (ErrorCodeTable[++i].desc != NULL) { + if (ErrorCodeTable[i].code == status) + return ErrorCodeTable[i].desc; + } + + return L"Unknown"; +} \ No newline at end of file diff --git a/src/arch/x86_64/utility.h b/src/arch/x86_64/utility.h index 8cf715c..272cd23 100644 --- a/src/arch/x86_64/utility.h +++ b/src/arch/x86_64/utility.h @@ -1,9 +1,19 @@ #include #include +#include "console.h" -#define CHECK_EFI_STATUS_OR_RETURN(s, msg) \ +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" %d\n", (s)); \ + Print(L"EFI_ERROR: " msg L": %s\n", ## __VA_ARGS__, util_error_message(s)); \ return (s); \ } +#define CHECK_EFI_STATUS_OR_FAIL(s, msg, ...) \ + if (EFI_ERROR((s))) { \ + con_status_fail(util_error_message(s)); \ + Print(L"\n" msg, ## __VA_ARGS__ ); \ + while (1) __asm__("hlt"); \ + } +