Skip to content

Commit

Permalink
kernel: Support native libc-less init
Browse files Browse the repository at this point in the history
  • Loading branch information
Qwinci committed Nov 30, 2023
1 parent 38c017c commit f4669e4
Show file tree
Hide file tree
Showing 13 changed files with 309 additions and 12 deletions.
2 changes: 2 additions & 0 deletions apps/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -1,8 +1,10 @@
set(APPS
user_tty
init
)

add_subdirectory(user_tty)
add_subdirectory(init)

set(APP_FILES ${APPS})
list(TRANSFORM APP_FILES PREPEND "${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/")
Expand Down
7 changes: 7 additions & 0 deletions apps/init/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
project(init)

set(CMAKE_C_STANDARD 23)

add_executable(init init.c)

target_link_libraries(init PRIVATE common)
4 changes: 4 additions & 0 deletions apps/init/init.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,4 @@

int main() {

}
5 changes: 5 additions & 0 deletions image.cmake
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ set(FILES
${PROJECT_SOURCE_DIR}/kernel/fonts/Tamsyn8x16r.psf
${PROJECT_SOURCE_DIR}/kernel/limine.cfg
bin/crescent
initramfs.tar
)

set(QEMU_FLAGS -m 2G -machine q35 -smp 1 -d int
Expand Down Expand Up @@ -65,6 +66,10 @@ endif()

find_program(GUESTMOUNT guestmount)

add_custom_command(OUTPUT initramfs.tar
COMMAND tar -cf initramfs.tar -C ${PROJECT_BINARY_DIR}/sysroot/ .
)

if(GUESTMOUNT)
add_custom_target(update_image
COMMAND mkdir -p ${PROJECT_BINARY_DIR}/mountpoint
Expand Down
6 changes: 5 additions & 1 deletion kernel/limine.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -5,9 +5,13 @@ TIMEOUT=0
PROTOCOL=limine
KERNEL_PATH=boot:///crescent
#KERNEL_CMDLINE=init=ext2_p0/user_tty
KERNEL_CMDLINE=init=ext2_p0/libc_test_app posix_root=ext2_p0
#KERNEL_CMDLINE=init=ext2_p0/libc_test_app posix_root=ext2_p0
KERNEL_CMDLINE=native_init=posix_root/init posix_root=initramfs

MODULE_PATH=boot:///Tamsyn8x16r.psf
MODULE_CMDLINE=Tamsyn8x16r.psf

MODULE_PATH=boot:///initramfs.tar
MODULE_CMDLINE=initramfs.tar

KASLR=no
29 changes: 18 additions & 11 deletions kernel/src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@
#ifdef CONFIG_TEST
#include "utils/test.h"
#endif
#include "dev/fbcon.h"
#include "fs/posix_rootfs.h"
#include "fs/tar.h"
#include "fs/vfs.h"
Expand Down Expand Up @@ -74,22 +75,28 @@ static int stderr_vnode_write(VNode* self, const void* data, usize off, usize si
}
kfree(null_terminated_init, parsed_cmdline.init.len + 1);

// todo don't hardcode this
const char* interp_path = "posix_rootfs/usr/lib/ld.so";
VNode* interp_vnode;
if ((status = kernel_fs_open(interp_path, &interp_vnode)) != 0) {
panic("failed to open interp file '%s': %d\n", interp_path, status);
}

usize interp_base;
if ((status = elf_load_from_file(init_process, interp_vnode, &init_res, false, &interp_base)) != 0) {
panic("failed to load init elf phdrs, status: %d\n", status);
}
LoadedElf program_res;
if ((status = elf_load_from_file(init_process, init_vnode, &program_res, false, NULL)) != 0) {
panic("failed to load init elf, status: %d\n", status);
}

if (!parsed_cmdline.native_init) {
// todo don't hardcode this
const char* interp_path = "posix_rootfs/usr/lib/ld.so";
VNode* interp_vnode;
if ((status = kernel_fs_open(interp_path, &interp_vnode)) != 0) {
panic("failed to open interp file '%s': %d\n", interp_path, status);
}

usize interp_base;
if ((status = elf_load_from_file(init_process, interp_vnode, &init_res, false, &interp_base)) != 0) {
panic("failed to load init elf phdrs, status: %d\n", status);
}
}
else {
init_res = program_res;
}

Str arg0 = str_new("posix_rootfs/libc_test_program");
Str args[] = {arg0};
SysvAux aux[] = {
Expand Down
5 changes: 5 additions & 0 deletions kernel/src/utils/cmdline.c
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,11 @@ KernelCmdline parse_kernel_cmdline(const char* cmdline) {
Str value = get_arg(&str);
res.init = value;
}
else if (str_strip_prefix(&str, str_new("native_init="))) {
Str value = get_arg(&str);
res.init = value;
res.native_init = true;
}
else if (str_strip_prefix(&str, str_new("posix_root="))) {
Str value = get_arg(&str);
res.posix_root = value;
Expand Down
1 change: 1 addition & 0 deletions kernel/src/utils/cmdline.h
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@
typedef struct {
Str init;
Str posix_root;
bool native_init;
} KernelCmdline;

KernelCmdline parse_kernel_cmdline(const char* cmdline);
2 changes: 2 additions & 0 deletions libs/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -24,3 +24,5 @@ ExternalProject_Add(mlibc
${NINJA} -C <BINARY_DIR> install
COMMAND touch <INSTALL_DIR>/usr/lib/libunwind.a
)

add_subdirectory(common)
12 changes: 12 additions & 0 deletions libs/common/CMakeLists.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
project(common)

set(CMAKE_C_STANDARD 23)

add_library(common STATIC
start.c
sys.c
)

target_include_directories(common PUBLIC ${CMAKE_SOURCE_DIR}/kernel/include)
target_compile_options(common PUBLIC -fno-stack-protector -Wall -Wextra)
target_link_options(common PUBLIC -nostdlib -Wl,--fatal-warnings)
7 changes: 7 additions & 0 deletions libs/common/start.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#include "sys.h"

int main();

__attribute__((noreturn)) void _start() {
sys_exit(main());
}
190 changes: 190 additions & 0 deletions libs/common/sys.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,190 @@
#include "sys.h"

size_t syscall0(size_t num) {
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num) : "r11", "rcx");
return ret;
}

size_t syscall1(size_t num, size_t a0) {
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0) : "r11", "rcx");
return ret;
}

