From 96ff1a24a7474b91c44a3dcd6f3abf3ec0542191 Mon Sep 17 00:00:00 2001 From: Ada Christine Date: Tue, 13 Feb 2024 01:04:02 +0000 Subject: reorganize a bit --- kjarna/Makefile | 7 +- kjarna/efi/file.c | 268 ++++++++++++++++++++++++++++++++++++++++++++++++ kjarna/efi/kjarna_efi.h | 36 +++++++ kjarna/efi/memory.c | 83 +++++++++++++++ kjarna/efi/protocol.c | 24 +++++ kjarna/efi/runtime.c | 195 +++++++++++++++++++++++++++++++++++ kjarna/efi/start.c | 29 ++++++ kjarna/file.c | 268 ------------------------------------------------ kjarna/kjarna.h | 7 ++ kjarna/kjarna_efi.h | 38 ------- kjarna/main.c | 5 +- kjarna/memory.c | 83 --------------- kjarna/protocol.c | 24 ----- kjarna/runtime.c | 195 ----------------------------------- kjarna/start.c | 30 ------ 15 files changed, 650 insertions(+), 642 deletions(-) create mode 100644 kjarna/efi/file.c create mode 100644 kjarna/efi/kjarna_efi.h create mode 100644 kjarna/efi/memory.c create mode 100644 kjarna/efi/protocol.c create mode 100644 kjarna/efi/runtime.c create mode 100644 kjarna/efi/start.c delete mode 100644 kjarna/file.c create mode 100644 kjarna/kjarna.h delete mode 100644 kjarna/kjarna_efi.h delete mode 100644 kjarna/memory.c delete mode 100644 kjarna/protocol.c delete mode 100644 kjarna/runtime.c delete mode 100644 kjarna/start.c diff --git a/kjarna/Makefile b/kjarna/Makefile index 4cf6102..b02fbe6 100644 --- a/kjarna/Makefile +++ b/kjarna/Makefile @@ -1,7 +1,7 @@ include ../defaults.mk include ../efi.mk -VPATH := ../lib +VPATH := ../lib efi/ IMAGE := kjarna.efi @@ -18,9 +18,10 @@ all: $(IMAGE) CRT_OBJS := start.o LIB_OBJS := memcmp.o memset.o memcpy.o memmove.o string.o elf64.o -APP_OBJS := file.o memory.o protocol.o runtime.o +EFI_OBJS := file.o memory.o protocol.o runtime.o +APP_OBJS := main.o -OBJS := $(CRT_OBJS) $(LIB_OBJS) $(APP_OBJS) +OBJS := $(CRT_OBJS) $(LIB_OBJS) $(EFI_OBJS) $(APP_OBJS) DEPS := $(OBJS:.o=.d) $(IMAGE): $(OBJS) diff --git a/kjarna/efi/file.c b/kjarna/efi/file.c new file mode 100644 index 0000000..6888390 --- /dev/null +++ b/kjarna/efi/file.c @@ -0,0 +1,268 @@ +#include +#include +#include +#include + +#include +#include +#include + +#include "kjarna_efi.h" + +#define FD_COUNT 16 +#define FD_MIN 3 +#define FD_MAX (FD_MIN + FD_COUNT - 1) + +static EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *fd_to_outconsole(int fd) +{ + switch (fd) + { + case STDOUT_FILENO: + return efi_context->system_table->ConOut; + case STDERR_FILENO: + return efi_context->system_table->StdErr; + default: + return nullptr; + } +} + +static EFI_SIMPLE_TEXT_INPUT_PROTOCOL *fd_to_inconsole(int fd) +{ + return fd == STDIN_FILENO ? efi_context->system_table->ConIn : nullptr; +} + +static EFI_FILE_PROTOCOL *open_files[FD_COUNT]; + +static EFI_FILE_PROTOCOL *fd_to_file(int fd) +{ + if (fd < FD_MIN || fd > FD_MAX) + { + return nullptr; + } + + return open_files[fd]; +} + +static int alloc_fd(void) +{ + for (int i = 0; i < FD_COUNT; i++) + { + if (open_files[i] == nullptr) + { + return FD_MIN + i; + } + } + + return -1; +} + +static void free_fd(int fd) +{ + if (fd < FD_MIN || fd > FD_MAX) + { + open_files[fd] = nullptr; + } +} + +int efi_open(const char *path, int flags, int mode) +{ + EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + EFI_LOADED_IMAGE_PROTOCOL *lip = nullptr; + + efi_errno = gBS->OpenProtocol( + efi_context->handle, + &lip_guid, + (void **)&lip, + efi_context->handle, + nullptr, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (lip == nullptr) + { + return -1; + } + + EFI_GUID sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *sfsp = nullptr; + + efi_errno = gBS->OpenProtocol( + lip->DeviceHandle, + &sfsp_guid, + (void **)&sfsp, + efi_context->handle, + nullptr, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (sfsp == nullptr) + { + return -1; + } + + EFI_FILE_PROTOCOL *root = nullptr; + + efi_errno = sfsp->OpenVolume(sfsp, &root); + + if (root == nullptr) + { + return -1; + } + + int fd = alloc_fd(); + + if (fd < FD_MIN) + { + return -1; + } + + size_t path_len = strlen(path) + 1; + CHAR16 *wcpath = efi_calloc_pool(path_len, sizeof(*wcpath)); + + if(mbstowcs(wcpath, path, path_len) == (size_t)-1) + { + efi_errno = EFI_INVALID_PARAMETER; + } + else + { + efi_errno = root->Open( + root, + &open_files[fd], + wcpath, + EFI_FILE_MODE_READ, + 0); + } + + efi_free_pool(wcpath); + + (void)flags; + (void)mode; + + return !EFI_ERROR(efi_errno) ? fd : -1; +} + +int efi_close(int fd) +{ + EFI_FILE_PROTOCOL *file = fd_to_file(fd); + + if (file == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + free_fd(fd); + + efi_errno = file->Close(file); + + return !EFI_ERROR(efi_errno) ? 0 : -1; +} + +off_t efi_lseek(int fd, off_t offset, int whence) +{ + if (whence != SEEK_SET) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + EFI_FILE_PROTOCOL *file = fd_to_file(fd); + + if (file == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + efi_errno = file->SetPosition(file, (UINTN)offset); + + return !EFI_ERROR(efi_errno) ? offset : -1; +} + +static ssize_t efi_console_read(EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console, CHAR16 *buffer, size_t length) +{ + (void)console; + (void)buffer; + efi_errno = EFI_INVALID_PARAMETER; + return !EFI_ERROR(efi_errno) ? length : -1; +} + +ssize_t efi_read(int fd, void *buffer, size_t length) +{ + if (buffer == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console = fd_to_inconsole(fd); + + if (console != nullptr) + { + return efi_console_read(console, buffer, length); + } + + EFI_FILE_PROTOCOL *file = fd_to_file(fd); + + if (file == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + size_t bytes = length; + efi_errno = file->Read(file, &bytes, buffer); + + return !EFI_ERROR(efi_errno) ? bytes : -1; +} + +static ssize_t efi_console_write(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *console, const void *buffer, size_t length) +{ + if (length == (size_t)-1) + { + length = strlen(buffer); + } + + wchar_t *ws = efi_calloc_pool(length + 1, sizeof(*ws)); + + if(mbstowcs(ws, buffer, length + 1) == (size_t)-1) + { + efi_errno = EFI_INVALID_PARAMETER; + } + else + { + efi_errno = console->OutputString(console, ws); + } + + efi_free_pool(ws); + + return !EFI_ERROR(efi_errno) ? length : -1; +} + +ssize_t efi_write(int fd, const void *buffer, size_t length) +{ + if (buffer == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *console = fd_to_outconsole(fd); + + if (console != nullptr) + { + return efi_console_write(console, buffer, length); + } + + EFI_FILE_PROTOCOL *file = fd_to_file(fd); + + if (file == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + size_t bytes = length; + efi_errno = file->Write(file, &bytes, (void *)buffer); + + return !EFI_ERROR(efi_errno) ? bytes : -1; +} + diff --git a/kjarna/efi/kjarna_efi.h b/kjarna/efi/kjarna_efi.h new file mode 100644 index 0000000..48b0034 --- /dev/null +++ b/kjarna/efi/kjarna_efi.h @@ -0,0 +1,36 @@ +#pragma once + +#include + +#include +#include + +#include "../kjarna.h" + +struct efi_context +{ + EFI_HANDLE const handle; + EFI_SYSTEM_TABLE * const system_table; +}; + +extern struct efi_context const *efi_context; +extern EFI_STATUS efi_errno; + +#define gST efi_context->system_table +#define gBS efi_context->system_table->BootServices + +void *efi_get_protocol(EFI_HANDLE handle, EFI_GUID *guid); + +int SYSV_ABI efi_open(const char *path, int flags, int mode); +int SYSV_ABI efi_close(int fd); +off_t SYSV_ABI efi_lseek(int fd, off_t offset, int whence); +ssize_t SYSV_ABI efi_read(int fd, void *buffer, size_t length); +ssize_t SYSV_ABI efi_write(int fd, const void *buffer, size_t length); + +void * SYSV_ABI efi_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); +int SYSV_ABI efi_munmap(void *addr, size_t length); + +void *efi_alloc_pool(size_t size); +void *efi_calloc_pool(size_t count, size_t size); +void efi_free_pool(void *block); + diff --git a/kjarna/efi/memory.c b/kjarna/efi/memory.c new file mode 100644 index 0000000..7fbb4a8 --- /dev/null +++ b/kjarna/efi/memory.c @@ -0,0 +1,83 @@ +#include + +#include +#include + +#include + +#include "kjarna_efi.h" + +void *efi_alloc_pool(size_t size) +{ + void *buffer; + + efi_errno = gBS->AllocatePool( + EfiLoaderData, + size, + &buffer); + + if (EFI_ERROR(efi_errno)) + { + return nullptr; + } + + return buffer; +} + +void *efi_calloc_pool(size_t count, size_t size) +{ + void *buffer = efi_alloc_pool(count * size); + + if (buffer != nullptr) + { + memset(buffer, 0, count * size); + } + + return buffer; +} + +void efi_free_pool(void *buffer) +{ + efi_errno = gBS->FreePool(buffer); +} + +#define KjarnaData EFIX_OS_MEMORY_TYPE(1) + +void *efi_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) +{ + (void)prot; + (void)flags; + (void)fd; + (void)offset; + + EFI_ALLOCATE_TYPE alloc_type = AllocateAnyPages; + EFI_MEMORY_TYPE memory_type = KjarnaData; + + void *buffer; + + if (addr != nullptr) + { + alloc_type = AllocateAddress; + } + + efi_errno = gBS->AllocatePages( + alloc_type, + memory_type, + EFI_SIZE_TO_PAGES(length), + (uintptr_t *)&buffer); + + if (EFI_ERROR(efi_errno)) + { + return nullptr; + } + + return buffer; +} + +int efi_munmap(void *addr, size_t length) +{ + efi_errno = gBS->FreePages((uintptr_t)addr, EFI_SIZE_TO_PAGES(length)); + + return !EFI_ERROR(efi_errno) ? 0 : -1; +} + diff --git a/kjarna/efi/protocol.c b/kjarna/efi/protocol.c new file mode 100644 index 0000000..e4be9cd --- /dev/null +++ b/kjarna/efi/protocol.c @@ -0,0 +1,24 @@ +#include + +#include "kjarna_efi.h" + +void *efi_get_protocol(EFI_HANDLE handle, EFI_GUID *guid) +{ + void *protocol; + + efi_errno = gBS->OpenProtocol( + handle, + guid, + &protocol, + efi_context->handle, + nullptr, + EFI_OPEN_PROTOCOL_GET_PROTOCOL); + + if (EFI_ERROR(efi_errno)) + { + return nullptr; + } + + return protocol; +} + diff --git a/kjarna/efi/runtime.c b/kjarna/efi/runtime.c new file mode 100644 index 0000000..5f2e7e1 --- /dev/null +++ b/kjarna/efi/runtime.c @@ -0,0 +1,195 @@ +#include +#include +#include +#include +#include + +#include "kjarna_efi.h" + +#include + +struct runtime_buffer +{ + char *base; + size_t length; +}; + +static ssize_t read_ehdr(int fd, Elf64_Ehdr *ehdr) +{ + ssize_t result; + + if (efi_lseek(fd, 0, SEEK_SET) == -1) + { + return -1; + } + else if ((result = efi_read(fd, ehdr, sizeof(*ehdr))) == -1) + { + return -1; + } + else if (!elf64_validate(ehdr, ET_DYN, EM_X86_64)) + { + return -1; + } + + return result; +} + +static ssize_t read_phdrs(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) +{ + if (efi_lseek(fd, ehdr->e_phoff, SEEK_SET) != -1) + { + return efi_read(fd, phdrs, ehdr->e_phnum * ehdr->e_phentsize); + } + + return -1; +} + +static void create_runtime_buffer(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, struct runtime_buffer *buffer) +{ + buffer->length = elf64_size(ehdr, phdrs); + buffer->base = efi_mmap(nullptr, buffer->length, 0, 0, -1, 0); +} + +static ssize_t load_segment(int fd, Elf64_Phdr *phdr, char *buffer) +{ + if (efi_lseek(fd, phdr->p_offset, SEEK_SET) == -1) + { + return -1; + } + + int result = efi_read(fd, &buffer[phdr->p_offset], phdr->p_filesz); + + if (result > 0 && phdr->p_memsz > phdr->p_filesz) + { + memset(&buffer[phdr->p_offset + phdr->p_filesz], 0, phdr->p_memsz - phdr->p_filesz); + } + + return result; +} + +static ssize_t load_segments(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, char *buffer) +{ + int i; + + for (i = 0; i < ehdr->e_phnum; i++) + { + if (phdrs[i].p_type != PT_LOAD) + { + continue; + } + + if (load_segment(fd, &phdrs[i], buffer) == -1) + { + return -1; + } + } + + return i; +} + +static struct runtime_buffer load_runtime(void) +{ + const char *runtime_entry_path = "\\adasoft\\sophia\\efi.os"; + + int runtime_fd; + + struct runtime_buffer buffer = { nullptr, 0 }; + + if ((runtime_fd = efi_open(runtime_entry_path, O_RDONLY, 0)) == -1) + { + return buffer; + } + + Elf64_Ehdr ehdr; + + if (read_ehdr(runtime_fd, &ehdr) == -1) + { + return buffer; + } + + Elf64_Phdr *phdrs = efi_calloc_pool(ehdr.e_phnum, ehdr.e_phentsize); + + if (phdrs == nullptr) + { + return buffer; + } + else if(read_phdrs(runtime_fd, &ehdr, phdrs) != -1) + { + create_runtime_buffer(&ehdr, phdrs, &buffer); + } + + if (buffer.base != nullptr && load_segments(runtime_fd, &ehdr, phdrs, buffer.base) == -1) + { + efi_munmap(buffer.base, buffer.length); + buffer.base = nullptr; + } + + efi_free_pool(phdrs); + + return buffer; +} + +kjarna_runtime_entry_func *runtime_entry_addr(struct runtime_buffer *buffer) +{ + if (buffer->base == nullptr) + { + return nullptr; + } + + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buffer->base; + + return (kjarna_runtime_entry_func *)(buffer->base + ehdr->e_entry); +} + +int runtime_start(void) +{ + struct kjarna_interface interface = + { + efi_open, + efi_close, + efi_lseek, + efi_read, + efi_write, + efi_mmap, + efi_munmap + }; + + struct kjarna_entry_params params = + { + &interface, + 0, + nullptr, + nullptr + }; + + struct runtime_buffer buffer = load_runtime(); + + kjarna_runtime_entry_func *runtime_entry = nullptr; + + if (buffer.base != nullptr) + { + runtime_entry = runtime_entry_addr(&buffer); + } + + if (runtime_entry != nullptr) + { + runtime_entry(¶ms); + } + + if (efi_munmap(buffer.base, buffer.length) == -1) + { + efi_write(STDOUT_FILENO, "failed unmap\r\n", -1); + + if (efi_errno == EFI_NOT_FOUND) + { + efi_write(STDOUT_FILENO, "not found\r\n", -1); + } + else + { + efi_write(STDOUT_FILENO, "bad alignment?\r\n", -1); + } + } + + return -1; +} + diff --git a/kjarna/efi/start.c b/kjarna/efi/start.c new file mode 100644 index 0000000..4a10541 --- /dev/null +++ b/kjarna/efi/start.c @@ -0,0 +1,29 @@ +#include +#include +#include +#include + +#include "../kjarna.h" +#include "kjarna_efi.h" + +struct efi_context const *efi_context; +EFI_STATUS efi_errno = EFI_SUCCESS; + +EFI_STATUS _exit(EFI_STATUS status) +{ + return gBS->Exit(efi_context->handle, status, 0, nullptr); +} + +EFI_STATUS _start(EFI_HANDLE handle, EFI_SYSTEM_TABLE *system_table) +{ + struct efi_context app_context = { handle, system_table }; + efi_context = &app_context; + + if (main(0, nullptr) != 0) + { + efi_errno = EFI_ABORTED; + } + + return _exit(efi_errno); +} + diff --git a/kjarna/file.c b/kjarna/file.c deleted file mode 100644 index 6888390..0000000 --- a/kjarna/file.c +++ /dev/null @@ -1,268 +0,0 @@ -#include -#include -#include -#include - -#include -#include -#include - -#include "kjarna_efi.h" - -#define FD_COUNT 16 -#define FD_MIN 3 -#define FD_MAX (FD_MIN + FD_COUNT - 1) - -static EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *fd_to_outconsole(int fd) -{ - switch (fd) - { - case STDOUT_FILENO: - return efi_context->system_table->ConOut; - case STDERR_FILENO: - return efi_context->system_table->StdErr; - default: - return nullptr; - } -} - -static EFI_SIMPLE_TEXT_INPUT_PROTOCOL *fd_to_inconsole(int fd) -{ - return fd == STDIN_FILENO ? efi_context->system_table->ConIn : nullptr; -} - -static EFI_FILE_PROTOCOL *open_files[FD_COUNT]; - -static EFI_FILE_PROTOCOL *fd_to_file(int fd) -{ - if (fd < FD_MIN || fd > FD_MAX) - { - return nullptr; - } - - return open_files[fd]; -} - -static int alloc_fd(void) -{ - for (int i = 0; i < FD_COUNT; i++) - { - if (open_files[i] == nullptr) - { - return FD_MIN + i; - } - } - - return -1; -} - -static void free_fd(int fd) -{ - if (fd < FD_MIN || fd > FD_MAX) - { - open_files[fd] = nullptr; - } -} - -int efi_open(const char *path, int flags, int mode) -{ - EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; - EFI_LOADED_IMAGE_PROTOCOL *lip = nullptr; - - efi_errno = gBS->OpenProtocol( - efi_context->handle, - &lip_guid, - (void **)&lip, - efi_context->handle, - nullptr, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - - if (lip == nullptr) - { - return -1; - } - - EFI_GUID sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *sfsp = nullptr; - - efi_errno = gBS->OpenProtocol( - lip->DeviceHandle, - &sfsp_guid, - (void **)&sfsp, - efi_context->handle, - nullptr, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - - if (sfsp == nullptr) - { - return -1; - } - - EFI_FILE_PROTOCOL *root = nullptr; - - efi_errno = sfsp->OpenVolume(sfsp, &root); - - if (root == nullptr) - { - return -1; - } - - int fd = alloc_fd(); - - if (fd < FD_MIN) - { - return -1; - } - - size_t path_len = strlen(path) + 1; - CHAR16 *wcpath = efi_calloc_pool(path_len, sizeof(*wcpath)); - - if(mbstowcs(wcpath, path, path_len) == (size_t)-1) - { - efi_errno = EFI_INVALID_PARAMETER; - } - else - { - efi_errno = root->Open( - root, - &open_files[fd], - wcpath, - EFI_FILE_MODE_READ, - 0); - } - - efi_free_pool(wcpath); - - (void)flags; - (void)mode; - - return !EFI_ERROR(efi_errno) ? fd : -1; -} - -int efi_close(int fd) -{ - EFI_FILE_PROTOCOL *file = fd_to_file(fd); - - if (file == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - free_fd(fd); - - efi_errno = file->Close(file); - - return !EFI_ERROR(efi_errno) ? 0 : -1; -} - -off_t efi_lseek(int fd, off_t offset, int whence) -{ - if (whence != SEEK_SET) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - EFI_FILE_PROTOCOL *file = fd_to_file(fd); - - if (file == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - efi_errno = file->SetPosition(file, (UINTN)offset); - - return !EFI_ERROR(efi_errno) ? offset : -1; -} - -static ssize_t efi_console_read(EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console, CHAR16 *buffer, size_t length) -{ - (void)console; - (void)buffer; - efi_errno = EFI_INVALID_PARAMETER; - return !EFI_ERROR(efi_errno) ? length : -1; -} - -ssize_t efi_read(int fd, void *buffer, size_t length) -{ - if (buffer == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console = fd_to_inconsole(fd); - - if (console != nullptr) - { - return efi_console_read(console, buffer, length); - } - - EFI_FILE_PROTOCOL *file = fd_to_file(fd); - - if (file == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - size_t bytes = length; - efi_errno = file->Read(file, &bytes, buffer); - - return !EFI_ERROR(efi_errno) ? bytes : -1; -} - -static ssize_t efi_console_write(EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *console, const void *buffer, size_t length) -{ - if (length == (size_t)-1) - { - length = strlen(buffer); - } - - wchar_t *ws = efi_calloc_pool(length + 1, sizeof(*ws)); - - if(mbstowcs(ws, buffer, length + 1) == (size_t)-1) - { - efi_errno = EFI_INVALID_PARAMETER; - } - else - { - efi_errno = console->OutputString(console, ws); - } - - efi_free_pool(ws); - - return !EFI_ERROR(efi_errno) ? length : -1; -} - -ssize_t efi_write(int fd, const void *buffer, size_t length) -{ - if (buffer == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - EFI_SIMPLE_TEXT_OUTPUT_PROTOCOL *console = fd_to_outconsole(fd); - - if (console != nullptr) - { - return efi_console_write(console, buffer, length); - } - - EFI_FILE_PROTOCOL *file = fd_to_file(fd); - - if (file == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - size_t bytes = length; - efi_errno = file->Write(file, &bytes, (void *)buffer); - - return !EFI_ERROR(efi_errno) ? bytes : -1; -} - diff --git a/kjarna/kjarna.h b/kjarna/kjarna.h new file mode 100644 index 0000000..d9291ca --- /dev/null +++ b/kjarna/kjarna.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +int main(int argc, char **argv); +int runtime_start(void); + diff --git a/kjarna/kjarna_efi.h b/kjarna/kjarna_efi.h deleted file mode 100644 index e24cc7f..0000000 --- a/kjarna/kjarna_efi.h +++ /dev/null @@ -1,38 +0,0 @@ -#pragma once - -#include - -#include -#include - -#include - -struct efi_context -{ - EFI_HANDLE const handle; - EFI_SYSTEM_TABLE * const system_table; -}; - -extern struct efi_context const *efi_context; -extern EFI_STATUS efi_errno; - -#define gST efi_context->system_table -#define gBS efi_context->system_table->BootServices - -void *efi_get_protocol(EFI_HANDLE handle, EFI_GUID *guid); - -int SYSV_ABI efi_open(const char *path, int flags, int mode); -int SYSV_ABI efi_close(int fd); -off_t SYSV_ABI efi_lseek(int fd, off_t offset, int whence); -ssize_t SYSV_ABI efi_read(int fd, void *buffer, size_t length); -ssize_t SYSV_ABI efi_write(int fd, const void *buffer, size_t length); - -void * SYSV_ABI efi_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); -int SYSV_ABI efi_munmap(void *addr, size_t length); - -void *efi_alloc_pool(size_t size); -void *efi_calloc_pool(size_t count, size_t size); -void efi_free_pool(void *block); - -int runtime_start(void); - diff --git a/kjarna/main.c b/kjarna/main.c index 3d34bf4..6420e83 100644 --- a/kjarna/main.c +++ b/kjarna/main.c @@ -1,6 +1,9 @@ -#include "kjarna_efi.h" +#include "kjarna.h" int main(int argc, char **argv) { + (void)argc; + (void)argv; + return runtime_start(); } diff --git a/kjarna/memory.c b/kjarna/memory.c deleted file mode 100644 index 7fbb4a8..0000000 --- a/kjarna/memory.c +++ /dev/null @@ -1,83 +0,0 @@ -#include - -#include -#include - -#include - -#include "kjarna_efi.h" - -void *efi_alloc_pool(size_t size) -{ - void *buffer; - - efi_errno = gBS->AllocatePool( - EfiLoaderData, - size, - &buffer); - - if (EFI_ERROR(efi_errno)) - { - return nullptr; - } - - return buffer; -} - -void *efi_calloc_pool(size_t count, size_t size) -{ - void *buffer = efi_alloc_pool(count * size); - - if (buffer != nullptr) - { - memset(buffer, 0, count * size); - } - - return buffer; -} - -void efi_free_pool(void *buffer) -{ - efi_errno = gBS->FreePool(buffer); -} - -#define KjarnaData EFIX_OS_MEMORY_TYPE(1) - -void *efi_mmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset) -{ - (void)prot; - (void)flags; - (void)fd; - (void)offset; - - EFI_ALLOCATE_TYPE alloc_type = AllocateAnyPages; - EFI_MEMORY_TYPE memory_type = KjarnaData; - - void *buffer; - - if (addr != nullptr) - { - alloc_type = AllocateAddress; - } - - efi_errno = gBS->AllocatePages( - alloc_type, - memory_type, - EFI_SIZE_TO_PAGES(length), - (uintptr_t *)&buffer); - - if (EFI_ERROR(efi_errno)) - { - return nullptr; - } - - return buffer; -} - -int efi_munmap(void *addr, size_t length) -{ - efi_errno = gBS->FreePages((uintptr_t)addr, EFI_SIZE_TO_PAGES(length)); - - return !EFI_ERROR(efi_errno) ? 0 : -1; -} - diff --git a/kjarna/protocol.c b/kjarna/protocol.c deleted file mode 100644 index e4be9cd..0000000 --- a/kjarna/protocol.c +++ /dev/null @@ -1,24 +0,0 @@ -#include - -#include "kjarna_efi.h" - -void *efi_get_protocol(EFI_HANDLE handle, EFI_GUID *guid) -{ - void *protocol; - - efi_errno = gBS->OpenProtocol( - handle, - guid, - &protocol, - efi_context->handle, - nullptr, - EFI_OPEN_PROTOCOL_GET_PROTOCOL); - - if (EFI_ERROR(efi_errno)) - { - return nullptr; - } - - return protocol; -} - diff --git a/kjarna/runtime.c b/kjarna/runtime.c deleted file mode 100644 index 5f2e7e1..0000000 --- a/kjarna/runtime.c +++ /dev/null @@ -1,195 +0,0 @@ -#include -#include -#include -#include -#include - -#include "kjarna_efi.h" - -#include - -struct runtime_buffer -{ - char *base; - size_t length; -}; - -static ssize_t read_ehdr(int fd, Elf64_Ehdr *ehdr) -{ - ssize_t result; - - if (efi_lseek(fd, 0, SEEK_SET) == -1) - { - return -1; - } - else if ((result = efi_read(fd, ehdr, sizeof(*ehdr))) == -1) - { - return -1; - } - else if (!elf64_validate(ehdr, ET_DYN, EM_X86_64)) - { - return -1; - } - - return result; -} - -static ssize_t read_phdrs(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) -{ - if (efi_lseek(fd, ehdr->e_phoff, SEEK_SET) != -1) - { - return efi_read(fd, phdrs, ehdr->e_phnum * ehdr->e_phentsize); - } - - return -1; -} - -static void create_runtime_buffer(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, struct runtime_buffer *buffer) -{ - buffer->length = elf64_size(ehdr, phdrs); - buffer->base = efi_mmap(nullptr, buffer->length, 0, 0, -1, 0); -} - -static ssize_t load_segment(int fd, Elf64_Phdr *phdr, char *buffer) -{ - if (efi_lseek(fd, phdr->p_offset, SEEK_SET) == -1) - { - return -1; - } - - int result = efi_read(fd, &buffer[phdr->p_offset], phdr->p_filesz); - - if (result > 0 && phdr->p_memsz > phdr->p_filesz) - { - memset(&buffer[phdr->p_offset + phdr->p_filesz], 0, phdr->p_memsz - phdr->p_filesz); - } - - return result; -} - -static ssize_t load_segments(int fd, Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, char *buffer) -{ - int i; - - for (i = 0; i < ehdr->e_phnum; i++) - { - if (phdrs[i].p_type != PT_LOAD) - { - continue; - } - - if (load_segment(fd, &phdrs[i], buffer) == -1) - { - return -1; - } - } - - return i; -} - -static struct runtime_buffer load_runtime(void) -{ - const char *runtime_entry_path = "\\adasoft\\sophia\\efi.os"; - - int runtime_fd; - - struct runtime_buffer buffer = { nullptr, 0 }; - - if ((runtime_fd = efi_open(runtime_entry_path, O_RDONLY, 0)) == -1) - { - return buffer; - } - - Elf64_Ehdr ehdr; - - if (read_ehdr(runtime_fd, &ehdr) == -1) - { - return buffer; - } - - Elf64_Phdr *phdrs = efi_calloc_pool(ehdr.e_phnum, ehdr.e_phentsize); - - if (phdrs == nullptr) - { - return buffer; - } - else if(read_phdrs(runtime_fd, &ehdr, phdrs) != -1) - { - create_runtime_buffer(&ehdr, phdrs, &buffer); - } - - if (buffer.base != nullptr && load_segments(runtime_fd, &ehdr, phdrs, buffer.base) == -1) - { - efi_munmap(buffer.base, buffer.length); - buffer.base = nullptr; - } - - efi_free_pool(phdrs); - - return buffer; -} - -kjarna_runtime_entry_func *runtime_entry_addr(struct runtime_buffer *buffer) -{ - if (buffer->base == nullptr) - { - return nullptr; - } - - Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buffer->base; - - return (kjarna_runtime_entry_func *)(buffer->base + ehdr->e_entry); -} - -int runtime_start(void) -{ - struct kjarna_interface interface = - { - efi_open, - efi_close, - efi_lseek, - efi_read, - efi_write, - efi_mmap, - efi_munmap - }; - - struct kjarna_entry_params params = - { - &interface, - 0, - nullptr, - nullptr - }; - - struct runtime_buffer buffer = load_runtime(); - - kjarna_runtime_entry_func *runtime_entry = nullptr; - - if (buffer.base != nullptr) - { - runtime_entry = runtime_entry_addr(&buffer); - } - - if (runtime_entry != nullptr) - { - runtime_entry(¶ms); - } - - if (efi_munmap(buffer.base, buffer.length) == -1) - { - efi_write(STDOUT_FILENO, "failed unmap\r\n", -1); - - if (efi_errno == EFI_NOT_FOUND) - { - efi_write(STDOUT_FILENO, "not found\r\n", -1); - } - else - { - efi_write(STDOUT_FILENO, "bad alignment?\r\n", -1); - } - } - - return -1; -} - diff --git a/kjarna/start.c b/kjarna/start.c deleted file mode 100644 index 6a737b3..0000000 --- a/kjarna/start.c +++ /dev/null @@ -1,30 +0,0 @@ -#include -#include -#include -#include - -#include "kjarna_efi.h" - -struct efi_context const *efi_context; -EFI_STATUS efi_errno = EFI_SUCCESS; - -EFI_STATUS _exit(EFI_STATUS status) -{ - return gBS->Exit(efi_context->handle, status, 0, nullptr); -} - -EFI_STATUS _start(EFI_HANDLE handle, EFI_SYSTEM_TABLE *system_table) -{ - struct efi_context app_context = { handle, system_table }; - efi_context = &app_context; - - int runtime_result = runtime_start(); - - if (runtime_result < 0) - { - efi_errno = EFI_ABORTED; - } - - return _exit(efi_errno); -} - -- cgit v1.3.1-1-g115d