summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2024-02-11 23:48:04 +0000
committerAda Christine <adachristine18@gmail.com>2024-02-11 23:48:04 +0000
commit3f9278b48ff4bc0d2cf1604034b3bba548572f04 (patch)
treedbdabed3ff580079d2e21045d2cbc5b274c2e418
parent9fbfc6e951e565ef98c49c1dcfc4b6a39514f17d (diff)
kjarna initial impl
-rw-r--r--api/efi/error.h4
-rw-r--r--api/kjarna/interface.h29
-rw-r--r--api/lib/kstring.h5
-rw-r--r--api/libc/stdlib.h6
-rw-r--r--api/libc/string.h11
-rw-r--r--api/libc/wchar.h6
-rw-r--r--api/posix/fcntl.h4
-rw-r--r--api/posix/sys/types.h7
-rw-r--r--api/posix/unistd.h11
-rw-r--r--kc/core/memory/memory.c31
-rw-r--r--kjarna/Makefile33
-rw-r--r--kjarna/file.c268
-rw-r--r--kjarna/kjarna_efi.h38
-rw-r--r--kjarna/main.c6
-rw-r--r--kjarna/memory.c83
-rw-r--r--kjarna/protocol.c24
-rw-r--r--kjarna/runtime.c195
-rw-r--r--kjarna/start.c30
-rw-r--r--lib/string.c39
19 files changed, 813 insertions, 17 deletions
diff --git a/api/efi/error.h b/api/efi/error.h
index b02f7ff..5fbcba8 100644
--- a/api/efi/error.h
+++ b/api/efi/error.h
@@ -6,8 +6,8 @@
#define EFI_SUCCESS 0
#define EFI_INVALID_PARAMETER EFI_ERROR_CODE(2)
+#define EFI_BUFFER_TOO_SMALL EFI_ERROR_CODE(5)
#define EFI_NOT_READY EFI_ERROR_CODE(6)
-#define EFI_ABORTED EFI_ERROR_CODE(21)
#define EFI_NOT_FOUND EFI_ERROR_CODE(14)
-#define EFI_BUFFER_TOO_SMALL EFI_ERROR_CODE(5)
+#define EFI_ABORTED EFI_ERROR_CODE(21)
diff --git a/api/kjarna/interface.h b/api/kjarna/interface.h
new file mode 100644
index 0000000..e0c491a
--- /dev/null
+++ b/api/kjarna/interface.h
@@ -0,0 +1,29 @@
+#pragma once
+
+#include <stddef.h>
+#include <posix/sys/types.h>
+
+#define SYSV_ABI __attribute__((sysv_abi))
+
+struct kjarna_interface
+{
+ int (SYSV_ABI *open)(const char *, int, int);
+ int (SYSV_ABI *close)(int);
+ off_t (SYSV_ABI *lseek)(int, off_t, int);
+ ssize_t (SYSV_ABI *read)(int, void *, size_t);
+ ssize_t (SYSV_ABI *write)(int, const void *, size_t);
+
+ void *(SYSV_ABI *mmap)(void *, size_t, int, int, int, off_t);
+ int (SYSV_ABI *munmap)(void *, size_t);
+};
+
+struct kjarna_entry_params
+{
+ struct kjarna_interface *interface;
+ int argc;
+ char **argv;
+ char **envp;
+};
+
+typedef int (SYSV_ABI kjarna_runtime_entry_func)(struct kjarna_entry_params *);
+
diff --git a/api/lib/kstring.h b/api/lib/kstring.h
index c28e17c..d1d45d5 100644
--- a/api/lib/kstring.h
+++ b/api/lib/kstring.h
@@ -7,8 +7,5 @@ void *memmove(void *dest, const void *src, size_t size);
void *memset(void *dest, int val, size_t size);
int memcmp(const void *str1, const void *str2, size_t count);
size_t strlen(const char *s);
-unsigned long long strtoull(
- const char *restrict begin,
- char **restrict end,
- int base);
+unsigned long long strtoull(const char *restrict begin, char **restrict end, int base);
diff --git a/api/libc/stdlib.h b/api/libc/stdlib.h
new file mode 100644
index 0000000..76a78eb
--- /dev/null
+++ b/api/libc/stdlib.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <stddef.h>
+
+size_t mbstowcs(wchar_t *dst, const char *src, size_t length);
+
diff --git a/api/libc/string.h b/api/libc/string.h
new file mode 100644
index 0000000..d1d45d5
--- /dev/null
+++ b/api/libc/string.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#include <stddef.h>
+
+void *memcpy(void *dest, const void *src, size_t size);
+void *memmove(void *dest, const void *src, size_t size);
+void *memset(void *dest, int val, size_t size);
+int memcmp(const void *str1, const void *str2, size_t count);
+size_t strlen(const char *s);
+unsigned long long strtoull(const char *restrict begin, char **restrict end, int base);
+
diff --git a/api/libc/wchar.h b/api/libc/wchar.h
new file mode 100644
index 0000000..4dd339d
--- /dev/null
+++ b/api/libc/wchar.h
@@ -0,0 +1,6 @@
+#pragma once
+
+#include <stddef.h>
+
+size_t wcslen(const wchar_t *s);
+
diff --git a/api/posix/fcntl.h b/api/posix/fcntl.h
new file mode 100644
index 0000000..7e55e02
--- /dev/null
+++ b/api/posix/fcntl.h
@@ -0,0 +1,4 @@
+#pragma once
+
+#define O_RDONLY 0
+
diff --git a/api/posix/sys/types.h b/api/posix/sys/types.h
new file mode 100644
index 0000000..2be0ef8
--- /dev/null
+++ b/api/posix/sys/types.h
@@ -0,0 +1,7 @@
+#pragma once
+
+#include <stdint.h>
+
+typedef int64_t ssize_t;
+typedef int64_t off_t;
+
diff --git a/api/posix/unistd.h b/api/posix/unistd.h
new file mode 100644
index 0000000..6bd69f5
--- /dev/null
+++ b/api/posix/unistd.h
@@ -0,0 +1,11 @@
+#pragma once
+
+#define STDIN_FILENO 0
+#define STDOUT_FILENO 1
+#define STDERR_FILENO 2
+
+enum seek_whence
+{
+ SEEK_SET
+};
+
diff --git a/kc/core/memory/memory.c b/kc/core/memory/memory.c
index 1c6fabb..ee0d9ca 100644
--- a/kc/core/memory/memory.c
+++ b/kc/core/memory/memory.c
@@ -599,13 +599,32 @@ void *vm_alloc(size_t size, enum vm_alloc_flags flags)
// TODO implement a proper allocator here rather than this bump allocator.
char *address = vm_state.first_free;
- if (address == vm_alloc_at(address, size, flags))
- {
- vm_state.first_free = address + size;
- return address;
- }
+ while (address != vm_alloc_at(address, size, flags))
+ {
+ address = address + size;
+ }
- return NULL;
+ if (address != nullptr)
+ {
+ vm_state.first_free = address + size;
+ }
+
+ return address;
+}
+
+
+void vm_free(void *address)
+{
+ struct vm_tree_key key = { (uintptr_t)address, 1 };
+ struct vm_tree_node *node;
+
+ if(!(node = vmt_search_key(vm_get_tree(), &key)))
+ {
+ return;
+ }
+
+ // TODO: delete paging structures etc.
+ vmt_delete(vm_get_tree(), node);
}
int anonymous_page_handler(
diff --git a/kjarna/Makefile b/kjarna/Makefile
new file mode 100644
index 0000000..4cf6102
--- /dev/null
+++ b/kjarna/Makefile
@@ -0,0 +1,33 @@
+include ../defaults.mk
+include ../efi.mk
+
+VPATH := ../lib
+
+IMAGE := kjarna.efi
+
+CPPFLAGS += -I../api -I../lib
+
+CFLAGS += --target=$(GNUEFIARCH)-unknown-windows -fshort-wchar -mno-avx \
+ -mno-sse -mno-mmx -funsigned-char -Wno-pointer-sign -ggdb \
+ -fno-ms-extensions
+
+LDFLAGS := --target=$(GNUEFIARCH)-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
+APP_OBJS := file.o memory.o protocol.o runtime.o
+
+OBJS := $(CRT_OBJS) $(LIB_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/file.c b/kjarna/file.c
new file mode 100644
index 0000000..6888390
--- /dev/null
+++ b/kjarna/file.c
@@ -0,0 +1,268 @@
+#include <efi/types.h>
+#include <efi/error.h>
+#include <efi/media.h>
+#include <efi/tables.h>
+
+#include <posix/unistd.h>
+#include <libc/stdlib.h>
+#include <libc/string.h>
+
+#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_efi.h b/kjarna/kjarna_efi.h
new file mode 100644
index 0000000..e24cc7f
--- /dev/null
+++ b/kjarna/kjarna_efi.h
@@ -0,0 +1,38 @@
+#pragma once
+
+#include <posix/sys/types.h>
+
+#include <efi/types.h>
+#include <efi/tables.h>
+
+#include <kjarna/interface.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);
+
+int runtime_start(void);
+
diff --git a/kjarna/main.c b/kjarna/main.c
new file mode 100644
index 0000000..3d34bf4
--- /dev/null
+++ b/kjarna/main.c
@@ -0,0 +1,6 @@
+#include "kjarna_efi.h"
+
+int main(int argc, char **argv)
+{
+}
+
diff --git a/kjarna/memory.c b/kjarna/memory.c
new file mode 100644
index 0000000..7fbb4a8
--- /dev/null
+++ b/kjarna/memory.c
@@ -0,0 +1,83 @@
+#include <libc/string.h>
+
+#include <efi/services.h>
+#include <efi/error.h>
+
+#include <stddef.h>
+
+#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
new file mode 100644
index 0000000..e4be9cd
--- /dev/null
+++ b/kjarna/protocol.c
@@ -0,0 +1,24 @@
+#include <efi/error.h>
+
+#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
new file mode 100644
index 0000000..5f2e7e1
--- /dev/null
+++ b/kjarna/runtime.c
@@ -0,0 +1,195 @@
+#include <posix/unistd.h>
+#include <posix/fcntl.h>
+#include <kjarna/interface.h>
+#include <libc/string.h>
+#include <lib/elf.h>
+
+#include "kjarna_efi.h"
+
+#include <efi/error.h>
+
+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(&params);
+ }
+
+ 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
new file mode 100644
index 0000000..6a737b3
--- /dev/null
+++ b/kjarna/start.c
@@ -0,0 +1,30 @@
+#include <efi/types.h>
+#include <efi/error.h>
+#include <efi/media.h>
+#include <efi/tables.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;
+
+ int runtime_result = runtime_start();
+
+ if (runtime_result < 0)
+ {
+ efi_errno = EFI_ABORTED;
+ }
+
+ return _exit(efi_errno);
+}
+
diff --git a/lib/string.c b/lib/string.c
index f6bc682..315fa1e 100644
--- a/lib/string.c
+++ b/lib/string.c
@@ -1,15 +1,46 @@
-#include <lib/kstring.h>
+#include <libc/string.h>
#include <stdbool.h>
size_t strlen(const char *s)
{
size_t l = 0;
- while (*s++) l++;
+ while (s != nullptr && *s++) l++;
return l;
}
+size_t wcslen(const wchar_t *s)
+{
+ size_t l = 0;
+
+ while (s != nullptr && *s++) l++;
+
+ return l;
+}
+
+size_t mbstowcs(wchar_t *dst, const char *src, size_t len)
+{
+ if (dst == nullptr || src == nullptr)
+ {
+ return -1;
+ }
+
+ size_t i;
+
+ for (i = 0; i < len; i++)
+ {
+ if ((dst[i] = src[i]) == 0)
+ {
+ break;
+ }
+ }
+
+ dst[i] = L'\0';
+
+ return i;
+}
+
static long long valueof(int c, int base)
{
long long result = 0;
@@ -28,9 +59,7 @@ static long long valueof(int c, int base)
}
// check if value is an uppercase ASCII alphabetical character
- else if (
- (c >= 'A' && c <= 'Z') ||
- (c >= 'a' && c <= 'z'))
+ else if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z'))
{
// mask in uppercase bit
c |= 0x20;