size_t syscall2(size_t num, size_t a0, size_t a1) {
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0), "S"(a1) : "r11", "rcx");
return ret;
}

size_t syscall3(size_t num, size_t a0, size_t a1, size_t a2) {
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0), "S"(a1), "d"(a2) : "r11", "rcx");
return ret;
}

size_t syscall4(size_t num, size_t a0, size_t a1, size_t a2, size_t a3) {
register size_t r10 __asm__("r10") = a3;
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0), "S"(a1), "d"(a2), "r"(r10) : "r11", "rcx");
return ret;
}

size_t syscall5(size_t num, size_t a0, size_t a1, size_t a2, size_t a3, size_t a4) {
register size_t r10 __asm__("r10") = a3;
register size_t r8 __asm__("r8") = a4;
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0), "S"(a1), "d"(a2), "r"(r10), "r"(r8) : "r11", "rcx");
return ret;
}

size_t syscall6(size_t num, size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5) {
register size_t r10 __asm__("r10") = a3;
register size_t r8 __asm__("r8") = a4;
register size_t r9 __asm__("r9") = a5;
size_t ret;
__asm__ volatile("syscall" : "=a"(ret) : "D"(num), "a"(a0), "S"(a1), "d"(a2), "r"(r10), "r"(r8), "r"(r9) : "r11", "rcx");
return ret;
}

__attribute__((noreturn)) void sys_exit(int status) {
syscall1(SYS_EXIT, status);
__builtin_unreachable();
}

int sys_dprint(const char* msg, size_t len) {
return (int) syscall2(SYS_DPRINT, (size_t) msg, len);
}

