diff --git a/build.sh b/build.sh index 8103dce..82e6d68 100755 --- a/build.sh +++ b/build.sh @@ -13,7 +13,9 @@ dd if=/dev/zero of=build/os.img bs="${sector_size}" count="$((partition_offset + dd if=build/mbr.bin of=build/os.img bs="${sector_size}" count=1 conv=notrunc dd if=build/bootloader.bin of=build/os.img bs="${sector_size}" seek=1 count="$((partition_offset - 1))" conv=notrunc mkfs.fat -F 16 --offset "${partition_offset}" build/os.img -mcopy -i build/os.img@@"$((partition_offset * sector_size))" src ::src +mcopy -i build/os.img@@"$((partition_offset * sector_size))" -s src ::src mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/kernel.bin ::kernel.bin -mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/terminal ::terminal -mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/echo ::echo +mmd -i build/os.img@@"$((partition_offset * sector_size))" ::bin +mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/terminal ::bin/terminal +mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/echo ::bin/echo +mcopy -i build/os.img@@"$((partition_offset * sector_size))" build/ls ::bin/ls diff --git a/meson.build b/meson.build index ec59149..9002f91 100644 --- a/meson.build +++ b/meson.build @@ -146,7 +146,6 @@ custom_target( build_by_default: true, ) - echo_start = custom_target( 'echo_start', input: 'src/user/start.asm', @@ -185,3 +184,42 @@ custom_target( command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], build_by_default: true, ) + +ls_start = custom_target( + 'ls_start', + input: 'src/user/start.asm', + output: 'ls_start.o', + command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'], +) + +ls_syscall = custom_target( + 'ls_syscall', + input: 'src/user/syscall.asm', + output: 'ls_syscall.o', + command: [nasm, '-f', 'elf64', '-o', '@OUTPUT@', '@INPUT@'], +) + +ls_elf = executable( + 'ls.elf', + sources: [ls_start, ls_syscall, lib_sources, 'src/user/app/ls/ls.c'], + c_args: [ + '-ffreestanding', + '-nostdlib', + '-fno-stack-protector', + '-mcmodel=large', + '-DVERSION="' + meson.project_version() + '"', + ], + link_args: [ + '-T', meson.project_source_root() / 'src/user/linker.ld', + '-nostdlib', + ], + link_depends: 'src/user/linker.ld', +) + +custom_target( + 'ls', + input: ls_elf, + output: 'ls', + command: ['objcopy', '-O', 'binary', '@INPUT@', '@OUTPUT@'], + build_by_default: true, +) diff --git a/src/kernel/kernel.c b/src/kernel/kernel.c index c0eb497..61fdb47 100644 --- a/src/kernel/kernel.c +++ b/src/kernel/kernel.c @@ -56,7 +56,7 @@ void kernel_main() { kernel->stdin = keyboard_init(); kernel->stdout = vga_init(); - fs_node_t *bin = fs_open_by(kernel->root, "terminal"); + fs_node_t *bin = path_open_file(kernel->root, kernel->cwd, "bin/terminal"); ASSERT(bin, "kernel: terminal not found"); diff --git a/src/kernel/syscall.asm b/src/kernel/syscall.asm index df629b1..9b53e26 100644 --- a/src/kernel/syscall.asm +++ b/src/kernel/syscall.asm @@ -28,6 +28,7 @@ syscall_entry: push r14 push r15 + mov r8, r10 ; arg4 mov rcx, rdx ; arg3 mov rdx, rsi ; arg2 mov rsi, rdi ; arg1 diff --git a/src/kernel/syscall.c b/src/kernel/syscall.c index 1057e03..9313085 100644 --- a/src/kernel/syscall.c +++ b/src/kernel/syscall.c @@ -145,11 +145,36 @@ static uint64_t spawn(const char *path, uint64_t argc, const char **argv) { return 0; } +static uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to) { + fs_node_t *dir = path_open_directory(current_process->root, current_process->cwd, path); + if (!dir) { + return (uint64_t)-1; + } + fs_node_t *item = fs_open_at(dir, index); + if (!item) { + if (dir != current_process->root) { + fs_close(dir); + } + return 0; + } + uint64_t length = string_length(item->name); + uint64_t size = length > max - 1 ? max - 1 : length; + memory_copy(item->name, size, to); + to[size] = '\0'; + + fs_close(item); + if (dir != current_process->root) { + fs_close(dir); + } + + return size; +} + static void exit() { process_switch_to(¤t_process->kernel_rsp, current_process->parent->kernel_rsp, VIRT_TO_PHYS(current_process->parent->pml4)); } -uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3) { +uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4) { switch (func) { case SYSCALL_READ: return read(arg1, arg2, (char *)arg3); @@ -161,6 +186,8 @@ uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t return chdir((const char *)arg1); case SYSCALL_SPAWN: return spawn((const char *)arg1, arg2, (const char **)arg3); + case SYSCALL_READDIR: + return readdir((const char *)arg1, arg2, arg3, (char *)arg4); case SYSCALL_EXIT: exit(); return 0; diff --git a/src/kernel/syscall.h b/src/kernel/syscall.h index a98214d..68b29af 100644 --- a/src/kernel/syscall.h +++ b/src/kernel/syscall.h @@ -7,8 +7,9 @@ #define SYSCALL_GETCWD 2 #define SYSCALL_CHDIR 3 #define SYSCALL_SPAWN 4 +#define SYSCALL_READDIR 5 #define SYSCALL_EXIT 60 void syscall_init(); -uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3); +uint64_t syscall_dispatch(uint64_t func, uint64_t arg1, uint64_t arg2, uint64_t arg3, uint64_t arg4); diff --git a/src/user/app/echo/echo.c b/src/user/app/echo/echo.c index 4be8332..9a08cfd 100644 --- a/src/user/app/echo/echo.c +++ b/src/user/app/echo/echo.c @@ -1,7 +1,7 @@ #include "src/lib/string.h" #include "src/user/syscall.h" -int main(uint64_t argc, const char **argv) { +uint64_t main(uint64_t argc, const char **argv) { for (uint64_t i = 1; i < argc; i++) { if (i > 1) { write(1, " ", 1); diff --git a/src/user/app/ls/ls.c b/src/user/app/ls/ls.c new file mode 100644 index 0000000..1ac2974 --- /dev/null +++ b/src/user/app/ls/ls.c @@ -0,0 +1,43 @@ +#include "src/lib/string.h" +#include "src/user/syscall.h" + +#define WRITE_S(s) write(1, s, sizeof(s) - 1); +#define WRITE_D(s) write(1, s, string_length(s)); + +uint64_t ls(const char *path) { + uint64_t i = 0; + while (1) { + char out[100]; + uint64_t s = readdir(path, i, 100, out); + if (!s) { + return 0; + } + if (s == (uint64_t)-1) { + WRITE_S("ls: path does not exist\n"); + return (uint64_t)-1; + } + WRITE_D(out); + WRITE_S("\n"); + i++; + } +} + +uint64_t main(uint64_t argc, const char **argv) { + if (argc == 1) { + return ls("."); + } + + uint64_t code = 0; + for (uint64_t i = 1; i < argc; i++) { + if (argc > 2) { + WRITE_S("\n"); + WRITE_D(argv[i]); + WRITE_S(":\n"); + } + if (ls(argv[i]) == (uint64_t)-1) { + code = (uint64_t)-1; + } + } + + return code; +} diff --git a/src/user/app/terminal/terminal.c b/src/user/app/terminal/terminal.c index 13c9e58..7287c33 100644 --- a/src/user/app/terminal/terminal.c +++ b/src/user/app/terminal/terminal.c @@ -6,6 +6,8 @@ static void help(uint8_t argc, char **argv); static void cd(uint8_t argc, char **argv); +#define PATH "/bin/" + #define WRITE_S(s) write(1, s, sizeof(s) - 1); #define WRITE_D(s) write(1, s, string_length(s)); @@ -117,9 +119,14 @@ static void on_enter_pressed() { } } if (i == sizeof(builtins) / sizeof(app_entry_t)) { - if (spawn(argv[0], argc, (const char **)argv) == (uint64_t)-1){ + uint64_t size = sizeof(PATH) + string_length(argv[0]) + 1; + char *path = memory_allocate(size); + memory_copy(PATH, sizeof(PATH), path); + memory_copy(argv[0], size - sizeof(PATH), path + sizeof(PATH) - 1); + if (spawn(path, argc, (const char **)argv) == (uint64_t)-1) { WRITE_S("terminal: program not found\n"); } + memory_free(path); } prompt_length = prompt_offset = 0; print_prompt(); @@ -258,7 +265,7 @@ static void on_char_received(char c) { } } -int main() { +uint64_t main() { memory_set('\b', PROMPT_LENGTH, (char *)bs); memory_set(' ', PROMPT_LENGTH, (char *)ws); diff --git a/src/user/syscall.asm b/src/user/syscall.asm index 43a63c3..912c511 100644 --- a/src/user/syscall.asm +++ b/src/user/syscall.asm @@ -30,6 +30,13 @@ spawn: syscall ret +global readdir +readdir: + mov r10, rcx + mov rax, 5 + syscall + ret + global exit exit: mov rax, 60 diff --git a/src/user/syscall.h b/src/user/syscall.h index 4702d89..059c143 100644 --- a/src/user/syscall.h +++ b/src/user/syscall.h @@ -12,4 +12,6 @@ uint64_t chdir(const char *path); uint64_t spawn(const char *path, uint64_t argc, const char **argv); +uint64_t readdir(const char *path, uint64_t index, uint64_t max, char *to); + void exit();