summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--api/kernel/component.h10
-rw-r--r--api/kernel/entry.h6
-rw-r--r--api/loader/efi/shim.h4
-rw-r--r--kernel/Makefile7
-rw-r--r--kernel/entry.c (renamed from kernel/entry_efi.c)0
-rw-r--r--lib/component.ld75
-rw-r--r--lib/elf.c106
-rw-r--r--lib/elf64.c45
-rw-r--r--lib/entry_x86_64.S18
-rw-r--r--lib/reloc_x86_64.c69
-rw-r--r--loader/Makefile3
-rw-r--r--loader/main_efi.c19
-rw-r--r--shim/Makefile5
-rw-r--r--shim/kc_main.c (renamed from shim/entry.c)32
-rw-r--r--shim/shim.ld49
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)
- }
-}
-