Browse Source

feat(posix): impl. posix interface, update usp

greatbridf 2 years ago
parent
commit
d4122bd571

+ 1 - 0
CMakeLists.txt

@@ -125,6 +125,7 @@ add_custom_target(boot.img
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/interrupt-test.out ::int.out
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/stack-test.out ::stack.out
     COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/init.out ::init.elf
+    COMMAND mcopy -i boot.img@@1M ${CMAKE_BINARY_DIR}/user-space-program/sh.out ::sh.elf
 )
 
 add_custom_command(OUTPUT run

+ 5 - 2
gblibc/CMakeLists.txt

@@ -6,12 +6,15 @@ add_library(gblibc STATIC
     src/arithmetic.c
     src/string.c
     src/crt0.s
+    src/fcntl.c
+    src/unistd.c
+    src/wait.c
 )
 
 target_include_directories(gblibc PUBLIC ${CMAKE_CURRENT_SOURCE_DIR}/include
                                   PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/private-include)
 
 set_target_properties(gblibc PROPERTIES PRIVATE_HEADER
-    "private-include/devutil.h")
+    "private-include/devutil.h,private-include/syscall.h")
 set_target_properties(gblibc PROPERTIES PUBLIC_HEADER
-    "include/stdio.h,include/stdint.h,include/stdarg.h,include/string.h")
+    "include/stdio.h,include/stdint.h,include/stdarg.h,include/string.h,include/unistd.h,include/sys/types.h,include/sys/wait.h,include/fcntl.h")

+ 16 - 0
gblibc/include/fcntl.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_FCNTL_H_
+#define __GBLIBC_FCNTL_H_
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int open(const char* filename, int flags, ...);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 16 - 0
gblibc/include/sys/types.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_SYS_TYPES_H
+#define __GBLIBC_SYS_TYPES_H
+
+#include <stdint.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef ssize_t pid_t;
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 16 - 0
gblibc/include/sys/wait.h

@@ -0,0 +1,16 @@
+#ifndef __GBLIBC_SYS_WAIT_H
+#define __GBLIBC_SYS_WAIT_H
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+pid_t wait(int* code);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 23 - 0
gblibc/include/unistd.h

@@ -0,0 +1,23 @@
+#ifndef __GBLIBC_UNISTD_H_
+#define __GBLIBC_UNISTD_H_
+
+#include <sys/types.h>
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+ssize_t read(int fd, void* buf, size_t count);
+ssize_t write(int fd, const void* buf, size_t count);
+
+_Noreturn void _exit(int code);
+pid_t fork(void);
+int execve(const char* pathname, char* const argv[], char* const envp[]);
+
+unsigned int sleep(unsigned int seconds);
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 76 - 0
gblibc/private-include/syscall.h

