summaryrefslogtreecommitdiff
path: root/boot/main.c
diff options
context:
space:
mode:
authorAda Christine <adachristine18@gmail.com>2025-02-01 23:25:40 +0000
committerAda Christine <adachristine18@gmail.com>2025-02-01 23:25:40 +0000
commit3d806c9e2fcb6226915982b6514919a3b9dac4dc (patch)
treecae747e3a5c6e31f89069e0ba1a7ae90cc4b85d9 /boot/main.c
parentf76631c47b92b0778b1073bcab55dc1240422f20 (diff)
write syscall functions
Diffstat (limited to 'boot/main.c')
-rw-r--r--boot/main.c108
1 files changed, 96 insertions, 12 deletions
diff --git a/boot/main.c b/boot/main.c
index 611c833..ed18578 100644
--- a/boot/main.c
+++ b/boot/main.c
@@ -5,6 +5,7 @@
#include <bits/x86_64/descriptor.h>
#include <libc/stdio.h>
#include <posix/sys/mman.h>
+#include <posix/unistd.h>
/*
* Fake syscall mechanism -
@@ -47,32 +48,114 @@ static struct segment_descriptor const fake_syscall_gdt[] =
typedef uint64_t syscall_delegate_parameters[6];
+static struct
+{
+ uint16_t cs;
+ uint16_t ds;
+ uint64_t rflags;
+ struct descriptor_table_register_long gdtr;
+}
+uefi_context;
+
+static void save_uefi_context()
+{
+ __asm__ volatile (
+ "movw %%cs, %0\n"
+ "movw %%ds, %1\n"
+ "pushfq\n"
+ "popq %3\n"
+ "sgdt %2\n"
+ :
+ "=m"(uefi_context.cs),
+ "=m"(uefi_context.ds),
+ "=m"(uefi_context.gdtr),
+ "=g"(uefi_context.rflags)
+ :
+ );
+}
+
+static void restore_uefi_context()
+{
+ __asm__ volatile (
+ "lgdt %0\n"
+ "mov %w1, %%ds\n"
+ "mov %w1, %%es\n"
+ "mov %w1, %%fs\n"
+ "mov %w1, %%gs\n"
+ "mov %w1, %%gs\n"
+ "mov %w1, %%ss\n"
+ "push %q2\n"
+ "lea .Lflush(%%rip), %%rax\n"
+ "push %%rax\n"
+ "lretq\n"
+ ".Lflush:\n"
+ "push %q3\n"
+ "popfq\n"
+ :
+ :
+ "m"(uefi_context.gdtr),
+ "m"(uefi_context.ds),
+ "m"(uefi_context.cs),
+ "g"(uefi_context.rflags)
+ :
+ "rax"
+ );
+
+}
+
struct syscall_context_return_state
{
- uint64_t rflags; // 8
- struct descriptor_table_register_long gdtr; // 24
- uint64_t return_ds; // 32
- uintptr_t return_rip; // 40
- uint64_t return_cs; // 48
+ uint64_t rflags;
+ struct descriptor_table_register_long gdtr;
+ uint64_t return_ds;
+ uintptr_t return_rip;
+ uint64_t return_cs;
};
struct syscall_context
{
- uint64_t pad; // 8
- uint64_t syscall_index; // 16
- syscall_delegate_parameters parameters; // 64
+ uint64_t pad;
+ uint64_t syscall_index;
+ syscall_delegate_parameters parameters;
struct syscall_context_return_state state;
};
+
typedef int64_t (syscall_delegate)(syscall_delegate_parameters params);
-//constexpr int NR_SYSCALLS = 10;
-//static syscall_delegate *syscall_handler_delegates[NR_SYSCALLS];
+int64_t syscall_delegate_write(syscall_delegate_parameters params)
+{
+ return write((int)params[0], (void *)params[1], (size_t)params[2]);
+}
+
+constexpr int NR_SYSCALLS = 10;
+static syscall_delegate *syscall_handler_delegates[NR_SYSCALLS] =
+{
+ nullptr,
+ syscall_delegate_write
+};
SYSV_ABI int64_t fake_syscall_handler(struct syscall_context *context)
{
- (void)context;
- return -1;
+ if (context->syscall_index > NR_SYSCALLS)
+ {
+ // TODO: ENOSYS
+ return -1;
+ }
+
+ syscall_delegate *delegate = syscall_handler_delegates[context->syscall_index];
+
+ if (delegate == nullptr)
+ {
+ // TODO: ENOSYS
+ return -1;
+ }
+
+ restore_uefi_context();
+ int64_t result = delegate(context->parameters);
+ save_uefi_context();
+
+ return result;
}
SYSV_ABI void fake_syscall_entry(void);
@@ -117,6 +200,7 @@ int main(int argc, char **argv)
struct kjarna_boot_image boot_image = get_boot_image();
install_syscall_handler();
void *fake_syscall_stack = create_fake_syscall_stack((void *)boot_image.entry);
+ save_uefi_context();
fake_syscall_start(fake_syscall_stack);
}