From f61da8be06fdfebc598cba783e78117319231140 Mon Sep 17 00:00:00 2001 From: Ada Christine Date: Sun, 3 Mar 2024 08:44:42 +0000 Subject: build changes --- boot/Makefile | 37 ++++++ boot/efi/config.h | 4 + boot/efi/file.c | 286 ++++++++++++++++++++++++++++++++++++++++ boot/efi/image.c | 198 ++++++++++++++++++++++++++++ boot/efi/kjarna_efi.h | 37 ++++++ boot/efi/memory.c | 83 ++++++++++++ boot/efi/protocol.c | 33 +++++ boot/efi/start.c | 32 +++++ boot/kjarna.h | 7 + boot/main.c | 9 ++ debug.sh | 42 +++--- kjarna/Makefile | 37 ------ kjarna/efi/file.c | 274 -------------------------------------- kjarna/efi/image.c | 196 --------------------------- kjarna/efi/kjarna_efi.h | 37 ------ kjarna/efi/memory.c | 83 ------------ kjarna/efi/protocol.c | 33 ----- kjarna/efi/start.c | 32 ----- kjarna/kjarna.h | 7 - kjarna/main.c | 9 -- kjarna_runtime/Makefile | 37 ------ kjarna_runtime/dynamic_x86_64.c | 139 ------------------- kjarna_runtime/kc.h | 46 ------- kjarna_runtime/kc.ld | 97 -------------- kjarna_runtime/kjarna.c | 13 -- kjarna_runtime/main.c | 17 --- kjarna_runtime/start_x86_64.S | 63 --------- service/Makefile | 37 ++++++ service/dynamic_x86_64.c | 139 +++++++++++++++++++ service/kc.h | 46 +++++++ service/kc.ld | 97 ++++++++++++++ service/kjarna.c | 13 ++ service/main.c | 17 +++ service/start_x86_64.S | 63 +++++++++ 34 files changed, 1165 insertions(+), 1135 deletions(-) create mode 100644 boot/Makefile create mode 100644 boot/efi/config.h create mode 100644 boot/efi/file.c create mode 100644 boot/efi/image.c create mode 100644 boot/efi/kjarna_efi.h create mode 100644 boot/efi/memory.c create mode 100644 boot/efi/protocol.c create mode 100644 boot/efi/start.c create mode 100644 boot/kjarna.h create mode 100644 boot/main.c delete mode 100644 kjarna/Makefile delete mode 100644 kjarna/efi/file.c delete mode 100644 kjarna/efi/image.c delete mode 100644 kjarna/efi/kjarna_efi.h delete mode 100644 kjarna/efi/memory.c delete mode 100644 kjarna/efi/protocol.c delete mode 100644 kjarna/efi/start.c delete mode 100644 kjarna/kjarna.h delete mode 100644 kjarna/main.c delete mode 100644 kjarna_runtime/Makefile delete mode 100644 kjarna_runtime/dynamic_x86_64.c delete mode 100644 kjarna_runtime/kc.h delete mode 100644 kjarna_runtime/kc.ld delete mode 100644 kjarna_runtime/kjarna.c delete mode 100644 kjarna_runtime/main.c delete mode 100644 kjarna_runtime/start_x86_64.S create mode 100644 service/Makefile create mode 100644 service/dynamic_x86_64.c create mode 100644 service/kc.h create mode 100644 service/kc.ld create mode 100644 service/kjarna.c create mode 100644 service/main.c create mode 100644 service/start_x86_64.S diff --git a/boot/Makefile b/boot/Makefile new file mode 100644 index 0000000..482744f --- /dev/null +++ b/boot/Makefile @@ -0,0 +1,37 @@ +include ../defaults.mk + +%.efi: + $(CC.info) + @$(CC) $(LDFLAGS) -o $@ $^ + +VPATH := ../lib efi/ + +IMAGE := kjarna.efi + +CPPFLAGS += -I../api -I../lib + +CFLAGS += --target=$(ARCH)-unknown-windows -fshort-wchar -mno-avx \ + -mno-sse -mno-mmx -funsigned-char -Wno-pointer-sign -ggdb \ + -fno-ms-extensions + +LDFLAGS := --target=$(ARCH)-unknown-windows -nostdlib -ggdb \ + -Wl,-entry:_start,-subsystem:efi_application -fuse-ld=lld-link + +all: $(IMAGE) + +CRT_OBJS := start.o +LIB_OBJS := memcmp.o memset.o memcpy.o memmove.o string.o elf64.o +EFI_OBJS := file.o memory.o protocol.o image.o +APP_OBJS := main.o + +OBJS := $(CRT_OBJS) $(LIB_OBJS) $(EFI_OBJS) $(APP_OBJS) +DEPS := $(OBJS:.o=.d) + +$(IMAGE): $(OBJS) + +CLEANLIST := $(wildcard $(BUILD) $(OBJS) $(IMAGE) $(IMAGE:.efi=.pdb)) +DCLEANLIST := $(CLEANLIST) $(wildcard $(DEPS)) + +include ../rules.mk +-include $(DEPS) + diff --git a/boot/efi/config.h b/boot/efi/config.h new file mode 100644 index 0000000..ae55f21 --- /dev/null +++ b/boot/efi/config.h @@ -0,0 +1,4 @@ +#pragma once + +#define SERVICE_FILE_PATH "/service/kjarna/kjarna.os" + diff --git a/boot/efi/file.c b/boot/efi/file.c new file mode 100644 index 0000000..9178654 --- /dev/null +++ b/boot/efi/file.c @@ -0,0 +1,286 @@ +#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; + } +} + +CHAR16 *swap_path_separator(CHAR16 *path) +{ + for (CHAR16 *r = path; *r != '\0'; r++) + { + *r = *r == L'/' ? '\\' : *r; + } + + return path; +} + +int efi_open(const char *path, int flags, int mode) +{ + static EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; + static EFI_GUID sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; + + EFI_LOADED_IMAGE_PROTOCOL *lip = efi_get_protocol(efi_context->handle, &lip_guid); + + if (lip == nullptr) + { + return -1; + } + + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *sfsp = efi_get_protocol(lip->DeviceHandle, &sfsp_guid); + + 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 + { + wcpath = swap_path_separator(wcpath); + + efi_errno = root->Open( + root, + &open_files[fd], + wcpath, + EFI_FILE_MODE_READ, + 0); + } + + efi_close_protocol(lip->DeviceHandle, &lip_guid); + efi_close_protocol(efi_context->handle, &sfsp_guid); + 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) +{ + EFI_FILE_PROTOCOL *file = fd_to_file(fd); + + if (file == nullptr) + { + efi_errno = EFI_INVALID_PARAMETER; + return -1; + } + + off_t current = 0; + + if (whence == SEEK_END) + { + efi_errno = file->SetPosition(file, (UINTN)-1); + } + + if (EFI_ERROR(efi_errno)) + { + return -1; + } + + if (whence == SEEK_CUR || whence == SEEK_END) + { + efi_errno = file->GetPosition(file, (UINTN *)¤t); + } + + if (EFI_ERROR(efi_errno)) + { + return -1; + } + + efi_errno = file->SetPosition(file, (UINTN)(offset + current)); + + return !EFI_ERROR(efi_errno) ? offset : -1; +} + +static ssize_t efi_console_read(EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console, CHAR16 *buffer, size_t length) +{ + //TODO: implement user input + (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 + 2, sizeof(*ws)); + + if(mbstowcs(ws, buffer, length + 2) == (size_t)-1) + { + efi_errno = EFI_INVALID_PARAMETER; + } + else + { + if (ws[length - 1] == L'\n') + ws[length] = L'\r'; + 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/boot/efi/image.c b/boot/efi/image.c new file mode 100644 index 0000000..42dab7d --- /dev/null +++ b/boot/efi/image.c @@ -0,0 +1,198 @@ +#include +#include +#include +#include +#include + +#include "kjarna_efi.h" + +#include "config.h" + +#include + +struct image_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_image_buffer(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, struct image_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 image_buffer load_image(void) +{ + const char *image_entry_path = SERVICE_FILE_PATH; + + int image_fd; + + struct image_buffer buffer = { nullptr, 0 }; + + if ((image_fd = efi_open(image_entry_path, O_RDONLY, 0)) == -1) + { + return buffer; + } + + Elf64_Ehdr ehdr; + + if (read_ehdr(image_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(image_fd, &ehdr, phdrs) != -1) + { + create_image_buffer(&ehdr, phdrs, &buffer); + } + + if (buffer.base != nullptr && load_segments(image_fd, &ehdr, phdrs, buffer.base) == -1) + { + efi_munmap(buffer.base, buffer.length); + buffer.base = nullptr; + } + + efi_close(image_fd); + efi_free_pool(phdrs); + + return buffer; +} + +kjarna_image_entry_func *image_entry_addr(struct image_buffer *buffer) +{ + if (buffer->base == nullptr) + { + return nullptr; + } + + Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buffer->base; + + return (kjarna_image_entry_func *)(buffer->base + ehdr->e_entry); +} + +int image_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 image_buffer buffer = load_image(); + + kjarna_image_entry_func *image_entry = nullptr; + + if (buffer.base != nullptr) + { + image_entry = image_entry_addr(&buffer); + } + + if (image_entry != nullptr) + { + image_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/boot/efi/kjarna_efi.h b/boot/efi/kjarna_efi.h new file mode 100644 index 0000000..ea9d3f1 --- /dev/null +++ b/boot/efi/kjarna_efi.h @@ -0,0 +1,37 @@ +#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); +void efi_close_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/boot/efi/memory.c b/boot/efi/memory.c new file mode 100644 index 0000000..7fbb4a8 --- /dev/null +++ b/boot/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/boot/efi/protocol.c b/boot/efi/protocol.c new file mode 100644 index 0000000..6bf8123 --- /dev/null +++ b/boot/efi/protocol.c @@ -0,0 +1,33 @@ +#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; +} + +void efi_close_protocol(EFI_HANDLE handle, EFI_GUID *guid) +{ + efi_errno = gBS->CloseProtocol( + handle, + guid, + efi_context->handle, + nullptr); +} + diff --git a/boot/efi/start.c b/boot/efi/start.c new file mode 100644 index 0000000..8ef8cbe --- /dev/null +++ b/boot/efi/start.c @@ -0,0 +1,32 @@ +#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; + + system_table->ConOut->ClearScreen(system_table->ConOut); + + if (main(0, nullptr) != 0) + { + efi_errno = EFI_ABORTED; + } + + + return _exit(efi_errno); +} + diff --git a/boot/kjarna.h b/boot/kjarna.h new file mode 100644 index 0000000..81bb79b --- /dev/null +++ b/boot/kjarna.h @@ -0,0 +1,7 @@ +#pragma once + +#include + +int main(int argc, char **argv); +int image_start(void); + diff --git a/boot/main.c b/boot/main.c new file mode 100644 index 0000000..38c913f --- /dev/null +++ b/boot/main.c @@ -0,0 +1,9 @@ +#include "kjarna.h" + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + return image_start(); +} + diff --git a/debug.sh b/debug.sh index 34f01dd..7618ba6 100755 --- a/debug.sh +++ b/debug.sh @@ -1,30 +1,42 @@ #!/usr/bin/env bash -make -C kjarna_runtime && -make -C kjarna && +BOOT_DIR=boot +BOOT_FILE=${BOOT_DIR}/kjarna.efi -BOOT_DIR=EFI/BOOT -BOOT_FILE=BOOTX64.EFI -SYS_DIR=adasoft/sophia -OVMF_DIR=/usr/share/ovmf/x64 +SERVICE_DIR=service +SERVICE_FILE=${SERVICE_DIR}/kjarna.os -LOADER_FILE=kjarna/kjarna.efi -SHIM_FILE=kjarna_runtime/kjarna.os +FIRMWARE_DIR=/usr/share/ovmf/x64 +FIRMWARE_FILE=${FIRMWARE_DIR}/OVMF_CODE.fd +FIRMWARE_VARS=${FIRMWARE_DIR}/OVMF_VARS.fd -KERNEL_FILE=kc/core/kernel.os +INSTALL_PREFIX=adasoft/sophia + +make -C ${SERVICE_DIR} && +make -C ${BOOT_DIR} && tempdir=$(mktemp -d) && -rundir=${tempdir}/run && +rundir=${tempdir}/run + +varsfile=${tempdir}/$(basename ${FIRMWARE_VARS}) + +efidir=${rundir}/efi +efibootdir=${efidir}/boot +bootdir=${efidir}/adasoft/kjarna +bootfile=${efibootdir}/BOOTX64.EFI +servdir=${rundir}/service/kjarna -cp ${OVMF_DIR}/OVMF_VARS.fd ${tempdir} && +mkdir -p ${efidir} ${efibootdir} && +mkdir -p ${bootdir} ${servdir} && -mkdir -p ${rundir}/${BOOT_DIR} ${rundir}/${SYS_DIR} && -cp ${LOADER_FILE} ${rundir}/${BOOT_DIR}/${BOOT_FILE} && -cp ${LOADER_FILE} ${SHIM_FILE} ${rundir}/${SYS_DIR} && +cp ${FIRMWARE_VARS} ${varsfile} && +cp ${BOOT_FILE} ${bootdir} && +cp ${BOOT_FILE} ${bootfile} && +cp ${SERVICE_FILE} ${servdir} && qemu-system-x86_64 -d int \ -drive if=pflash,format=raw,unit=0,file=/usr/share/ovmf/x64/OVMF_CODE.fd,readonly=on \ - -drive if=pflash,format=raw,unit=1,file=${tempdir}/OVMF_VARS.fd \ + -drive if=pflash,format=raw,unit=1,file=${varsfile} \ -net none -drive file=fat:rw:${rundir} -monitor stdio \ -serial file:sophia.log -no-shutdown -no-reboot -s -S diff --git a/kjarna/Makefile b/kjarna/Makefile deleted file mode 100644 index 482744f..0000000 --- a/kjarna/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -include ../defaults.mk - -%.efi: - $(CC.info) - @$(CC) $(LDFLAGS) -o $@ $^ - -VPATH := ../lib efi/ - -IMAGE := kjarna.efi - -CPPFLAGS += -I../api -I../lib - -CFLAGS += --target=$(ARCH)-unknown-windows -fshort-wchar -mno-avx \ - -mno-sse -mno-mmx -funsigned-char -Wno-pointer-sign -ggdb \ - -fno-ms-extensions - -LDFLAGS := --target=$(ARCH)-unknown-windows -nostdlib -ggdb \ - -Wl,-entry:_start,-subsystem:efi_application -fuse-ld=lld-link - -all: $(IMAGE) - -CRT_OBJS := start.o -LIB_OBJS := memcmp.o memset.o memcpy.o memmove.o string.o elf64.o -EFI_OBJS := file.o memory.o protocol.o image.o -APP_OBJS := main.o - -OBJS := $(CRT_OBJS) $(LIB_OBJS) $(EFI_OBJS) $(APP_OBJS) -DEPS := $(OBJS:.o=.d) - -$(IMAGE): $(OBJS) - -CLEANLIST := $(wildcard $(BUILD) $(OBJS) $(IMAGE) $(IMAGE:.efi=.pdb)) -DCLEANLIST := $(CLEANLIST) $(wildcard $(DEPS)) - -include ../rules.mk --include $(DEPS) - diff --git a/kjarna/efi/file.c b/kjarna/efi/file.c deleted file mode 100644 index 517e09e..0000000 --- a/kjarna/efi/file.c +++ /dev/null @@ -1,274 +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) -{ - static EFI_GUID lip_guid = EFI_LOADED_IMAGE_PROTOCOL_GUID; - static EFI_GUID sfsp_guid = EFI_SIMPLE_FILE_SYSTEM_PROTOCOL_GUID; - - EFI_LOADED_IMAGE_PROTOCOL *lip = efi_get_protocol(efi_context->handle, &lip_guid); - - if (lip == nullptr) - { - return -1; - } - - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *sfsp = efi_get_protocol(lip->DeviceHandle, &sfsp_guid); - - 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_close_protocol(lip->DeviceHandle, &lip_guid); - efi_close_protocol(efi_context->handle, &sfsp_guid); - 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) -{ - EFI_FILE_PROTOCOL *file = fd_to_file(fd); - - if (file == nullptr) - { - efi_errno = EFI_INVALID_PARAMETER; - return -1; - } - - off_t current = 0; - - if (whence == SEEK_END) - { - efi_errno = file->SetPosition(file, (UINTN)-1); - } - - if (EFI_ERROR(efi_errno)) - { - return -1; - } - - if (whence == SEEK_CUR || whence == SEEK_END) - { - efi_errno = file->GetPosition(file, (UINTN *)¤t); - } - - if (EFI_ERROR(efi_errno)) - { - return -1; - } - - efi_errno = file->SetPosition(file, (UINTN)(offset + current)); - - return !EFI_ERROR(efi_errno) ? offset : -1; -} - -static ssize_t efi_console_read(EFI_SIMPLE_TEXT_INPUT_PROTOCOL *console, CHAR16 *buffer, size_t length) -{ - //TODO: implement user input - (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 + 2, sizeof(*ws)); - - if(mbstowcs(ws, buffer, length + 2) == (size_t)-1) - { - efi_errno = EFI_INVALID_PARAMETER; - } - else - { - if (ws[length - 1] == L'\n') - ws[length] = L'\r'; - 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/image.c b/kjarna/efi/image.c deleted file mode 100644 index c26b588..0000000 --- a/kjarna/efi/image.c +++ /dev/null @@ -1,196 +0,0 @@ -#include -#include -#include -#include -#include - -#include "kjarna_efi.h" - -#include - -struct image_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_image_buffer(Elf64_Ehdr *ehdr, Elf64_Phdr *phdrs, struct image_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 image_buffer load_image(void) -{ - const char *image_entry_path = "\\adasoft\\sophia\\kjarna.os"; - - int image_fd; - - struct image_buffer buffer = { nullptr, 0 }; - - if ((image_fd = efi_open(image_entry_path, O_RDONLY, 0)) == -1) - { - return buffer; - } - - Elf64_Ehdr ehdr; - - if (read_ehdr(image_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(image_fd, &ehdr, phdrs) != -1) - { - create_image_buffer(&ehdr, phdrs, &buffer); - } - - if (buffer.base != nullptr && load_segments(image_fd, &ehdr, phdrs, buffer.base) == -1) - { - efi_munmap(buffer.base, buffer.length); - buffer.base = nullptr; - } - - efi_close(image_fd); - efi_free_pool(phdrs); - - return buffer; -} - -kjarna_image_entry_func *image_entry_addr(struct image_buffer *buffer) -{ - if (buffer->base == nullptr) - { - return nullptr; - } - - Elf64_Ehdr *ehdr = (Elf64_Ehdr *)buffer->base; - - return (kjarna_image_entry_func *)(buffer->base + ehdr->e_entry); -} - -int image_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 image_buffer buffer = load_image(); - - kjarna_image_entry_func *image_entry = nullptr; - - if (buffer.base != nullptr) - { - image_entry = image_entry_addr(&buffer); - } - - if (image_entry != nullptr) - { - image_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/kjarna_efi.h b/kjarna/efi/kjarna_efi.h deleted file mode 100644 index ea9d3f1..0000000 --- a/kjarna/efi/kjarna_efi.h +++ /dev/null @@ -1,37 +0,0 @@ -#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); -void efi_close_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 deleted file mode 100644 index 7fbb4a8..0000000 --- a/kjarna/efi/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/efi/protocol.c b/kjarna/efi/protocol.c deleted file mode 100644 index 6bf8123..0000000 --- a/kjarna/efi/protocol.c +++ /dev/null @@ -1,33 +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; -} - -void efi_close_protocol(EFI_HANDLE handle, EFI_GUID *guid) -{ - efi_errno = gBS->CloseProtocol( - handle, - guid, - efi_context->handle, - nullptr); -} - diff --git a/kjarna/efi/start.c b/kjarna/efi/start.c deleted file mode 100644 index 8ef8cbe..0000000 --- a/kjarna/efi/start.c +++ /dev/null @@ -1,32 +0,0 @@ -#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; - - system_table->ConOut->ClearScreen(system_table->ConOut); - - if (main(0, nullptr) != 0) - { - efi_errno = EFI_ABORTED; - } - - - return _exit(efi_errno); -} - diff --git a/kjarna/kjarna.h b/kjarna/kjarna.h deleted file mode 100644 index 81bb79b..0000000 --- a/kjarna/kjarna.h +++ /dev/null @@ -1,7 +0,0 @@ -#pragma once - -#include - -int main(int argc, char **argv); -int image_start(void); - diff --git a/kjarna/main.c b/kjarna/main.c deleted file mode 100644 index 38c913f..0000000 --- a/kjarna/main.c +++ /dev/null @@ -1,9 +0,0 @@ -#include "kjarna.h" - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - return image_start(); -} - diff --git a/kjarna_runtime/Makefile b/kjarna_runtime/Makefile deleted file mode 100644 index d6e762d..0000000 --- a/kjarna_runtime/Makefile +++ /dev/null @@ -1,37 +0,0 @@ -include ../defaults.mk - -LDFLAGS += -z max-page-size=4096 --export-dynamic -pic \ - -z separate-code -pie -Bsymbolic -shared \ - -z noexecstack -g - -VPATH := ../lib - -TARGET := kjarna.os -.DEFAULT: $(TARGET) - -CPPFLAGS += -I../api/posix -I../api/libc -I../api -I. - -CFLAGS += -fPIC -fvisibility=hidden -mgeneral-regs-only - -LDSCRIPT := kc.ld - -CRT_OBJS := start_x86_64.o dynamic_x86_64.o elf64.o kjarna.o -LIB_OBJS := memcmp.o memcpy.o memmove.o memset.o string.o stdio.o \ - printf.o -APP_OBJS := main.o - -OBJS := $(CRT_OBJS) $(LIB_OBJS) $(APP_OBJS) - -DEPS := $(patsubst %.o,%.d,$(OBJS)) - -$(TARGET): $(LDSCRIPT) $(MAKEFILE_LIST) -$(TARGET): $(OBJS) - -CLEANLIST := $(wildcard $(OBJS) $(TARGET)) -DCLEANLIST := $(wildcard $(DEPS)) - -include ../rules.mk --include $(DEPS) - -.DEFAULT: $(TARGET) - diff --git a/kjarna_runtime/dynamic_x86_64.c b/kjarna_runtime/dynamic_x86_64.c deleted file mode 100644 index 02538ec..0000000 --- a/kjarna_runtime/dynamic_x86_64.c +++ /dev/null @@ -1,139 +0,0 @@ -#include - -#include -#include - -extern void _rtld_link(void); - -struct elf64_relatab -{ - Elf64_Rela *entries; - size_t size; - size_t entsize; -}; - -struct elf64_symtab -{ - Elf64_Sym *entries; - const char *strings; - size_t strsize; -}; - -struct elf64_dso_info -{ - char *base; - struct elf64_relatab jmprel; - struct elf64_relatab reladyn; - struct elf64_symtab dynsym; - Elf64_Addr *pltgot; -}; - -static struct elf64_dso_info dso_info; - -void kc_dynamic_init(char *base, Elf64_Dyn *dyn) -{ - dso_info = (struct elf64_dso_info) - { - base, - { - elf64_dt_ptr(base, dyn, DT_JMPREL), - elf64_dt_val(dyn, DT_PLTRELSZ), - elf64_dt_val(dyn, DT_PLTREL) == DT_RELA ? sizeof(Elf64_Rela) : -1 - }, - { - elf64_dt_ptr(base, dyn, DT_RELA), - elf64_dt_val(dyn, DT_RELASZ), - elf64_dt_val(dyn, DT_RELAENT) - }, - { - elf64_dt_ptr(base, dyn, DT_SYMTAB), - elf64_dt_ptr(base, dyn, DT_STRTAB), - elf64_dt_val(dyn, DT_STRSZ) - }, - elf64_dt_ptr(base, dyn, DT_PLTGOT) - }; - - if (dso_info.pltgot != nullptr) - { - dso_info.pltgot[1] = (uintptr_t)&dso_info; - dso_info.pltgot[2] = (uintptr_t)_rtld_link; - } - - kc_dynamic_reloc(base, &dso_info.jmprel); - kc_dynamic_reloc(base, &dso_info.reladyn); -} - -void *kc_dynamic_link(struct elf64_dso_info *dso, int index) -{ - struct kjarna_interface *ftab = entry_params->interface; - - int symindex = ELF64_R_SYM(dso->jmprel.entries[index].r_info); - int strindex = dso->dynsym.entries[symindex].st_name; - const char *name = &dso->dynsym.strings[strindex]; - uintptr_t *fixup = (uintptr_t *)(dso->base + dso->jmprel.entries[index].r_offset); - - // TODO: generate a symbol table for kjarna interface - // TODO: implement symbol lookup (maybe hashed too) - if (strcmp(name, "open") == 0) - { - *fixup = (uintptr_t)*ftab->open; - } - else if (strcmp(name, "close") == 0) - { - *fixup = (uintptr_t)*ftab->close; - } - else if (strcmp(name, "read") == 0) - { - *fixup = (uintptr_t)*ftab->read; - } - else if (strcmp(name, "write") == 0) - { - *fixup = (uintptr_t)*ftab->write; - } - else if (strcmp(name, "lseek") == 0) - { - *fixup = (uintptr_t)*ftab->lseek; - } - else if (strcmp(name, "mmap") == 0) - { - *fixup = (uintptr_t)*ftab->mmap; - } - else if (strcmp(name, "munmap") == 0) - { - *fixup = (uintptr_t)*ftab->munmap; - } - else - { - return nullptr; - } - - return fixup; -} - -static void do_rela(char *base, Elf64_Rela *rela) -{ - uintptr_t *fixup = (uintptr_t *)(base + rela->r_offset); - - switch (ELF64_R_TYPE(rela->r_info)) - { - case R_X86_64_JUMP_SLOT: - *fixup += (uintptr_t)base; - break; - case R_X86_64_RELATIVE: - *fixup = (uintptr_t)(rela->r_addend + base); - break; - default: - break; - } -} - -void kc_dynamic_reloc(char *base, struct elf64_relatab *rela) -{ - size_t entries = rela->size / rela->entsize; - - for (size_t i = 0; rela->entries && (i < entries); i++) - { - do_rela(base, &rela->entries[i]); - } -} - diff --git a/kjarna_runtime/kc.h b/kjarna_runtime/kc.h deleted file mode 100644 index ff3a1ca..0000000 --- a/kjarna_runtime/kc.h +++ /dev/null @@ -1,46 +0,0 @@ -#pragma once - -#ifndef __ASSEMBLER__ - -#include - -#include - -#include - -extern struct kjarna_entry_params *entry_params; - -#define KC_EXPORT __attribute__((visibility("default"))) - -extern unsigned char kc_image_base; -extern unsigned char kc_text_begin; -extern unsigned char kc_text_end; -extern unsigned char kc_rodata_begin; -extern unsigned char kc_data_begin; -extern unsigned char kc_data_end; -extern unsigned char kc_image_end; - -struct elf64_dso_info; -struct elf64_relatab; - -extern void kc_dynamic_init(char *base, Elf64_Dyn *dyn); -extern void *kc_dynamic_link(struct elf64_dso_info *dso, int index); -extern void kc_dynamic_reloc(char *base, struct elf64_relatab *dso); - -#else - -.extern kc_image_base -.extern kc_text_begin -.extern kc_text_end -.extern kc_rodata_begin -.extern kc_rodata_end -.extern kc_data_begin -.extern kc_data_end -.extern kc_image_end -.extern _DYNAMIC - -.extern kc_dynamic_init -.extern kc_dynamic_link - -#endif // __ASSEMBLER__ - diff --git a/kjarna_runtime/kc.ld b/kjarna_runtime/kc.ld deleted file mode 100644 index f7b0339..0000000 --- a/kjarna_runtime/kc.ld +++ /dev/null @@ -1,97 +0,0 @@ -ENTRY(_start) - -SECTIONS -{ - PROVIDE_HIDDEN(kc_image_base = .); - - . = SIZEOF_HEADERS; - - .rela.plt : - { - *(.rela.plt) - } - - .rela.dyn : - { - *(.rela.dyn) - } - - .hash : - { - *(.hash) - } - - .dynsym : - { - *(.dynsym) - } - - .dynstr : - { - *(.dynstr) - } - - .rodata : - { - *(.rodata) - *(.rodata.*) - } - - .text : ALIGN(4K) - { - PROVIDE_HIDDEN(kc_text_begin = .); - *(.text.start) - *(.text) - } - - .plt : - { - *(.plt) - . = ALIGN(4K); - PROVIDE_HIDDEN(kc_text_end = .); - } =0xcc - - .dynamic : ALIGN(4K) - { - PROVIDE_HIDDEN(kc_data_begin = .); - *(.dynamic) - } - - .got : - { - *(.got) - } - - .got.plt : - { - *(.got.plt) - } - - .data : - { - *(.data) - } - - .data.rel : - { - *(.data.rel) - *(.data.rel.*) - } - - .bss : - { - *(.bss) - *(.dynbss) - . = ALIGN(4K); - PROVIDE_HIDDEN(kc_data_end = .); - } - - PROVIDE_HIDDEN(kc_image_end = .); - - /DISCARD/ : - { - *(.eh_frame) - *(.comment) - } -} - diff --git a/kjarna_runtime/kjarna.c b/kjarna_runtime/kjarna.c deleted file mode 100644 index 6b37d1e..0000000 --- a/kjarna_runtime/kjarna.c +++ /dev/null @@ -1,13 +0,0 @@ -#include - -struct kjarna_entry_params *entry_params; - -extern int main(int argc, char **argv); - -int kjarna_entry(struct kjarna_entry_params *params) -{ - entry_params = params; - - return main(params->argc, params->argv); -} - diff --git a/kjarna_runtime/main.c b/kjarna_runtime/main.c deleted file mode 100644 index 12a5522..0000000 --- a/kjarna_runtime/main.c +++ /dev/null @@ -1,17 +0,0 @@ -#include -#include - -#define KJARNA_REVISION 1 - -int main(int argc, char **argv) -{ - (void)argc; - (void)argv; - - printf("kjarna %d\n", KJARNA_REVISION); - - while (1); - - return 0; -} - diff --git a/kjarna_runtime/start_x86_64.S b/kjarna_runtime/start_x86_64.S deleted file mode 100644 index 19db34f..0000000 --- a/kjarna_runtime/start_x86_64.S +++ /dev/null @@ -1,63 +0,0 @@ -#include - -.section .text.start - -.extern kjarna_entry - -.hidden _start -.global _start -.type _start, @function -_start: - push %rbp - push %rdi - push %rsi - mov %rsp, %rbp - and $-0x10, %rsp - lea kc_image_base(%rip), %rdi - lea _DYNAMIC(%rip), %rsi - call kc_dynamic_init - mov %rbp, %rsp - pop %rsi - pop %rdi - mov %rsp, %rbp - and $-0x10, %rsp - call kjarna_entry - mov %rbp, %rsp - pop %rbp - ret -.size _start, . - _start - -.section .text - -.hidden _rtld_link -.global _rtld_link -.type _rtld_link, @function -_rtld_link: - push %rbp - mov %rsp, %rbp - push %r9 - push %r8 - push %rcx - push %rdx - push %rsi - push %rdi - mov 8(%rbp), %rdi - mov 16(%rbp), %rsi - push %rbp - mov %rsp, %rbp - and $-0x10, %rsp - call kc_dynamic_link - mov %rbp, %rsp - pop %rbp - pop %rdi - pop %rsi - pop %rdx - pop %rcx - pop %r8 - pop %r9 - mov %rbp, %rsp - pop %rbp - add $0x10, %rsp - jmp *(%rax) -.size _rtld_link, . - _rtld_link - diff --git a/service/Makefile b/service/Makefile new file mode 100644 index 0000000..d6e762d --- /dev/null +++ b/service/Makefile @@ -0,0 +1,37 @@ +include ../defaults.mk + +LDFLAGS += -z max-page-size=4096 --export-dynamic -pic \ + -z separate-code -pie -Bsymbolic -shared \ + -z noexecstack -g + +VPATH := ../lib + +TARGET := kjarna.os +.DEFAULT: $(TARGET) + +CPPFLAGS += -I../api/posix -I../api/libc -I../api -I. + +CFLAGS += -fPIC -fvisibility=hidden -mgeneral-regs-only + +LDSCRIPT := kc.ld + +CRT_OBJS := start_x86_64.o dynamic_x86_64.o elf64.o kjarna.o +LIB_OBJS := memcmp.o memcpy.o memmove.o memset.o string.o stdio.o \ + printf.o +APP_OBJS := main.o + +OBJS := $(CRT_OBJS) $(LIB_OBJS) $(APP_OBJS) + +DEPS := $(patsubst %.o,%.d,$(OBJS)) + +$(TARGET): $(LDSCRIPT) $(MAKEFILE_LIST) +$(TARGET): $(OBJS) + +CLEANLIST := $(wildcard $(OBJS) $(TARGET)) +DCLEANLIST := $(wildcard $(DEPS)) + +include ../rules.mk +-include $(DEPS) + +.DEFAULT: $(TARGET) + diff --git a/service/dynamic_x86_64.c b/service/dynamic_x86_64.c new file mode 100644 index 0000000..02538ec --- /dev/null +++ b/service/dynamic_x86_64.c @@ -0,0 +1,139 @@ +#include + +#include +#include + +extern void _rtld_link(void); + +struct elf64_relatab +{ + Elf64_Rela *entries; + size_t size; + size_t entsize; +}; + +struct elf64_symtab +{ + Elf64_Sym *entries; + const char *strings; + size_t strsize; +}; + +struct elf64_dso_info +{ + char *base; + struct elf64_relatab jmprel; + struct elf64_relatab reladyn; + struct elf64_symtab dynsym; + Elf64_Addr *pltgot; +}; + +static struct elf64_dso_info dso_info; + +void kc_dynamic_init(char *base, Elf64_Dyn *dyn) +{ + dso_info = (struct elf64_dso_info) + { + base, + { + elf64_dt_ptr(base, dyn, DT_JMPREL), + elf64_dt_val(dyn, DT_PLTRELSZ), + elf64_dt_val(dyn, DT_PLTREL) == DT_RELA ? sizeof(Elf64_Rela) : -1 + }, + { + elf64_dt_ptr(base, dyn, DT_RELA), + elf64_dt_val(dyn, DT_RELASZ), + elf64_dt_val(dyn, DT_RELAENT) + }, + { + elf64_dt_ptr(base, dyn, DT_SYMTAB), + elf64_dt_ptr(base, dyn, DT_STRTAB), + elf64_dt_val(dyn, DT_STRSZ) + }, + elf64_dt_ptr(base, dyn, DT_PLTGOT) + }; + + if (dso_info.pltgot != nullptr) + { + dso_info.pltgot[1] = (uintptr_t)&dso_info; + dso_info.pltgot[2] = (uintptr_t)_rtld_link; + } + + kc_dynamic_reloc(base, &dso_info.jmprel); + kc_dynamic_reloc(base, &dso_info.reladyn); +} + +void *kc_dynamic_link(struct elf64_dso_info *dso, int index) +{ + struct kjarna_interface *ftab = entry_params->interface; + + int symindex = ELF64_R_SYM(dso->jmprel.entries[index].r_info); + int strindex = dso->dynsym.entries[symindex].st_name; + const char *name = &dso->dynsym.strings[strindex]; + uintptr_t *fixup = (uintptr_t *)(dso->base + dso->jmprel.entries[index].r_offset); + + // TODO: generate a symbol table for kjarna interface + // TODO: implement symbol lookup (maybe hashed too) + if (strcmp(name, "open") == 0) + { + *fixup = (uintptr_t)*ftab->open; + } + else if (strcmp(name, "close") == 0) + { + *fixup = (uintptr_t)*ftab->close; + } + else if (strcmp(name, "read") == 0) + { + *fixup = (uintptr_t)*ftab->read; + } + else if (strcmp(name, "write") == 0) + { + *fixup = (uintptr_t)*ftab->write; + } + else if (strcmp(name, "lseek") == 0) + { + *fixup = (uintptr_t)*ftab->lseek; + } + else if (strcmp(name, "mmap") == 0) + { + *fixup = (uintptr_t)*ftab->mmap; + } + else if (strcmp(name, "munmap") == 0) + { + *fixup = (uintptr_t)*ftab->munmap; + } + else + { + return nullptr; + } + + return fixup; +} + +static void do_rela(char *base, Elf64_Rela *rela) +{ + uintptr_t *fixup = (uintptr_t *)(base + rela->r_offset); + + switch (ELF64_R_TYPE(rela->r_info)) + { + case R_X86_64_JUMP_SLOT: + *fixup += (uintptr_t)base; + break; + case R_X86_64_RELATIVE: + *fixup = (uintptr_t)(rela->r_addend + base); + break; + default: + break; + } +} + +void kc_dynamic_reloc(char *base, struct elf64_relatab *rela) +{ + size_t entries = rela->size / rela->entsize; + + for (size_t i = 0; rela->entries && (i < entries); i++) + { + do_rela(base, &rela->entries[i]); + } +} + diff --git a/service/kc.h b/service/kc.h new file mode 100644 index 0000000..ff3a1ca --- /dev/null +++ b/service/kc.h @@ -0,0 +1,46 @@ +#pragma once + +#ifndef __ASSEMBLER__ + +#include + +#include + +#include + +extern struct kjarna_entry_params *entry_params; + +#define KC_EXPORT __attribute__((visibility("default"))) + +extern unsigned char kc_image_base; +extern unsigned char kc_text_begin; +extern unsigned char kc_text_end; +extern unsigned char kc_rodata_begin; +extern unsigned char kc_data_begin; +extern unsigned char kc_data_end; +extern unsigned char kc_image_end; + +struct elf64_dso_info; +struct elf64_relatab; + +extern void kc_dynamic_init(char *base, Elf64_Dyn *dyn); +extern void *kc_dynamic_link(struct elf64_dso_info *dso, int index); +extern void kc_dynamic_reloc(char *base, struct elf64_relatab *dso); + +#else + +.extern kc_image_base +.extern kc_text_begin +.extern kc_text_end +.extern kc_rodata_begin +.extern kc_rodata_end +.extern kc_data_begin +.extern kc_data_end +.extern kc_image_end +.extern _DYNAMIC + +.extern kc_dynamic_init +.extern kc_dynamic_link + +#endif // __ASSEMBLER__ + diff --git a/service/kc.ld b/service/kc.ld new file mode 100644 index 0000000..f7b0339 --- /dev/null +++ b/service/kc.ld @@ -0,0 +1,97 @@ +ENTRY(_start) + +SECTIONS +{ + PROVIDE_HIDDEN(kc_image_base = .); + + . = SIZEOF_HEADERS; + + .rela.plt : + { + *(.rela.plt) + } + + .rela.dyn : + { + *(.rela.dyn) + } + + .hash : + { + *(.hash) + } + + .dynsym : + { + *(.dynsym) + } + + .dynstr : + { + *(.dynstr) + } + + .rodata : + { + *(.rodata) + *(.rodata.*) + } + + .text : ALIGN(4K) + { + PROVIDE_HIDDEN(kc_text_begin = .); + *(.text.start) + *(.text) + } + + .plt : + { + *(.plt) + . = ALIGN(4K); + PROVIDE_HIDDEN(kc_text_end = .); + } =0xcc + + .dynamic : ALIGN(4K) + { + PROVIDE_HIDDEN(kc_data_begin = .); + *(.dynamic) + } + + .got : + { + *(.got) + } + + .got.plt : + { + *(.got.plt) + } + + .data : + { + *(.data) + } + + .data.rel : + { + *(.data.rel) + *(.data.rel.*) + } + + .bss : + { + *(.bss) + *(.dynbss) + . = ALIGN(4K); + PROVIDE_HIDDEN(kc_data_end = .); + } + + PROVIDE_HIDDEN(kc_image_end = .); + + /DISCARD/ : + { + *(.eh_frame) + *(.comment) + } +} + diff --git a/service/kjarna.c b/service/kjarna.c new file mode 100644 index 0000000..6b37d1e --- /dev/null +++ b/service/kjarna.c @@ -0,0 +1,13 @@ +#include + +struct kjarna_entry_params *entry_params; + +extern int main(int argc, char **argv); + +int kjarna_entry(struct kjarna_entry_params *params) +{ + entry_params = params; + + return main(params->argc, params->argv); +} + diff --git a/service/main.c b/service/main.c new file mode 100644 index 0000000..12a5522 --- /dev/null +++ b/service/main.c @@ -0,0 +1,17 @@ +#include +#include + +#define KJARNA_REVISION 1 + +int main(int argc, char **argv) +{ + (void)argc; + (void)argv; + + printf("kjarna %d\n", KJARNA_REVISION); + + while (1); + + return 0; +} + diff --git a/service/start_x86_64.S b/service/start_x86_64.S new file mode 100644 index 0000000..19db34f --- /dev/null +++ b/service/start_x86_64.S @@ -0,0 +1,63 @@ +#include + +.section .text.start + +.extern kjarna_entry + +.hidden _start +.global _start +.type _start, @function +_start: + push %rbp + push %rdi + push %rsi + mov %rsp, %rbp + and $-0x10, %rsp + lea kc_image_base(%rip), %rdi + lea _DYNAMIC(%rip), %rsi + call kc_dynamic_init + mov %rbp, %rsp + pop %rsi + pop %rdi + mov %rsp, %rbp + and $-0x10, %rsp + call kjarna_entry + mov %rbp, %rsp + pop %rbp + ret +.size _start, . - _start + +.section .text + +.hidden _rtld_link +.global _rtld_link +.type _rtld_link, @function +_rtld_link: + push %rbp + mov %rsp, %rbp + push %r9 + push %r8 + push %rcx + push %rdx + push %rsi + push %rdi + mov 8(%rbp), %rdi + mov 16(%rbp), %rsi + push %rbp + mov %rsp, %rbp + and $-0x10, %rsp + call kc_dynamic_link + mov %rbp, %rsp + pop %rbp + pop %rdi + pop %rsi + pop %rdx + pop %rcx + pop %r8 + pop %r9 + mov %rbp, %rsp + pop %rbp + add $0x10, %rsp + jmp *(%rax) +.size _rtld_link, . - _rtld_link + -- cgit v1.3.1-1-g115d