summaryrefslogtreecommitdiff
path: root/loader
diff options
context:
space:
mode:
Diffstat (limited to 'loader')
-rw-r--r--loader/Makefile2
-rw-r--r--loader/image_efi.c211
-rw-r--r--loader/loader_efi.c182
-rw-r--r--loader/loader_efi.h64
-rw-r--r--loader/main_efi.c324
-rw-r--r--loader/memory_efi.c55
-rw-r--r--loader/paging_efi.c155
7 files changed, 237 insertions, 756 deletions
diff --git a/loader/Makefile b/loader/Makefile
index 975c2ce..dd8c21c 100644
--- a/loader/Makefile
+++ b/loader/Makefile
@@ -10,7 +10,7 @@ CPPFLAGS += -I../api
all: $(BUILD)
-OBJS := main_efi.o loader_efi.o paging_efi.o memory_efi.o image_efi.o \
+OBJS := main_efi.o elf.o \
memcmp.o memmove.o
DEPS := $(OBJS:.o=.d)
diff --git a/loader/image_efi.c b/loader/image_efi.c
deleted file mode 100644
index 04d0a9b..0000000
--- a/loader/image_efi.c
+++ /dev/null
@@ -1,211 +0,0 @@
-#include "loader_efi.h"
-
-static bool validate_image(Elf64_Ehdr *ehdr);
-static size_t image_size(struct system_image *image);
-static enum page_type get_page_type(Elf64_Phdr *phdr);
-
-struct system_image *system_image_open(CHAR16 *path)
-{
- EFI_STATUS status;
- EFI_FILE_PROTOCOL *root;
- EFI_FILE_PROTOCOL *file;
- struct system_image *image = NULL;
-
- status = e_system_partition->OpenVolume(e_system_partition, &root);
-
- if (EFI_ERROR(status))
- {
- Print(L"failed opening system partition root: %r\r\n", status);
- return NULL;
- }
-
- status = root->Open(root, &file, path, EFI_FILE_MODE_READ, 0);
-
- if (EFI_ERROR(status))
- {
- Print(L"failed opening image file %s: %r\r\n", path, status);
- return NULL;
- }
-
- image = efi_allocate(sizeof(*image));
-
- if (!image)
- {
- Print(L"failed allocating image data: %r\r\n", e_last_error);
- goto failure;
- }
-
- image->file = file;
-
- UINTN ehdr_size = sizeof(image->ehdr);
- status = file->Read(file, &ehdr_size, &image->ehdr);
-
- if (EFI_ERROR(status))
- {
- Print(L"failed reading image file %s: %r\r\n", path, status);
- goto failure;
- }
-
- if (!validate_image(&image->ehdr))
- {
- Print(L"failed validating image file %s: %r\r\n", path, status);
- goto failure;
- }
-
- UINTN phdrs_size = image->ehdr.e_phentsize * image->ehdr.e_phnum;
- image->phdrs = efi_allocate(phdrs_size);
-
- if (!image->phdrs)
- {
- Print(L"failed allocating segment data: %r", e_last_error);
- goto failure;
- }
-
- status = file->Read(file, &phdrs_size, image->phdrs);
-
- if (EFI_ERROR(status))
- {
- Print(L"failed reading segment data: %r", status);
- goto failure;
- }
-
- return image;
-
-failure:
- file->Close(file);
- return NULL;
-}
-
-bool system_image_load(struct system_image *image)
-{
- image->buffer = system_allocate(image_size(image));
-
- if (image->buffer.type != SYSTEM_MEMORY)
- {
- return false;
- }
-
- e_bs->SetMem((VOID *)image->buffer.base, image->buffer.size, 0);
-
- Elf64_Ehdr *ehdr = &image->ehdr;
- Elf64_Phdr *phdrs = image->phdrs;
-
- Print(L"found %d segments in image\r\n", ehdr->e_phnum);
-
- EFI_STATUS status = EFI_SUCCESS;
-
- for (UINTN i = 0; i < ehdr->e_phnum && !EFI_ERROR(status); i++)
- {
- switch (phdrs[i].p_type)
- {
- case PT_LOAD:
- Print(L"loadable segment %16.0lx at offset %x of %d bytes\r\n",
- phdrs[i].p_vaddr,
- phdrs[i].p_offset,
- phdrs[i].p_memsz);
-
- void *segment = (void *)(image->buffer.base + phdrs[i].p_paddr);
- UINTN segment_size = phdrs[i].p_filesz;
-
- image->file->SetPosition(image->file, phdrs[i].p_offset);
- status = image->file->Read(image->file, &segment_size, segment);
- break;
- default:
- continue;
- }
- }
-
- if (EFI_ERROR(status))
- {
- Print(L"failure reading segment from file: %r\r\n", status);
- return false;
- }
-
- return true;
-}
-
-void system_image_map(struct system_image *image)
-{
- Elf64_Ehdr *ehdr = &image->ehdr;
- Elf64_Phdr *phdrs = image->phdrs;
-
- for (int i = 0; i < ehdr->e_phnum; i++)
- {
- if (phdrs[i].p_type == PT_LOAD)
- {
- void *virt_begin = (void *)phdrs[i].p_vaddr;
- uint64_t phys_begin = image->buffer.base + phdrs[i].p_paddr;
- size_t size = phdrs[i].p_memsz;
- Print(L"mapping segment %16.0lx to %16.0lx %d bytes\r\n",
- virt_begin,
- phys_begin,
- size);
-
- paging_map_pages(virt_begin,
- phys_begin,
- get_page_type(&phdrs[i]),
- size);
- }
- }
-}
-
-
-static bool validate_image(Elf64_Ehdr *ehdr)
-{
- if (ehdr->e_ident[EI_MAG0] != ELFMAG0 ||
- ehdr->e_ident[EI_MAG1] != ELFMAG1 ||
- ehdr->e_ident[EI_MAG2] != ELFMAG2 ||
- ehdr->e_ident[EI_MAG3] != ELFMAG3 ||
- ehdr->e_ident[EI_CLASS] != ELFCLASS64 ||
- ehdr->e_ident[EI_DATA] != ELFDATA2LSB ||
- ehdr->e_ident[EI_VERSION] != EV_CURRENT ||
- ehdr->e_machine != EM_X86_64)
- {
- Print(L"invalid image format\r\n");
- return false;
- }
-
- Print(L"elf x64 image detected\r\n");
-
- return true;
-}
-
-static size_t image_size(struct system_image *image)
-{
- size_t size = 0;
- Elf64_Phdr *phdrs = image->phdrs;
-
- for (int i = 0; i < image->ehdr.e_phnum; i++)
- {
- if (phdrs[i].p_type != PT_LOAD)
- {
- continue;
- }
-
- if (phdrs[i].p_paddr + phdrs[i].p_memsz > size)
- {
- size = phdrs[i].p_paddr + phdrs[i].p_memsz;
- if (phdrs[i].p_align > 1)
- {
- size = (size + phdrs[i].p_align - 1) & ~(phdrs[i].p_align - 1);
- }
- }
- }
-
- return size;
-}
-
-static enum page_type get_page_type(Elf64_Phdr *phdr)
-{
- switch (phdr->p_flags)
- {
- case (PF_R|PF_X):
- return CODE_PAGE_TYPE;
- case (PF_R):
- return RODATA_PAGE_TYPE;
- case (PF_R|PF_W):
- return DATA_PAGE_TYPE;
- }
-
- return INVALID_PAGE_TYPE;
-}
diff --git a/loader/loader_efi.c b/loader/loader_efi.c
deleted file mode 100644
index 23540ef..0000000
--- a/loader/loader_efi.c
+++ /dev/null
@@ -1,182 +0,0 @@
-#include "loader_efi.h"
-
-#include <loader/data_efi.h>
-
-#include <kernel/entry.h>
-
-static CHAR16 *kernel_path = L"\\adasoft\\sophia\\kernel.os";
-static struct system_image *kernel_image = NULL;
-
-static struct efi_memory_map_data *get_memory_map_data(void);
-static struct efi_framebuffer_data *get_framebuffer_data(void);
-static void *get_acpi_data(void);
-
-noreturn static void enter_kernel()
-{
- struct efi_boot_data data;
- kernel_entry_func kernel_entry;
- kernel_entry = (kernel_entry_func)(kernel_image->ehdr.e_entry);
-
- struct memory_range kernel_entry_stack =
- system_allocate(KERNEL_ENTRY_STACK_SIZE);
-
- // get a stack here for now idfk
- paging_map_range(KERNEL_ENTRY_STACK_BASE,
- &kernel_entry_stack,
- DATA_PAGE_TYPE);
-
- data.acpi = get_acpi_data();
- data.framebuffer = get_framebuffer_data();
- data.memory_map = get_memory_map_data();
-
- EFI_STATUS status = e_bs->ExitBootServices(e_image_handle,
- data.memory_map->key);
-
- if (EFI_ERROR(status))
- {
- Print(L"failed exiting boot services environment: %r\r\n", status);
- efi_exit(status);
- }
-
- // enter the kernel address environment
- paging_enter();
-
- // set the kernel entry stack.
- __asm__
- (
- "mov %0, %%rsp"
- :
- : "r"((uint64_t)KERNEL_ENTRY_STACK_HEAD)
- );
-
- kernel_entry(&data);
-
- while(true);
-}
-
-void loader_main(void)
-{
- kernel_image = system_image_open(kernel_path);
-
- Print(L"loading %s\r\n", kernel_path);
-
- if (system_image_load(kernel_image))
- {
- Print(L"loaded kernel image at base %16.0lx size %d bytes\r\n",
- kernel_image->buffer.base,
- kernel_image->buffer.size);
- }
- else
- {
- Print(L"failed loading kernel image\r\n");
- efi_exit(EFI_ABORTED);
- }
-
- paging_init();
- system_image_map(kernel_image);
- Print(L"kernel maps created. entering kernel\r\n");
- enter_kernel();
-
- efi_exit(EFI_ABORTED);
-}
-
-static struct efi_memory_map_data *get_memory_map_data(void)
-{
- EFI_STATUS status;
- UINTN mapsize = 0;
- struct efi_memory_map_data *map = NULL;
-
- status = e_bs->GetMemoryMap(&mapsize, NULL, NULL, NULL, NULL);
-
- if (status == EFI_BUFFER_TOO_SMALL)
- {
- map = efi_allocate(sizeof(*map) + mapsize);
- }
-
- if (map)
- {
- status = e_bs->GetMemoryMap(&map->size,
- map->data,
- &map->key,
- &map->descsize,
- &map->descver);
- }
- else
- {
- status = e_last_error;
- }
-
- if (EFI_ERROR(status))
- {
- Print(L"failed getting memory map: %r\r\n", status);
- return NULL;
- }
-
- return map;
-}
-
-static struct efi_framebuffer_data *get_framebuffer_data(void)
-{
- struct efi_framebuffer_data *framebuffer;
-
- if (!e_graphics_output)
- {
- return NULL;
- }
-
- framebuffer = efi_allocate(sizeof(*framebuffer));
-
- if (framebuffer)
- {
- EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE *mode = e_graphics_output->Mode;
-
- framebuffer->bitmask = mode->Info->PixelInformation;
- framebuffer->width = mode->Info->HorizontalResolution;
- framebuffer->height = mode->Info->VerticalResolution;
- framebuffer->buffer.base = mode->FrameBufferBase;
- framebuffer->buffer.size = mode->FrameBufferSize;
- framebuffer->buffer.type = RESERVED_MEMORY;
- framebuffer->pxformat = mode->Info->PixelFormat;
-
- switch (framebuffer->pxformat)
- {
- //falthrough
- case PixelBlueGreenRedReserved8BitPerColor:
- case PixelRedGreenBlueReserved8BitPerColor:
- framebuffer->pxsize = sizeof(EFI_GRAPHICS_OUTPUT_BLT_PIXEL);
- break;
- default:
- // TODO: calculate pixel size for bitmask format
- framebuffer->pxsize = 0;
- }
-
- framebuffer->pitch = framebuffer->width * framebuffer->pxsize;
- }
- else
- {
- Print(L"failed getting framebuffer data: %r\r\n", e_last_error);
- return NULL;
- }
-
- return framebuffer;
-}
-
-static void *get_acpi_data(void)
-{
- struct efi_acpi_data *acpi = efi_allocate(sizeof(*acpi));
-
- EFI_GUID acpi_20_guid = ACPI_20_TABLE_GUID;
-
- for (UINTN i = 0; acpi && i < e_st->NumberOfTableEntries; i++)
- {
- if (!CompareGuid(&acpi_20_guid, &e_st->ConfigurationTable[i].VendorGuid))
- {
- acpi->rsdp = e_st->ConfigurationTable[i].VendorTable;
- return acpi;
- }
- }
-
- Print(L"failed getting acpi rsdp\r\n");
- return NULL;
-}
-
diff --git a/loader/loader_efi.h b/loader/loader_efi.h
deleted file mode 100644
index 4ce3098..0000000
--- a/loader/loader_efi.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#pragma once
-
-#include <kernel/memory/range.h>
-#include <kernel/memory/paging.h>
-
-#include <elf/elf64.h>
-
-#include <efi.h>
-#include <efilib.h>
-
-#include <stdbool.h>
-#include <stddef.h>
-#include <stdnoreturn.h>
-
-enum page_type
-{
- INVALID_PAGE_TYPE = 0x0,
- CODE_PAGE_TYPE = PAGE_PR,
- RODATA_PAGE_TYPE = PAGE_PR|PAGE_NX,
- DATA_PAGE_TYPE = PAGE_PR|PAGE_WR|PAGE_NX
-};
-
-struct system_image
-{
- struct memory_range buffer;
- EFI_FILE_PROTOCOL *file;
- Elf64_Ehdr ehdr;
- Elf64_Phdr *phdrs;
-};
-
-extern EFI_SYSTEM_TABLE *e_st;
-extern EFI_BOOT_SERVICES *e_bs;
-extern EFI_RUNTIME_SERVICES *e_rt;
-
-extern EFI_HANDLE e_image_handle;
-extern EFI_LOADED_IMAGE_PROTOCOL *e_loaded_image;
-extern EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *e_system_partition;
-extern EFI_GRAPHICS_OUTPUT_PROTOCOL *e_graphics_output;
-extern EFI_STATUS e_last_error;
-
-noreturn void efi_exit(EFI_STATUS status);
-
-struct memory_range system_allocate(size_t size);
-
-void *efi_allocate(size_t size);
-void efi_free(void *buffer);
-
-void paging_init(void);
-void paging_enter(void);
-void *paging_map_page(void *vaddr, phys_addr_t paddr, enum page_type type);
-void *paging_map_pages(void *vaddr,
- phys_addr_t paddr,
- enum page_type type,
- size_t size);
-void *paging_map_range(void *vaddr,
- struct memory_range *range,
- enum page_type type);
-
-struct system_image *system_image_open(CHAR16 *path);
-bool system_image_load(struct system_image *image);
-void system_image_map(struct system_image *image);
-
-void loader_main(void);
-
diff --git a/loader/main_efi.c b/loader/main_efi.c
index 8abf42a..7edb44d 100644
--- a/loader/main_efi.c
+++ b/loader/main_efi.c
@@ -1,129 +1,277 @@
-#include "loader_efi.h"
+#include <loader/efi/shim.h>
-#include <stdbool.h>
-#include <stddef.h>
+#include <efi.h>
+#include <efidebug.h>
+#include <efilib.h>
-EFI_SYSTEM_TABLE *e_st;
-EFI_BOOT_SERVICES *e_bs;
-EFI_RUNTIME_SERVICES *e_rt;
+#include "../lib/elf.h"
-EFI_HANDLE e_image_handle;
-EFI_LOADED_IMAGE_PROTOCOL *e_loaded_image;
-EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *e_system_partition;
-EFI_GRAPHICS_OUTPUT_PROTOCOL *e_graphics_output;
-EFI_STATUS e_last_error;
+EFI_STATUS alloc_page(EFI_MEMORY_TYPE type,
+ UINTN size,
+ EFI_PHYSICAL_ADDRESS *base);
+EFI_STATUS free_page(EFI_PHYSICAL_ADDRESS base, UINTN size);
-extern int _text;
-extern int _data;
+EFI_STATUS open_image(struct efi_loader_image *image);
+EFI_STATUS allocate_image(struct efi_loader_image *image);
+EFI_STATUS load_image(struct efi_loader_image *image);
-static EFI_LOADED_IMAGE_PROTOCOL *open_loaded_image(void);
-static EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *open_system_partition(void);
-static EFI_GRAPHICS_OUTPUT_PROTOCOL *open_graphics_output(void);
+static EFI_STATUS enter_shim(void);
+
+static struct efi_loader_image shim_image =
+{
+ .path = L"\\adasoft\\sophia\\efi.os"
+};
+
+static struct efi_loader_interface loader_interface =
+{
+ &alloc_page,
+ &free_page,
+
+ &open_image,
+ &allocate_image,
+ &load_image
+};
EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table)
{
- e_image_handle = image_handle;
- e_st = system_table;
- e_bs = e_st->BootServices;
- e_rt = e_st->RuntimeServices;
-
- InitializeLib(e_image_handle, e_st);
- Print(L"loader starting\r\n");
-
- e_loaded_image = open_loaded_image();
- e_system_partition = open_system_partition();
- e_graphics_output = open_graphics_output();
+ InitializeLib(image_handle, system_table);
+
+ shim_image.image_handle = image_handle;
+
+ EFI_STATUS status;
+
+ if (EFI_ERROR((status = open_image(&shim_image))))
+ {
+ Print(L"error opening shim image: %r\r\n");
+ }
+
+ if (EFI_ERROR((status = allocate_image(&shim_image))))
+ {
+ Print(L"error allocating shim image: %r\r\n");
+ }
+
+ if (EFI_ERROR((status = load_image(&shim_image))))
+ {
+ Print(L"error loading shim image: %r\r\n");
+ }
+
+ if (EFI_ERROR((status = enter_shim())))
+ {
+ Print(L"error running shim image: %r\r\n");
+ }
+
+ if (shim_image.root)
+ {
+ shim_image.root->Close(shim_image.root);
+ }
+ if (shim_image.file)
+ {
+ shim_image.file->Close(shim_image.file);
+ }
+
+ if (shim_image.buffer_base && shim_image.buffer_size)
+ {
+ free_page(shim_image.buffer_base,
+ EFI_SIZE_TO_PAGES(shim_image.buffer_size));
+ }
- WaitForSingleEvent(e_st->ConIn->WaitForKey, 0);
-
- loader_main();
+ return status;
+}
- efi_exit(EFI_ABORTED);
+EFI_STATUS alloc_page(EFI_MEMORY_TYPE type,
+ UINTN size,
+ EFI_PHYSICAL_ADDRESS *base)
+{
+ return gBS->AllocatePages(AllocateAnyPages,
+ type,
+ EFI_SIZE_TO_PAGES(size),
+ base);
}
-noreturn void efi_exit(EFI_STATUS status)
+EFI_STATUS free_page(EFI_PHYSICAL_ADDRESS base, UINTN size)
{
- if (EFI_ERROR(status))
+ return gBS->FreePages(base, size);
+}
+
+
+EFI_STATUS open_image(struct efi_loader_image *image)
+{
+ EFI_FILE_PROTOCOL *root;
+
+ EFI_LOADED_IMAGE_PROTOCOL *loader_image;
+
+ EFI_STATUS status;
+
+ status = gBS->OpenProtocol(image->image_handle,
+ &LoadedImageProtocol,
+ (void *)&loader_image,
+ image->image_handle,
+ NULL,
+ EFI_OPEN_PROTOCOL_GET_PROTOCOL);
+
+
+ if (EFI_ERROR(status) ||
+ !(root = LibOpenRoot(loader_image->DeviceHandle)))
+ {
+ Print(L"failed opening root device\r\n");
+ return EFI_NOT_FOUND;
+ }
+
+ Print(L"opening image %s\r\n", image->path);
+
+ status = root->Open(root,
+ &image->file,
+ image->path,
+ EFI_FILE_MODE_READ,
+ 0);
+
+ if (!EFI_ERROR(status))
+ {
+ image->root = root;
+ }
+ else
{
- Print(L"loader exited: %r\r\n", status);
+ Print(L"failed opening image: %r\r\n", status);
+ return status;
}
-
- e_bs->Exit(e_image_handle, status, 0, NULL);
- while (true);
+ Elf64_Ehdr ehdr;
+ UINTN ehdr_size = sizeof(ehdr);
+
+ Elf64_Phdr *phdrs = NULL;
+ UINTN phdrs_size = 0;
+
+ if (!EFI_ERROR((status = image->file->Read(image->file,
+ &ehdr_size,
+ &ehdr))))
+ {
+ if (elf_validate(&ehdr, ET_EXEC, EM_X86_64))
+ {
+ phdrs_size = ehdr.e_phentsize * ehdr.e_phnum;
+ phdrs = AllocatePool(phdrs_size);
+ ASSERT(phdrs);
+ }
+ else
+ {
+ FreePool(phdrs);
+ Print(L"invalid image format detected\r\n");
+ return EFI_INVALID_PARAMETER;
+ }
+ }
+ else
+ {
+ Print(L"failed reading shim image headers\r\n");
+ return status;
+ }
+
+ if (!EFI_ERROR((status = image->file->Read(image->file,
+ &phdrs_size,
+ phdrs))))
+ {
+ image->buffer_size = elf_size(&ehdr, phdrs);
+ image->system_table = gST;
+ Print(L"elf image %d bytes\r\n", image->buffer_size);
+ }
+ else
+ {
+ Print(L"failed reading shim image segments\r\n");
+ }
+
+ FreePool(phdrs);
+
+ return status;
}
-static EFI_LOADED_IMAGE_PROTOCOL *open_loaded_image(void)
+EFI_STATUS allocate_image(struct efi_loader_image *image)
{
- Print(L"opening loaded image\r\n");
-
+ Print(L"allocating image %s\r\n", image->path);
EFI_STATUS status;
- EFI_LOADED_IMAGE_PROTOCOL *image;
-
- status = e_bs->OpenProtocol(e_image_handle,
- &LoadedImageProtocol,
- (void **)&image,
- e_image_handle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
-
- if (EFI_ERROR(status))
+
+ status = alloc_page(SystemMemoryType,
+ image->buffer_size,
+ &image->buffer_base);
+
+ if (!EFI_ERROR(status))
{
- Print(L"failed opening loaded image\r\n");
- efi_exit(status);
+ gBS->SetMem((void *)image->buffer_base, image->buffer_size, 0);
}
- Print(L"image base: 0x%16.0x\r\n", image->ImageBase);
- Print(L"image .text segment: 0x%16.0x\r\n", &_text);
- Print(L"image .data segment: 0x%16.0x\r\n", &_data);
-
- return image;
+ return status;
}
-static EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *open_system_partition(void)
+static EFI_STATUS read_image(struct efi_loader_image *image,
+ VOID **buffer,
+ UINTN offset,
+ UINTN length)
{
- Print(L"opening system partition\r\n");
-
+ Print(L"reading %d bytes from image at 0x%8.0x %s\r\n", length, offset, image->path);
EFI_STATUS status;
- EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *partition;
-
- status = e_bs->OpenProtocol(e_loaded_image->DeviceHandle,
- &FileSystemProtocol,
- (void **)&partition,
- e_image_handle,
- NULL,
- EFI_OPEN_PROTOCOL_GET_PROTOCOL);
- if (EFI_ERROR(status))
+ ASSERT(buffer);
+
+ if (!EFI_ERROR((status = image->file->SetPosition(image->file, offset))))
{
- Print(L"failed opening system partition\r\n");
- efi_exit(status);
+ *buffer = (void *)(image->buffer_base + offset);
+ status = image->file->Read(image->file, &length, *buffer);
}
-
- Print(L"opened system partition\r\n");
-
- return partition;
+ else
+ {
+ Print(L"failed seeking shim image\r\n");
+ }
+
+ return status;
}
-static EFI_GRAPHICS_OUTPUT_PROTOCOL *open_graphics_output(void)
+EFI_STATUS load_image(struct efi_loader_image *image)
{
EFI_STATUS status;
- EFI_GRAPHICS_OUTPUT_PROTOCOL *graphics;
-
- Print(L"opening graphics output\r\n");
-
- status = e_bs->LocateProtocol(&GraphicsOutputProtocol,
- NULL,
- (VOID **)&graphics);
+ Elf64_Ehdr *ehdr;
+ Elf64_Phdr *phdrs;
- if (EFI_ERROR(status))
+ if (!EFI_ERROR((status = read_image(image,
+ (void **)&ehdr,
+ 0,
+ sizeof(*ehdr)))) &&
+ !EFI_ERROR((status = read_image(image,
+ (void **)&phdrs,
+ ehdr->e_phoff,
+ ehdr->e_phnum * ehdr->e_phentsize))))
{
- Print(L"failed opening graphics output: %r\r\n", status);
- return NULL;
+ for (UINTN i = 0; i < ehdr->e_phnum && !EFI_ERROR(status); i++)
+ {
+ if (PT_LOAD != phdrs[i].p_type)
+ {
+ continue;
+ }
+
+ void *placement;
+ status = read_image(image,
+ &placement,
+ phdrs[i].p_offset,
+ phdrs[i].p_filesz);
+
+ if (!EFI_ERROR(status))
+ {
+ Print(L"loaded segment 0x%16.0x of %d bytes "
+ L"(file size %d bytes)\r\n",
+ placement,
+ phdrs[i].p_memsz,
+ phdrs[i].p_filesz);
+ }
+ }
}
- Print(L"graphics output opened\r\n");
+ return status;
+}
+
+static EFI_STATUS enter_shim(void)
+{
+ EFI_STATUS status;
+ Elf64_Ehdr *ehdr = (Elf64_Ehdr *)shim_image.buffer_base;
+ efi_shim_entry_func entry;
- return graphics;
+ entry = (efi_shim_entry_func)(shim_image.buffer_base + ehdr->e_entry);
+ status = entry(&shim_image, &loader_interface);
+ return status;
}
diff --git a/loader/memory_efi.c b/loader/memory_efi.c
deleted file mode 100644
index 2fab6b7..0000000
--- a/loader/memory_efi.c
+++ /dev/null
@@ -1,55 +0,0 @@
-#include "loader_efi.h"
-
-#include <loader/data_efi.h>
-#include <kernel/memory/paging.h>
-
-struct memory_range system_allocate(size_t size)
-{
- EFI_STATUS status;
- struct memory_range buffer;
-
- buffer.type = SYSTEM_MEMORY;
- buffer.size = size;
-
- status = e_bs->AllocatePages(AllocateAnyPages,
- SystemMemoryType,
- page_count(buffer.size, 1),
- &buffer.base);
-
- if (EFI_ERROR(status))
- {
- Print(L"error allocating range: %r\r\n", status);
- e_last_error = status;
- buffer.type = UNUSABLE_MEMORY;
- }
-
- return buffer;
-}
-
-void *efi_allocate(size_t size)
-{
- EFI_STATUS status;
- void *buffer;
-
- status = e_bs->AllocatePool(EfiLoaderData, size, &buffer);
-
- if (EFI_ERROR(status))
- {
- e_last_error = status;
- buffer = NULL;
- }
-
- return buffer;
-}
-
-void efi_free(void *buffer)
-{
- EFI_STATUS status;
-
- status = e_bs->FreePool(buffer);
-
- if (EFI_ERROR(status))
- {
- e_last_error = status;
- }
-}
diff --git a/loader/paging_efi.c b/loader/paging_efi.c
deleted file mode 100644
index 5f65213..0000000
--- a/loader/paging_efi.c
+++ /dev/null
@@ -1,155 +0,0 @@
-#include "loader_efi.h"
-
-#include <kernel/memory/paging.h>
-
-#define KERNEL_SPACE_LOWER (void *)0xffffffff80000000
-#define KERNEL_SPACE_UPPER (void *)0xffffffffc0000000
-
-static uint64_t *new_page_table(void);
-static uint64_t *get_page_table(void *vaddr, int level);
-static uint64_t *get_page_entry(void *vaddr);
-
-static uint64_t *get_page_map(void);
-static void set_page_map(uint64_t *map);
-
-static uint64_t *efi_page_map = NULL;
-static uint64_t *system_page_map = NULL;
-
-void paging_init(void)
-{
- efi_page_map = get_page_map();
- system_page_map = new_page_table();
-
- if (!system_page_map)
- {
- Print(L"error creating page map: %r\r\n", e_last_error);
- efi_exit(e_last_error);
- }
-
- // copy the identity mappings from the EFI PML4.
- system_page_map[0] = efi_page_map[0];
-
- // create kernel fractal mappings
- // TODO: move this into the kernel instead?
- uint64_t *lower_pm2 = get_page_table(KERNEL_SPACE_LOWER, 2);
- uint64_t *upper_pm2 = get_page_table(KERNEL_SPACE_UPPER, 2);
-
- upper_pm2[PAGE_TABLE_INDEX_MASK - 1] = (phys_addr_t)lower_pm2|DATA_PAGE_TYPE;
- upper_pm2[PAGE_TABLE_INDEX_MASK] = (phys_addr_t)upper_pm2|DATA_PAGE_TYPE;
-}
-
-void paging_enter(void)
-{
- // use the system_page_map instead of efi_page_map
- set_page_map(system_page_map);
-}
-
-void *paging_map_page(void *vaddr, phys_addr_t paddr, enum page_type type)
-{
- uint64_t *entry = get_page_entry(vaddr);
-
- if (entry)
- {
- *entry = paddr | type;
- return vaddr;
- }
-
- return NULL;
-}
-
-void *paging_map_pages(void *vaddr,
- phys_addr_t paddr,
- enum page_type type,
- size_t size)
-{
- for (size_t offset = 0; offset < size; offset += page_size(1))
- {
- if (!paging_map_page((char *)vaddr + offset, paddr + offset, type))
- {
- return NULL;
- }
- }
-
- return vaddr;
-}
-
-void *paging_map_range(void *vaddr,
- struct memory_range *range,
- enum page_type type)
-{
- return paging_map_pages(vaddr, range->base, type, range->size);
-}
-
-static uint64_t *new_page_table(void)
-{
- struct memory_range table = system_allocate(page_size(1));
-
- if (table.type == SYSTEM_MEMORY)
- {
- e_bs->SetMem((void *)table.base, table.size, 0);
- return (uint64_t *)table.base;
- }
-
- return NULL;
-}
-
-static uint64_t *get_page_table(void *vaddr, int level)
-{
- // don't try to do anything if there's no page map.
- if (!system_page_map)
- {
- return NULL;
- }
-
- // don't try to do anything outside of the page map
- if ((level < 1) || (level > PAGE_MAP_LEVELS))
- {
- return NULL;
- }
-
- // don't use a non-canonical address
-
- uint64_t *map = system_page_map;
-
- for (int i = PAGE_MAP_LEVELS; i > level; i--)
- {
- if (!map[pte_index(vaddr, i)])
- {
- uint64_t *next_map = new_page_table();
- map[pte_index(vaddr, i)] = (phys_addr_t)next_map|PAGE_PR|PAGE_WR;
- map = next_map;
- }
- else
- {
- map = (uint64_t *)page_address(map[pte_index(vaddr, i)], 1);
- }
- }
-
- return map;
-}
-
-static uint64_t *get_page_entry(void *vaddr)
-{
- uint64_t *table = get_page_table(vaddr, 1);
- return &table[pte_index(vaddr, 1)];
-}
-
-static uint64_t *get_page_map(void)
-{
- uint64_t map;
- __asm__("mov %%cr3, %0" : "=r"(map));
- return (uint64_t *)(page_address(map, 1));
-}
-
-static void set_page_map(uint64_t *map)
-{
- __asm__
- (
- "pushf\r\n"
- "cli\r\n"
- "mov %0, %%cr3\r\n"
- "popf"
- :
- : "r"(map)
- );
-}