int sys_create_process(const char* path, size_t path_len, Handle* ret) {
return (int) syscall3(SYS_CREATE_PROCESS, (size_t) path, (size_t) path_len, (size_t) ret);
}

int sys_kill_process(Handle handle) {
return (int) syscall1(SYS_KILL_PROCESS, handle);
}

int sys_wait_process(Handle handle) {
return (int) syscall1(SYS_WAIT_PROCESS, handle);
}

Handle sys_create_thread(void (*fn)(void*), void* arg) {
return (Handle) syscall2(SYS_CREATE_THREAD, (size_t) fn, (size_t) arg);
}

int sys_kill_thread(Handle thread) {
return (int) syscall1(SYS_KILL_THREAD, (size_t) thread);
}

void sys_sleep(size_t ms) {
syscall1(SYS_SLEEP, ms);
}

int sys_wait_thread(Handle thread) {
return (int) syscall1(SYS_WAIT_THREAD, thread);
}

int sys_wait_for_event(Event* event) {
return (int) syscall1(SYS_WAIT_FOR_EVENT, (size_t) event);
}

int sys_poll_event(Event* event) {
return (int) syscall1(SYS_POLL_EVENT, (size_t) event);
}

int sys_shutdown(ShutdownType type) {
return (int) syscall1(SYS_SHUTDOWN, type);
}

bool sys_request_cap(uint32_t cap) {
return syscall1(SYS_REQUEST_CAP, cap);
}

void* sys_mmap(size_t size, int protection) {
return (void*) syscall2(SYS_MMAP, size, protection);
}

int sys_munmap(void* ptr, size_t size) {
return (int) syscall2(SYS_MUNMAP, (size_t) ptr, size);
}

int sys_close(Handle handle) {
return (int) syscall1(SYS_CLOSE, handle);
}

int sys_devmsg(Handle handle, size_t msg, void* data) {
return (int) syscall3(SYS_DEVMSG, (size_t) handle, msg, (size_t) data);
}

int sys_devenum(DeviceType type, DeviceInfo* res, size_t* count) {
return (int) syscall3(SYS_DEVENUM, (size_t) type, (size_t) res, (size_t) count);
}

int sys_open(const char* path, size_t path_len, Handle* ret) {
return (int) syscall3(SYS_OPEN, (size_t) path, path_len, (size_t) ret);
}

int sys_open_ex(const char* dev, size_t dev_len, const char* path, size_t path_len, Handle* ret) {
return (int) syscall5(SYS_OPEN_EX, (size_t) dev, dev_len, (size_t) path, path_len, (size_t) ret);
}

int sys_read(Handle handle, void* buffer, size_t size) {
return (int) syscall3(SYS_READ, handle, (size_t) buffer, size);
}

int sys_write(Handle handle, const void* buffer, size_t size) {
return (int) syscall3(SYS_WRITE, handle, (size_t) buffer, size);
}

int sys_seek(Handle handle, CrescentSeekType type, SeekOff offset) {
return (int) syscall3(SYS_WRITE, handle, (size_t) type, (size_t) offset);
}

int sys_stat(Handle handle, CrescentStat* stat) {
return (int) syscall2(SYS_STAT, handle, (size_t) stat);
}

int sys_opendir(const char* path, size_t path_len, CrescentDir** ret) {
return (int) syscall3(SYS_OPENDIR, (size_t) path, path_len, (size_t) ret);
}

int sys_closedir(CrescentDir* dir) {
return (int) syscall1(SYS_CLOSEDIR, (size_t) dir);
}

int sys_readdir(CrescentDir* dir, CrescentDirEntry* entry) {
return (int) syscall2(SYS_READDIR, (size_t) dir, (size_t) entry);
}

int sys_write_fs_base(size_t value) {
return (int) syscall1(SYS_WRITE_FS_BASE, value);
}

int sys_write_gs_base(size_t value) {
return (int) syscall1(SYS_WRITE_GS_BASE, value);
}

