diff options
| -rw-r--r-- | api/kernel/component.h | 10 | ||||
| -rw-r--r-- | api/kernel/entry.h | 6 | ||||
| -rw-r--r-- | api/loader/efi/shim.h | 4 | ||||
| -rw-r--r-- | kernel/Makefile | 7 | ||||
| -rw-r--r-- | kernel/entry.c (renamed from kernel/entry_efi.c) | 0 | ||||
| -rw-r--r-- | lib/component.ld | 75 | ||||
| -rw-r--r-- | lib/elf.c | 106 | ||||
| -rw-r--r-- | lib/elf64.c | 45 | ||||
| -rw-r--r-- | lib/entry_x86_64.S | 18 | ||||
| -rw-r--r-- | lib/reloc_x86_64.c | 69 | ||||
| -rw-r--r-- | loader/Makefile | 3 | ||||
| -rw-r--r-- | loader/main_efi.c | 19 | ||||
| -rw-r--r-- | shim/Makefile | 5 | ||||
| -rw-r--r-- | shim/kc_main.c (renamed from shim/entry.c) | 32 | ||||
| -rw-r--r-- | shim/shim.ld | 49 |
15 files changed, 246 insertions, 202 deletions
diff --git a/api/kernel/component.h b/api/kernel/component.h new file mode 100644 index 0000000..d795283 --- /dev/null +++ b/api/kernel/component.h @@ -0,0 +1,10 @@ +#pragma once + +extern char kc_image_base; +extern char kc_text_begin; +extern char kc_text_end; +extern char kc_rodata_begin; +extern char kc_rodata_end; +extern char kc_data_begin; +extern char kc_data_end; + diff --git a/api/kernel/entry.h b/api/kernel/entry.h index d119ca1..d1a6ee0 100644 --- a/api/kernel/entry.h +++ b/api/kernel/entry.h @@ -1,8 +1,4 @@ #pragma once -#define KERNEL_ENTRY_STACK_SIZE 0x4000 -#define KERNEL_ENTRY_STACK_HEAD (void *)0xffffffffff000000 -#define KERNEL_ENTRY_STACK_BASE ((char *)KERNEL_ENTRY_STACK_HEAD - KERNEL_ENTRY_STACK_SIZE) - -typedef void (*kernel_entry_func)(void *data); +typedef int (*kc_entry_func)(void *parameters); diff --git a/api/loader/efi/shim.h b/api/loader/efi/shim.h index 9421cc3..0255361 100644 --- a/api/loader/efi/shim.h +++ b/api/loader/efi/shim.h @@ -16,7 +16,6 @@ struct efi_loader_image { CHAR16 *path; - EFI_HANDLE image_handle; EFI_SYSTEM_TABLE *system_table; EFI_FILE_PROTOCOL *root; EFI_FILE_PROTOCOL *file; @@ -32,6 +31,9 @@ typedef EFI_STATUS (*efi_page_free_func)(EFI_PHYSICAL_ADDRESS base, UINTN size); struct efi_loader_interface { + EFI_HANDLE image_handle; + EFI_SYSTEM_TABLE *system_table; + efi_page_alloc_func page_alloc; efi_page_free_func page_free; diff --git a/kernel/Makefile b/kernel/Makefile index 7caf69c..407c4bb 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -5,11 +5,6 @@ VPATH := ../lib TARGET := kernel.os .DEFAULT: $(TARGET) -# EFI API for temporary things - -EFIAPIDIR := /usr/local/include/efi - -CPPFLAGS += -I../api -I$(EFIAPIDIR) -I$(EFIAPIDIR)/$(ARCH) -I$(EFIAPIDIR)/protocol CFLAGS += -Wno-unused-const-variable -Wno-unused-function -fvisibility=hidden -g LIBDIRS += -L$(dir $(shell $(CC) -print-libgcc-file-name)) @@ -18,7 +13,7 @@ LDFLAGS += -z max-page-size=4096 --export-dynamic LOADLIBES := -lgcc SOBJS := -GOBJS := entry_efi.o kprint.o serial.o port.o main.o memory.o \ +GOBJS := entry.o kprint.o serial.o port.o main.o memory.o \ memset.o memcpy.o memmove.o memcmp.o cpu.o exceptions.o \ panic.o IOBJS := diff --git a/kernel/entry_efi.c b/kernel/entry.c index 5eecaf2..5eecaf2 100644 --- a/kernel/entry_efi.c +++ b/kernel/entry.c diff --git a/lib/component.ld b/lib/component.ld new file mode 100644 index 0000000..3a48ae8 --- /dev/null +++ b/lib/component.ld @@ -0,0 +1,75 @@ +ENTRY(kc_entry) + +SECTIONS +{ + PROVIDE(kc_image_base = .); + + . = sizeof_headers; + + .rel : + { + *(.rel) + *(.rel.*) + } + + .rela : + { + *(.rel) + *(.rela.*) + } + + .hash : + { + *(.hash) + } + + .dynsym : + { + *(.dynsym) + } + + .dynstr : + { + *(.dynstr) + } + + .text : ALIGN(4K) + { + PROVIDE(kc_text_begin = .); + *(.text.start) + *(.text) + . = ALIGN(4K); + PROVIDE(kc_text_end = .); + } =0xcc + + .dynamic : ALIGN(4K) + { + *(.dynamic) + } + + .data : + { + PROVIDE(kc_data_begin = .); + *(.rodata) + *(.data) + } + + .data.rel : + { + *(.data.rel) + *(.data.rel.*) + } + + .bss : + { + *(.bss) + PROVIDE(kc_data_end = .); + } + + /DISCARD/ : + { + *(.eh_frame) + *(.comment) + } +} + diff --git a/lib/elf.c b/lib/elf.c deleted file mode 100644 index 551a5a5..0000000 --- a/lib/elf.c +++ /dev/null @@ -1,106 +0,0 @@ -#include "elf.h" - -bool elf64_validate(Elf64_Ehdr *ehdr, unsigned type, unsigned machine) -{ - 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 != machine || - ehdr->e_type != type) - { - return false; - } - - return true; -} - -size_t elf64_size(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) -{ - size_t size = 0; - - for (int i = 0; i < 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; -} - -void elf64_reloc(Elf64_Ehdr *ehdr) -{ - // locate the dynamic segment - Elf64_Phdr *phdrs = (Elf64_Phdr *)(ehdr->e_phoff + (uintptr_t)ehdr); - Elf64_Dyn *dyn = NULL; - Elf64_Rela *rela = NULL; - size_t rela_size; - int rela_count; - - for (int i = 0; i < ehdr->e_phnum; i++) - { - if (phdrs[i].p_type != PT_DYNAMIC) continue; - - dyn = (Elf64_Dyn *)(phdrs[i].p_offset + (uintptr_t)ehdr); - } - - // parse the dynamic segment - while (dyn->d_tag != DT_NULL) - { - switch (dyn->d_tag) - { - case DT_RELA: - rela = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)ehdr); - break; - case DT_RELASZ: - rela_size = dyn->d_val; - break; - case DT_RELAENT: - rela_count = rela_size / dyn->d_val; - break; - default: - break; - } - dyn++; - } - - // perform the actual relocations - - for (int i; i < rela_count; i++) - { - union - { - Elf_Byte word8; - Elf64_Half word16; - Elf64_Word word32; - Elf64_Xword word64; - } - *reloc_ptr = NULL; - - switch (ELF64_R_TYPE(rela[i].r_info)) - { - case R_AMD64_RELATIVE: - reloc_ptr = (void *)(rela[i].r_offset + (uintptr_t)ehdr); - reloc_ptr->word64 = (rela[i].r_addend + (uintptr_t)ehdr); - break; - default: - break; - } - } -} - diff --git a/lib/elf64.c b/lib/elf64.c new file mode 100644 index 0000000..2dee395 --- /dev/null +++ b/lib/elf64.c @@ -0,0 +1,45 @@ +#include "elf.h" + +bool elf64_validate(Elf64_Ehdr *ehdr, unsigned type, unsigned machine) +{ + 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 != machine || + ehdr->e_type != type) + { + return false; + } + + return true; +} + +size_t elf64_size(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs) +{ + size_t size = 0; + + for (int i = 0; i < ehdr->e_phnum; i++) + { + if (phdrs[i].p_type != PT_LOAD) + { + continue; + } + + if (phdrs[i].p_offset + phdrs[i].p_memsz > size) + { + size = phdrs[i].p_offset + phdrs[i].p_memsz; + if (phdrs[i].p_align > 1) + { + size = (size + phdrs[i].p_align - 1) & + ~(phdrs[i].p_align - 1); + } + } + } + + return size; +} + diff --git a/lib/entry_x86_64.S b/lib/entry_x86_64.S new file mode 100644 index 0000000..231953a --- /dev/null +++ b/lib/entry_x86_64.S @@ -0,0 +1,18 @@ +.section .text.start +.extern kc_reloc +.extern kc_main +.extern _DYNAMIC +.extern kc_image_base + +.global kc_entry +.type kc_entry, @function +kc_entry: + push %rdi + lea _DYNAMIC(%rip), %rdi + lea kc_image_base(%rip), %rsi + call kc_reloc + pop %rdi + call kc_main + ret +.size kc_entry, . - kc_entry + diff --git a/lib/reloc_x86_64.c b/lib/reloc_x86_64.c new file mode 100644 index 0000000..0204700 --- /dev/null +++ b/lib/reloc_x86_64.c @@ -0,0 +1,69 @@ +#include <kernel/component.h> + +#include <elf/elf64.h> + +#include <stddef.h> + +#define STARTCODE __attribute__((section(".text.start"))) + +STARTCODE +static void do_rela(Elf64_Rela *rela, void *base) +{ + union + { + Elf_Byte word8; + Elf64_Half word16; + Elf64_Word word32; + Elf64_Xword word64; + } + *fixup; + + switch (ELF64_R_TYPE(rela->r_info)) + { + case R_AMD64_RELATIVE: + fixup = (void *)(rela->r_offset + (uintptr_t)base); + fixup->word64 = (rela->r_addend + (uintptr_t)base); + break; + default: + break; + } +} + +STARTCODE +void kc_reloc(Elf64_Dyn *dyn, void *base) +{ + struct + { + Elf64_Rela *entries; + size_t *size; + size_t *entsize; + } + rela = {NULL, NULL, NULL}; + + // parse the dynamic segment + while (dyn && dyn++->d_tag != DT_NULL) + { + switch (dyn->d_tag) + { + case DT_RELA: + rela.entries = (Elf64_Rela *)(dyn->d_ptr + (uintptr_t)base); + break; + case DT_RELASZ: + rela.size = &dyn->d_val; + break; + case DT_RELAENT: + rela.entsize = &dyn->d_val; + break; + default: + break; + } + } + + // perform the actual relocation + + for (size_t i = 0; rela.entries && (i < *rela.size / *rela.entsize); i++) + { + do_rela(&rela.entries[i], base); + } +} + diff --git a/loader/Makefile b/loader/Makefile index dd8c21c..ab7f970 100644 --- a/loader/Makefile +++ b/loader/Makefile @@ -10,8 +10,7 @@ CPPFLAGS += -I../api all: $(BUILD) -OBJS := main_efi.o elf.o \ - memcmp.o memmove.o +OBJS := main_efi.o elf64.o memcmp.o memmove.o DEPS := $(OBJS:.o=.d) IMAGE_SO := $(IMAGE:.efi=_efi.so) diff --git a/loader/main_efi.c b/loader/main_efi.c index 4c9c9a0..37802cb 100644 --- a/loader/main_efi.c +++ b/loader/main_efi.c @@ -1,5 +1,7 @@ #include <loader/efi/shim.h> +#include <kernel/entry.h> + #include <efi.h> #include <efidebug.h> #include <efilib.h> @@ -24,9 +26,10 @@ static struct efi_loader_image shim_image = static struct efi_loader_interface loader_interface = { + NULL, + NULL, &alloc_page, &free_page, - &open_image, &allocate_image, &load_image @@ -35,8 +38,8 @@ static struct efi_loader_interface loader_interface = EFI_STATUS efi_main(EFI_HANDLE image_handle, EFI_SYSTEM_TABLE *system_table) { InitializeLib(image_handle, system_table); - - shim_image.image_handle = image_handle; + loader_interface.image_handle = image_handle; + loader_interface.system_table = system_table; EFI_STATUS status; @@ -102,10 +105,10 @@ EFI_STATUS open_image(struct efi_loader_image *image) EFI_STATUS status; - status = gBS->OpenProtocol(image->image_handle, + status = gBS->OpenProtocol(loader_interface.image_handle, &LoadedImageProtocol, (void *)&loader_image, - image->image_handle, + loader_interface.image_handle, NULL, EFI_OPEN_PROTOCOL_GET_PROTOCOL); @@ -269,10 +272,10 @@ static EFI_STATUS enter_shim(void) { EFI_STATUS status; Elf64_Ehdr *ehdr = (Elf64_Ehdr *)shim_image.buffer_base; - efi_shim_entry_func entry; + kc_entry_func entry; - entry = (efi_shim_entry_func)(shim_image.buffer_base + ehdr->e_entry); - status = entry(&shim_image, &loader_interface); + entry = (kc_entry_func)(shim_image.buffer_base + ehdr->e_entry); + status = entry(&loader_interface); return status; } diff --git a/shim/Makefile b/shim/Makefile index 42007b8..7183088 100644 --- a/shim/Makefile +++ b/shim/Makefile @@ -14,11 +14,12 @@ CFLAGS += -Wno-unused-const-variable -Wno-unused-function -fvisibility=hidden \ -g -fshort-wchar -mgeneral-regs-only LIBDIRS += -L$(dir $(shell $(CC) -print-libgcc-file-name)) -LDSCRIPT := shim.ld +LDSCRIPT := ../lib/component.ld LDFLAGS += -z max-page-size=4096 --export-dynamic -pic --no-dynamic-linker LOADLIBES := -lgcc -OBJS := entry.o elf.o memcmp.o memcpy.o memmove.o memset.o +OBJS := entry_x86_64.o reloc_x86_64.o kc_main.o elf64.o memcmp.o memcpy.o \ + memmove.o memset.o $(OBJS): CFLAGS += -fPIC DEPS := $(patsubst %.o,%.d,$(OBJS)) diff --git a/shim/entry.c b/shim/kc_main.c index a4d00c7..1829616 100644 --- a/shim/entry.c +++ b/shim/kc_main.c @@ -37,38 +37,24 @@ struct efi_loader_image kernel_image = .path = L"\\adasoft\\sophia\\kernel.os" }; -static struct efi_loader_image *shim_image; static struct efi_boot_data boot_data; -EFI_STATUS efi_shim_entry(struct efi_loader_image *image, - struct efi_loader_interface *interface) -{ - /* 1. load kernel and boot modules into memory - * 2. generate page tables for kernel and boot modules - * 2. gather boot data, store as type SystemMemoryType - * 3. exit boot services - * 5. ??????????? - */ - - void *image_base = (void *)image->buffer_base; +// TODO: split relocation code out into library - elf_reloc(image_base); +EFI_STATUS kc_main(struct efi_loader_interface *interface) +{ + // 1. load kernel and boot modules into memory + // 2. generate page tables for kernel and boot modules + // 2. gather boot data, store as type SystemMemoryType + // 3. exit boot services + // 5. ??????????? EFI_STATUS status; - if (!image) + if (!interface) { return EFI_INVALID_PARAMETER; } - else if (!shim_image) - { - shim_image = image; - kernel_image.image_handle = shim_image->image_handle; - } - else - { - return EFI_ALREADY_STARTED; - } if (!EFI_ERROR((status = interface->image_open(&kernel_image))) && !EFI_ERROR((status = interface->image_alloc(&kernel_image))) && diff --git a/shim/shim.ld b/shim/shim.ld deleted file mode 100644 index f0643ca..0000000 --- a/shim/shim.ld +++ /dev/null @@ -1,49 +0,0 @@ -ENTRY(efi_shim_entry) - -SECTIONS -{ - . = sizeof_headers; - - .rel : - { - *(.rel.*) - } - - .rela : - { - *(.rela.*) - } - - .text : ALIGN(4K) - { - PROVIDE(_text_begin = .); - *(.text) - . = ALIGN(4K); - PROVIDE(_text_end = .); - } =0xcc - - .data : - { - PROVIDE(_data_begin = .); - *(.rodata) - *(.data) - } - - .data.rel : - { - *(.data.rel) - *(.data.rel.*) - } - - .bss : - { - *(.bss) - PROVIDE(_data_end = .); - } - - /DISCARD/ : - { - *(.eh_frame) - } -} - |
