summaryrefslogtreecommitdiff
path: root/kernel/efi
diff options
context:
space:
mode:
authorFreya Murphy <freya@freyacat.org>2025-04-19 16:36:51 -0400
committerFreya Murphy <freya@freyacat.org>2025-04-19 16:37:54 -0400
commit472ec944d2ed81d0304cc6cac80946a6a44776be (patch)
treef6cae641c143a0b45bb289d9d9fc6145706025b0 /kernel/efi
parentset mmap limit (diff)
downloadcomus-472ec944d2ed81d0304cc6cac80946a6a44776be.tar.gz
comus-472ec944d2ed81d0304cc6cac80946a6a44776be.tar.bz2
comus-472ec944d2ed81d0304cc6cac80946a6a44776be.zip
UEFI and republicans
Diffstat (limited to 'kernel/efi')
-rw-r--r--kernel/efi/efi.c28
-rw-r--r--kernel/efi/efi.h9
-rw-r--r--kernel/efi/gop.c52
-rw-r--r--kernel/efi/mmap.c87
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;
+}