@@ -0,0 +1,76 @@
+#ifndef __GBLIBC_SYSCALL_H_
+#define __GBLIBC_SYSCALL_H_
+
+#include <stdint.h>
+
+#define SYS_fork (0x00)
+#define SYS_write (0x01)
+#define SYS_sleep (0x02)
+#define SYS_crash (0x03)
+#define SYS_exec (0x04)
+#define SYS_exit (0x05)
+#define SYS_wait (0x06)
+#define SYS_read (0x07)
+#define SYS_getdents (0x08)
+#define SYS_open (0x09)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+static inline uint32_t syscall0(uint32_t no)
+{
+    asm volatile(
+        "movl %1, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(no)
+        : "eax");
+    return no;
+}
+static inline uint32_t syscall1(uint32_t no, uint32_t arg)
+{
+    asm volatile(
+        "movl %1, %%edi\n"
+        "movl %2, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg), "g"(no)
+        : "eax", "edi");
+    return no;
+}
+static inline uint32_t syscall2(uint32_t no, uint32_t arg1, uint32_t arg2)
+{
+    asm volatile(
+        "movl %1, %%edi\n"
+        "movl %2, %%esi\n"
+        "movl %3, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg1), "g"(arg2), "g"(no)
+        : "eax", "edi", "esi");
+    return no;
+}
+static inline uint32_t syscall3(uint32_t no, uint32_t arg1, uint32_t arg2, uint32_t arg3)
+{
+    asm volatile(
+        "movl %1, %%edi\n"
+        "movl %2, %%esi\n"
+        "movl %3, %%edx\n"
+        "movl %4, %%eax\n"
+        "int $0x80\n"
+        "movl %%eax, %0"
+        : "=g"(no)
+        : "g"(arg1), "g"(arg2), "g"(arg3), "g"(no)
+        : "eax", "edx", "edi", "esi");
+    return no;
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif

+ 7 - 0
gblibc/src/fcntl.c

@@ -0,0 +1,7 @@
+#include <fcntl.h>
+#include <syscall.h>
+
+int open(const char* filename, int flags, ...)
+{
+    return syscall2(SYS_open, (uint32_t)filename, flags);
+}

+ 34 - 0
gblibc/src/unistd.c

@@ -0,0 +1,34 @@
+#include <unistd.h>
+#include <syscall.h>
+
+ssize_t read(int fd, void* buf, size_t count)
+{
+    return syscall3(SYS_read, fd, (uint32_t)buf, count);
+}
+
+ssize_t write(int fd, const void* buf, size_t count)
+{
+    return syscall3(SYS_write, fd, (uint32_t)buf, count);
+}
+
+_Noreturn void _exit(int code)
+{
+    (void)syscall1(SYS_exit, code);
+    // if syscall failed
+    for (;;);
+}
+
+pid_t fork(void)
+{
+    return syscall0(SYS_fork);
+}
+
+int execve(const char* pathname, char* const argv[], char* const envp[])
+{
+    return syscall3(SYS_exec, (uint32_t)pathname, (uint32_t)argv, (uint32_t)envp);
+}
+
+unsigned int sleep(unsigned int seconds)
+{
+    return syscall1(SYS_sleep, seconds);
+}

+ 7 - 0
gblibc/src/wait.c

@@ -0,0 +1,7 @@
+#include <sys/wait.h>
+#include <syscall.h>
+
+pid_t wait(int* code)
+{
+    return syscall1(SYS_wait, (uint32_t)code);
+}

+ 1 - 1
src/kernel/process.cpp

@@ -166,7 +166,7 @@ void NORETURN _kernel_init(void)
     current_process->attr.system = 0;
     current_thread->attr.system = 0;
 
-    const char* argv[] = { "/mnt/INIT.ELF", nullptr };
+    const char* argv[] = { "/mnt/INIT.ELF", "/mnt/SH.ELF", nullptr };
     const char* envp[] = { nullptr };
 
     types::elf::elf32_load_data d;

+ 12 - 1
src/kernel/syscall.cpp

@@ -7,6 +7,7 @@
 #include <kernel/mm.hpp>
 #include <kernel/process.hpp>
 #include <kernel/syscall.hpp>
+#include <kernel/tty.hpp>
 #include <kernel/vfs.hpp>
 #include <kernel_main.hpp>
 #include <stdint.h>
@@ -144,7 +145,11 @@ void _syscall_exec(interrupt_stack* data)
     d.exec = exec;
     d.system = false;
 
-    assert(types::elf::elf32_load(&d) == GB_OK);
+    int ret = types::elf::elf32_load(&d);
+    if (ret != GB_OK) {
+        data->s_regs.eax = d.errcode;
+        return;
+    }
 
     data->v_eip = d.eip;
     data->esp = (uint32_t)d.sp;
@@ -175,6 +180,12 @@ void _syscall_exit(interrupt_stack* data)
     // unmap all user memory areas
     current_process->mms.clear_user();
 
+    // init should never exit
+    if (current_process->ppid == 0) {
+        console->print("kernel panic: init exited!\n");
+        crash();
+    }
+
     // make child processes orphans (children of init)
     procs->make_children_orphans(pid);
 

+ 2 - 1
user-space-program/CMakeLists.txt

@@ -15,7 +15,8 @@ add_executable(hello-world.out hello-world.s)
 add_executable(interrupt-test.out interrupt-test.s)
 add_executable(stack-test.out stack-test.s)
 add_executable(init.out init.c)
+add_executable(sh.out sh.c)
 
 add_custom_target(user_space_programs
-    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out
+    DEPENDS hello-world.out interrupt-test.out stack-test.out init.out sh.out
 )

+ 7 - 75
user-space-program/basic-lib.h

@@ -1,10 +1,7 @@
-typedef __UINT32_TYPE__ uint32_t;
-typedef __UINT16_TYPE__ uint16_t;
-typedef __UINT8_TYPE__ uint8_t;
+#include <stdint.h>
+#include <sys/types.h>
 
-typedef uint32_t pid_t;
-typedef uint32_t size_t;
-typedef size_t ino_t;
+typedef uint32_t ino_t;
 
 #define GNU_ATTRIBUTE(attr) __attribute__((attr))
 #define NORETURN GNU_ATTRIBUTE(noreturn)
@@ -25,66 +22,6 @@ typedef size_t ino_t;
 
 #define DT_MAX (S_DT_MASK + 1) /* 16 */
 
-static inline uint32_t syscall(uint32_t num, uint32_t arg1, uint32_t arg2, uint32_t arg3)
-{
-    asm volatile(
-        "movl %1, %%edi\n"
-        "movl %2, %%esi\n"
-        "movl %3, %%edx\n"
-        "movl %4, %%eax\n"
-        "int $0x80\n"
-        "movl %%eax, %0"
-        : "=g"(num)
-        : "g"(arg1), "g"(arg2), "g"(arg3), "g"(num)
-        : "eax", "edx", "edi", "esi");
-    return num;
-}
-
-static inline void NORETURN syscall_noreturn(uint32_t num, uint32_t arg1, uint32_t arg2, uint32_t arg3)
-{
-    asm volatile(
-        "movl %1, %%edi\n"
-        "movl %2, %%esi\n"
-        "movl %3, %%edx\n"
-        "movl %4, %%eax\n"
-        "int $0x80\n"
-        "movl %%eax, %0"
-        : "=g"(num)
-        : "g"(arg1), "g"(arg2), "g"(arg3), "g"(num)
-        : "eax", "edx", "edi", "esi");
-    // crash
-    syscall_noreturn(0x05, 0, 0, 0);
-}
-
-static inline int fork(void)
-{
-    return syscall(0x00, 0, 0, 0);
-}
-static inline uint32_t write(int fd, const char* buf, size_t count)
-{
-    return syscall(0x01, fd, (uint32_t)buf, count);
-}
-static inline uint32_t read(int fd, char* buf, size_t count)
-{
-    return syscall(0x07, fd, (uint32_t)buf, count);
-}
-static inline void sleep(void)
-{
-    syscall(0x02, 0, 0, 0);
-}
-static inline void NORETURN exec(const char* bin, const char** argv)
-{
-    syscall_noreturn(0x04, (uint32_t)bin, (uint32_t)argv, 0);
-}
-static inline void NORETURN exit(int exit_code)
-{
-    syscall_noreturn(0x05, exit_code, 0, 0);
-}
-static inline uint32_t wait(int* return_value)
-{
-    return syscall(0x06, (uint32_t)return_value, 0, 0);
-}
-
 struct __attribute__((__packed__)) user_dirent {
     ino_t d_ino; // inode number
     uint32_t d_off; // ignored
@@ -93,12 +30,7 @@ struct __attribute__((__packed__)) user_dirent {
     // uint8_t d_type; // file type, with offset of (d_reclen - 1)
 };
 
-static inline size_t getdents(int fd, struct user_dirent* buf, size_t cnt)
-{
-    return syscall(0x08, fd, (uint32_t)buf, cnt);
-}
-
-static inline int open(const char* path, uint32_t flags)
-{
-    return syscall(0x09, (uint32_t)path, flags, 0);
-}
+// static inline size_t getdents(int fd, struct user_dirent* buf, size_t cnt)
+// {
+//     return syscall(0x08, fd, (uint32_t)buf, cnt);
+// }

+ 18 - 2
user-space-program/hello-world.s

@@ -5,5 +5,21 @@
 .globl main
 main:
 	movl $0xcbcbcbcb, %eax
-	movl $0xacacacac, %ebx
-	jmp .
+	movl $0xacacacac, %edx
+
+	movl $0x01, %eax
+	movl $0, %edi
+	movl $_str, %esi
+	movl $_str_size, %ecx
+	movl (%ecx), %edx
+	int $0x80
+
+	xorl %eax, %eax
+	ret
+
+.data
+_str:
+	.ascii "Hello, World!\n"
+
+_str_size:
+	.long (_str_size - _str)

+ 30 - 98
user-space-program/init.c

@@ -1,114 +1,46 @@
-#include "basic-lib.h"
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <sys/wait.h>
 
-static inline char tc(int n) {
-    return '0' + n;
-}
-
-void print_int(int n) {
-    char buf[12];
-    int len = 0;
-
-    while (n) {
-        int dig = n % 10;
-        buf[len++] = tc(dig);
-        n /= 10;
-    }
-
-    write(0, buf, len);
-}
-
-size_t strlen(const char* str)
-{
-    const char* p = str;
-    while (*p)
-        ++p;
-    return p - str;
-}
-
-static inline void print(const char* str)
-{
-    write(0, str, strlen(str));
-}
+#define print(str) write(0, str, strlen(str))
 
 int main(int argc, char** argv)
 {
-    for (int i = 0; i < argc; ++i)
-        write(0, argv[i], 0);
+    print("***** GBOS INIT SYSTEM *****\n");
 
-    print("Hello World from user space init\n");
-    int ret = fork();
-    if (ret == 0) {
-        print("child\n");
-        exit(255);
-    } else {
-        print("parent\n");
+    pid_t sh_pid = fork();
+    if (sh_pid < 0) {
+        print("[init] unable to fork(), exiting...\n");
+        return -1;
     }
 
-    char buf[128] = {};
-
-    const char* path = "/dev";
-    print("content in ");
-    print(path);
-    print(":\n");
-
-    int dir = open(path, O_RDONLY | O_DIRECTORY);
-    if (dir >= 0) {
-        for (;;) {
-            int n = getdents(dir, (struct user_dirent*)buf, 128);
-            if (n < 0)
-                print("error\n");
-            if (n <= 0)
-                break;
-
-            int bpos = 0;
-            for (; bpos < n;) {
-                struct user_dirent* dirp = (struct user_dirent*)(buf + bpos);
-                print("ino: ");
-                print_int(dirp->d_ino);
-                print(", filename: \"");
-                print(dirp->d_name);
-                print("\", filetype: ");
-                switch (buf[bpos + dirp->d_reclen - 1]) {
-                    case DT_REG:
-                        print("regular file");
-                        break;
-                    case DT_DIR:
-                        print("directory");
-                        break;
-                    case DT_BLK:
-                        print("block device");
-                        break;
-                    default:
-                        print("unknown");
-                        break;
-                }
-                print("\n");
-                bpos += dirp->d_reclen;
-            }
-        }
-    }
+    // child
+    if (sh_pid == 0) {
+        char* shell_argv[128] = {};
+        char* envp[1] = { NULL };
 
-    for (;;) {
-        int n = read(0, buf, 128);
-        if (n)
-            write(0, buf, n);
+        if (argc < 2)
+            shell_argv[0] = "/bin/sh";
         else
-            print("fuck!\n");
+            shell_argv[0] = argv[1];
+        
+        for (int i = 2; i < argc; ++i)
+            shell_argv[i - 1] = argv[i];
         
-        if (buf[0] == 'e' && buf[1] == 'x' && buf[2] == 'i' && buf[3] == 't') {
-            print("\nexited echo mode!\n");
-            break;
-        }
+        execve(shell_argv[0], shell_argv, envp);
+
+        print("[init] unable to run sh, exiting...\n");
+        return -1;
     }
 
+    int ret, pid;
+    char buf[512] = {};
     for (;;) {
-        int ret;
-        pid_t pid = wait(&ret);
-        print("ret: ");
-        print_int(ret);
-        print(", pid: ");
-        print_int(pid);
-        print("\n");
+        pid = wait(&ret);
+        snprintf(buf, sizeof(buf), "[init] pid%d has exited with code %d\n", pid, ret);
+        print(buf);
     }
+
     return 0;
 }

+ 8 - 8
user-space-program/interrupt-test.s

@@ -14,16 +14,16 @@ main:
 	movl %eax, %ecx
 # write
 	movl $1, %eax
-	movl $__user_interrupt_test_string, %edi
+	movl $0, %edi
+	movl $__user_interrupt_test_string, %esi
+	movl $(__user_interrupt_test_string_end - __user_interrupt_test_string), %edx
 	int $0x80
-# sleep
-	movl $2, %eax
-	movl $0xffffffff, %edi
-	int $0x80
-# noreturn
-	jmp .
+
+	xorl %eax, %eax
+	ret
 
 .data
 
 __user_interrupt_test_string:
-	.asciz "syscall 0x01 write: hello from user space\n"
+	.ascii "syscall 0x01 write: hello from user space\n"
+__user_interrupt_test_string_end:

+ 106 - 0
user-space-program/sh.c

@@ -0,0 +1,106 @@
+#include <sys/wait.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+#define print(str) write(0, str, strlen(str))
+
+// struct cmd {
+//     enum {
+//         pipe,
+//         list,
+//     } op;
+//     struct cmd* left;
+//     struct cmd* right;
+//     struct token* tk;
+// };
+
+// struct token {
+//     char* start;
+//     size_t len;
+
+//     struct token* next;
+// };
+
+// static inline int betwn(char c, char s, char e)
+// {
+//     return c >= s && c <= e;
+// }
+// static inline int is_num(char c)
+// {
+//     return betwn(c, '0', '9');
+// }
+// static inline int check_token(char c)
+// {
+//     return betwn(c, 'a', 'z') || betwn(c, 'A', 'Z') || (c == '_');
+// }
+// static inline int read_token(char* buf, struct token** cur)
+// {
+//     char* p = buf;
+//     for (; *p && (check_token(*p) || (p != buf && is_num(*p))); ++p) {
+//         (*cur)->start = buf;
+//         ++(*cur)->len;
+//     }
+//     if ((*cur)->start) {
+//         (*cur)->next = *cur + 1;
+//         *cur = (*cur)->next;
+//     }
+//     return p - buf;
+// }
+
+int main(int argc, const char** argv)
+{
+    (void)argc, (void)argv;
+    char buf[512] = {};
+
+    print("sh # ");
+
+    for (;;) {
+        int n = read(0, buf, sizeof(buf));
+
+        char token[1024] = {};
+        char* args[128] = { token, 0 };
+        int j = 0;
+        int k = 1;
+
+        for (int i = 0; i < n; ++i) {
+            if (buf[i] == ' ') {
+                token[j++] = 0;
+                args[k++] = token + j;
+                continue;
+            }
+            if (buf[i] == '\n') {
+                token[j++] = 0;
+
+                if (strcmp(args[0], "exit") == 0)
+                    return 0;
+
+                pid_t pid = fork();
+                if (pid == 0) {
+                    char* envp[] = { NULL };
+                    int ret = execve(args[0], args, envp);
+                    char _b[128];
+                    snprintf(_b, sizeof(_b), "sh: execve() failed with code %d\n", ret);
+                    print(_b);
+                    return -1;
+                }
+
+                int code;
+                wait(&code);
+
+                char _b[128];
+                snprintf(_b, sizeof(_b), "sh (%d) # ", code);
+                print(_b);
+
+                j = 0;
+                k = 1;
+                memset(args, 0x00, sizeof(args));
+                args[0] = token;
+                continue;
+            }
+            token[j++] = buf[i];
+        }
+    }
+
+    return 0;
+}

+ 1 - 1
user-space-program/stack-test.s

@@ -13,4 +13,4 @@ main:
 	movl %ebp, %esp
 	popl %ebp
 
-	jmp .
+	ret