int sys_posix_open(const char* path, size_t path_len) {
return (int) syscall2(SYS_POSIX_OPEN, (size_t) path, path_len);
}

int sys_posix_close(int fd) {
return (int) syscall1(SYS_POSIX_CLOSE, (size_t) fd);
}

int sys_posix_read(int fd, void* buffer, size_t size) {
return (int) syscall3(SYS_POSIX_READ, (size_t) fd, (size_t) buffer, size);
}

int sys_posix_write(int fd, const void* buffer, size_t size) {
return (int) syscall3(SYS_POSIX_WRITE, (size_t) fd, (size_t) buffer, size);
}

SeekOff sys_posix_seek(int fd, CrescentSeekType type, SeekOff offset) {
return (SeekOff) syscall3(SYS_POSIX_SEEK, (size_t) fd, (size_t) type, (size_t) offset);
}

int sys_posix_mmap(void* hint, size_t size, int prot, void** window) {
return (int) syscall4(SYS_POSIX_MMAP, (size_t) hint, size, (size_t) prot, (size_t) window);
}
51 changes: 51 additions & 0 deletions libs/common/sys.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,51 @@
#pragma once
#include <stddef.h>
#include <crescent/handle.h>
#include <crescent/input.h>
#include <crescent/sys.h>
#include <crescent/dev.h>
#include <crescent/fs.h>

size_t syscall0(size_t num);
size_t syscall1(size_t num, size_t a0);
size_t syscall2(size_t num, size_t a0, size_t a1);
size_t syscall3(size_t num, size_t a0, size_t a1, size_t a2);
size_t syscall4(size_t num, size_t a0, size_t a1, size_t a2, size_t a3);
size_t syscall5(size_t num, size_t a0, size_t a1, size_t a2, size_t a3, size_t a4);
size_t syscall6(size_t num, size_t a0, size_t a1, size_t a2, size_t a3, size_t a4, size_t a5);
__attribute__((noreturn)) void sys_exit(int status);
int sys_dprint(const char* msg, size_t len);
int sys_create_process(const char* path, size_t path_len, Handle* ret);
int sys_kill_process(Handle handle);
int sys_wait_process(Handle handle);
Handle sys_create_thread(void (*fn)(void*), void* arg);
int sys_kill_thread(Handle thread);
void sys_sleep(size_t ms);
int sys_wait_thread(Handle thread);
int sys_wait_for_event(Event* event);
int sys_poll_event(Event* event);
int sys_shutdown(ShutdownType type);
bool sys_request_cap(uint32_t cap);
void* sys_mmap(size_t size, int protection);
int sys_munmap(void* ptr, size_t size);
int sys_close(Handle handle);
int sys_devmsg(Handle handle, size_t msg, void* data);
int sys_devenum(DeviceType type, DeviceInfo* res, size_t* count);
int sys_open(const char* path, size_t path_len, Handle* ret);
int sys_open_ex(const char* dev, size_t dev_len, const char* path, size_t path_len, Handle* ret);
int sys_read(Handle handle, void* buffer, size_t size);
int sys_write(Handle handle, const void* buffer, size_t size);
int sys_seek(Handle handle, CrescentSeekType type, SeekOff offset);
int sys_stat(Handle handle, CrescentStat* stat);
int sys_opendir(const char* path, size_t path_len, CrescentDir** ret);
int sys_closedir(CrescentDir* dir);
int sys_readdir(CrescentDir* dir, CrescentDirEntry* entry);
int sys_write_fs_base(size_t value);
int sys_write_gs_base(size_t value);

int sys_posix_open(const char* path, size_t path_len);
int sys_posix_close(int fd);
int sys_posix_read(int fd, void* buffer, size_t size);
int sys_posix_write(int fd, const void* buffer, size_t size);
SeekOff sys_posix_seek(int fd, CrescentSeekType type, SeekOff offset);
int sys_posix_mmap(void* hint, size_t size, int prot, void** window);

0 comments on commit f4669e4

Please sign in to comment.