diff options
author | Freya Murphy <freya@freyacat.org> | 2025-04-19 16:36:51 -0400 |
---|---|---|
committer | Freya Murphy <freya@freyacat.org> | 2025-04-19 16:37:54 -0400 |
commit | 472ec944d2ed81d0304cc6cac80946a6a44776be (patch) | |
tree | f6cae641c143a0b45bb289d9d9fc6145706025b0 /kernel/efi | |
parent | set mmap limit (diff) | |
download | comus-472ec944d2ed81d0304cc6cac80946a6a44776be.tar.gz comus-472ec944d2ed81d0304cc6cac80946a6a44776be.tar.bz2 comus-472ec944d2ed81d0304cc6cac80946a6a44776be.zip |
UEFI and republicans
Diffstat (limited to 'kernel/efi')
-rw-r--r-- | kernel/efi/efi.c | 28 | ||||
-rw-r--r-- | kernel/efi/efi.h | 9 | ||||
-rw-r--r-- | kernel/efi/gop.c | 52 | ||||
-rw-r--r-- | kernel/efi/mmap.c | 87 |
4 files changed, 176 insertions, 0 deletions
diff --git a/kernel/efi/efi.c b/kernel/efi/efi.c new file mode 100644 index 0000000..4f253a7 --- /dev/null +++ b/kernel/efi/efi.c @@ -0,0 +1,28 @@ +#include "lib/klib.h" +#include <lib.h> +#include <comus/efi.h> +#include <comus/mboot.h> +#include <comus/memory.h> +#include <efi.h> + +#include "efi.h" + +void efi_init(EFI_HANDLE IH, EFI_SYSTEM_TABLE *ST) +{ + EFI_STATUS status; + + if (IH == NULL || ST == NULL) + return; + + status = efi_load_mmap(ST); + if (EFI_ERROR(status)) + panic("Failed to load efi memory map, EFI_STATUS = %lu\n", status); + + status = efi_load_gop(ST); + if (EFI_ERROR(status)) + panic( + "Failed to locate graphics output protocol (GOP), EFI_STATUS = %lu\n", + status); + + ST->BootServices->ExitBootServices(IH, 0); +} diff --git a/kernel/efi/efi.h b/kernel/efi/efi.h new file mode 100644 index 0000000..7428f37 --- /dev/null +++ b/kernel/efi/efi.h @@ -0,0 +1,9 @@ +#ifndef __EFI_H +#define __EFI_H + +#include <efi.h> + +EFI_STATUS efi_load_mmap(EFI_SYSTEM_TABLE *ST); +EFI_STATUS efi_load_gop(EFI_SYSTEM_TABLE *ST); + +#endif /* efi.h */ diff --git a/kernel/efi/gop.c b/kernel/efi/gop.c new file mode 100644 index 0000000..899bbee --- /dev/null +++ b/kernel/efi/gop.c @@ -0,0 +1,52 @@ +#include <lib.h> +#include <efi.h> +#include <comus/efi.h> + +static EFI_GRAPHICS_OUTPUT_PROTOCOL *gop = NULL; + +EFI_STATUS efi_load_gop(EFI_SYSTEM_TABLE *ST) +{ + EFI_STATUS status = EFI_SUCCESS; + EFI_GUID gopGuid = EFI_GRAPHICS_OUTPUT_PROTOCOL_GUID; + EFI_GRAPHICS_OUTPUT_MODE_INFORMATION *info; + UINTN SizeOfInfo, numModes, nativeMode; + + status = ST->BootServices->LocateProtocol(&gopGuid, NULL, (void **)&gop); + if (EFI_ERROR(status)) + return status; + + status = gop->QueryMode(gop, gop->Mode == NULL ? 0 : gop->Mode->Mode, + &SizeOfInfo, &info); + if (status == EFI_NOT_STARTED) + status = gop->SetMode(gop, 0); + if (EFI_ERROR(status)) + return status; + + nativeMode = gop->Mode->Mode; + numModes = gop->Mode->MaxMode; + + // find the best mode + UINTN best = nativeMode; + UINTN width = 0; + for (UINTN i = 0; i < numModes; i++) { + status = gop->QueryMode(gop, i, &SizeOfInfo, &info); + if (info->PixelFormat != PixelBlueGreenRedReserved8BitPerColor && + info->PixelFormat != PixelRedGreenBlueReserved8BitPerColor) + continue; + if (info->HorizontalResolution > width) { + width = info->HorizontalResolution; + best = i; + } + } + + gop->SetMode(gop, best); + if (EFI_ERROR(status)) + return status; + + return status; +} + +EFI_GRAPHICS_OUTPUT_PROTOCOL *efi_get_gop(void) +{ + return gop; +} diff --git a/kernel/efi/mmap.c b/kernel/efi/mmap.c new file mode 100644 index 0000000..26aba6a --- /dev/null +++ b/kernel/efi/mmap.c @@ -0,0 +1,87 @@ +#include <lib.h> +#include <efi.h> +#include <comus/efi.h> +#include <comus/memory.h> + +struct memory_map efi_mmap = { 0 }; + +EFI_STATUS efi_load_mmap(EFI_SYSTEM_TABLE *ST) +{ + EFI_STATUS status = EFI_SUCCESS; + + EFI_MEMORY_DESCRIPTOR *memory_map = NULL; + UINT32 version = 0; + UINTN map_key = 0; + UINTN descriptor_size = 0; + UINTN memory_map_size = 0; + + status = ST->BootServices->GetMemoryMap( + &memory_map_size, memory_map, &map_key, &descriptor_size, &version); + + assert(status != EFI_SUCCESS, + "GetMemoryMap should NEVER succeed the first time"); + if (status != EFI_BUFFER_TOO_SMALL) + return status; + + UINTN encompassing_size = memory_map_size + (2 * descriptor_size); + void *buffer = NULL; + status = ST->BootServices->AllocatePool(EfiLoaderData, encompassing_size, + &buffer); + + if (EFI_ERROR(status)) + return status; + + memory_map = (EFI_MEMORY_DESCRIPTOR *)buffer; + memory_map_size = encompassing_size; + status = ST->BootServices->GetMemoryMap( + &memory_map_size, memory_map, &map_key, &descriptor_size, &version); + + if (EFI_ERROR(status)) + return status; + + uint32_t idx = 0; + for (size_t i = 0; i < (memory_map_size / descriptor_size); i++) { + EFI_MEMORY_DESCRIPTOR *seg = + (EFI_MEMORY_DESCRIPTOR *)((char *)memory_map + + (descriptor_size * i)); + if (idx >= N_MMAP_ENTRY) + panic("Too many mmap entries: limit is %d", N_MMAP_ENTRY); + efi_mmap.entries[idx].addr = seg->PhysicalStart; + efi_mmap.entries[idx].len = seg->NumberOfPages * PAGE_SIZE; + switch (seg->Type) { + case EfiReservedMemoryType: + case EfiMemoryMappedIO: + case EfiMemoryMappedIOPortSpace: + efi_mmap.entries[idx].type = SEG_TYPE_RESERVED; + break; + case EfiConventionalMemory: + efi_mmap.entries[idx].type = SEG_TYPE_FREE; + break; + case EfiACPIReclaimMemory: + case EfiACPIMemoryNVS: + efi_mmap.entries[idx].type = SEG_TYPE_ACPI; + break; + case EfiUnusableMemory: + efi_mmap.entries[idx].type = SEG_TYPE_DEFECTIVE; + break; + default: + efi_mmap.entries[idx].type = SEG_TYPE_EFI; + break; + } + idx++; + } + efi_mmap.entry_count = idx; + + ST->BootServices->FreePool(buffer); + + return status; +} + +int efi_get_mmap(struct memory_map *map) +{ + if (efi_mmap.entry_count) { + *map = efi_mmap; + return 0; + } + return 1; +} |