Преглед изворни кода

[Feat] Add VMProcess Package

xcbosa mbp16 пре 5 месеци
родитељ
комит
64a4538e4d

+ 11 - 0
package/0xcvmkitosboot/0xcvmkitosboot.mk

@@ -0,0 +1,11 @@
+MYTOOL_VERSION = 1.0
+MYTOOL_SITE = ./package/0xcvmkitosboot/src
+MYTOOL_SITE_METHOD = local
+
+define MYTOOL_BUILD_CMDS
+	$(MAKE) CC="$(TARGET_CC)" LD="$(TARGET_LD)" -C $(@D)
+endef
+
+define MYTOOL_INSTALL_TARGET_CMDS
+	$(INSTALL) -D -m 0755 $(@D)/xcvmkitosroot $(TARGET_DIR)/sbin/xcvmkitosroot
+endef

+ 4 - 0
package/0xcvmkitosboot/Config.in

@@ -0,0 +1,4 @@
+config BR2_PACKAGE_0xcvmkitosboot
+    bool "0xcvmkitosboot"
+    help
+        XCVMKitOSBootLoader

+ 7 - 0
package/0xcvmkitosboot/src/Makefile

@@ -0,0 +1,7 @@
+all: xcvmkitosroot
+
+xcvmkitosroot: vmprocess.c
+    $(CC) $^ -o $@
+
+clean:
+    rm -f xcvmkitosroot

+ 400 - 0
package/0xcvmkitosboot/src/vmprocess.c

@@ -0,0 +1,400 @@
+#include <stdio.h>
+#include <pthread.h>
+#include <unistd.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <fcntl.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <string.h>
+#include <spawn.h>
+#include <sys/wait.h>
+#include <signal.h>
+#include <pty.h>
+#include <termios.h>
+#include <sys/ioctl.h>
+
+#define POSIX_SPAWN_SETSID              0x0400
+#define DEBUG 0
+#define VMP_DEVICE_RX "/etc/.vmpdrvfna_rx"
+#define VMP_DEVICE_TX "/etc/.vmpdrvfna_tx"
+#define VMP_TID_MAX 64
+#define VMP_TX_POOL_SIZE 64
+#define VMP_STRBUF_LEN 128
+
+typedef struct {
+    short width;
+    short height;
+    short xpixel;
+    short ypixel;
+} rx_command_win_size;
+
+typedef enum {
+    rx_command_type_runproc,
+    rx_command_type_killproc,
+    rx_command_type_lsproc,
+    rx_command_type_sstdin,
+    rx_command_type_winsize,
+    rx_command_type_ping
+} rx_command_type;
+
+typedef struct {
+    rx_command_type type;
+    int8_t tid;
+    int signal;
+    long magic;
+    char sstdin[VMP_STRBUF_LEN];
+    int sstdin_len;
+    rx_command_win_size win_size;
+} rx_command;
+
+typedef enum {
+    tx_command_type_online,
+    tx_command_type_stdout,
+    tx_command_type_cb,
+    tx_command_type_stoped
+} tx_command_type;
+
+typedef struct {
+    tx_command_type type;
+    int8_t tid;
+    int8_t error;
+    long magic;
+    char sstdout[VMP_STRBUF_LEN];
+    int sstdout_len;
+} tx_command;
+
+typedef int FD;
+typedef int pipe_t[2];
+
+typedef struct {
+    int8_t tid;
+    int8_t inuse;
+    char command[VMP_STRBUF_LEN];
+    pid_t pid;
+    pthread_t io_thread;
+    int master_pty;
+    int slave_pty;
+    FD stdin_fd;
+    rx_command_win_size win_size;
+} management_process;
+
+void debug_print_rx(rx_command rx) {
+#if DEBUG
+    printf("RX: (type=%d tid=%d signal=%d magic=%ld sstdin=%s)\n", rx.type, rx.tid, rx.signal, rx.magic, rx.sstdin);
+#endif
+}
+
+void debug_print_tx(tx_command tx) {
+#if DEBUG
+    printf("TX: (type=%d tid=%d error=%d magic=%ld sstdout=%s)\n", tx.type, tx.tid, tx.error, tx.magic, tx.sstdout);
+#endif
+}
+
+static FD RX, TX;
+static management_process processes[VMP_TID_MAX];
+static pthread_mutex_t processes_lock;
+static tx_command tx_cmds[VMP_TX_POOL_SIZE];
+static int tx_cmds_ptr = 0;
+static pthread_mutex_t tx_lock;
+
+void *tx_thread(void *ptr) {
+    while (1) {
+        pthread_mutex_lock(&tx_lock);
+        for (int i = 0; i < tx_cmds_ptr; i++) {
+            write(TX, &tx_cmds[i], sizeof(tx_command));
+        }
+        tx_cmds_ptr = 0;
+        pthread_mutex_unlock(&tx_lock);
+        usleep(100);
+    }
+}
+
+void tx_push(tx_command cmd) {
+    debug_print_tx(cmd);
+    pthread_mutex_lock(&tx_lock);
+    while (tx_cmds_ptr >= VMP_TX_POOL_SIZE) {
+        pthread_mutex_unlock(&tx_lock);
+        usleep(100);
+        pthread_mutex_lock(&tx_lock);
+    }
+    tx_cmds[tx_cmds_ptr++] = cmd;
+    pthread_mutex_unlock(&tx_lock);
+}
+
+#define CB_SUCC "succ"
+#define CB_NO_TID "no_tid"
+#define CB_NO_PTY "no_pty"
+#define CB_TID_KILLED "tid_killed"
+#define CT_LAUNCH_FAIL "launch_fail"
+#define CT_PUSH(ptype, pmagic, ptid, perror, reason) \
+{ \
+    tx_command ct_cmd = { \
+        .type = ptype, \
+        .tid = ptid, \
+        .error = perror, \
+        .magic = pmagic, \
+        .sstdout_len = strlen(reason) \
+    }; \
+    bzero(&ct_cmd.sstdout[0], VMP_STRBUF_LEN); \
+    memcpy(&ct_cmd.sstdout[0], reason, strlen(reason)); \
+    tx_push(ct_cmd); \
+}
+#define CB_PUSH(pmagic, pterror, reason) CT_PUSH(tx_command_type_cb, pmagic, 0, pterror, reason)
+
+void *mproc_io_thread(management_process *mproc) {
+    char slave_name[256];
+    if (openpty(&mproc->master_pty, &mproc->slave_pty, 
+               slave_name, NULL, &mproc->win_size) == -1) {
+        CT_PUSH(tx_command_type_stoped, 0, mproc->tid, 1, CB_NO_PTY);
+        mproc->inuse = 0;
+        return NULL;
+    }
+
+    struct termios tios;
+    tcgetattr(mproc->slave_pty, &tios);
+    tios.c_lflag &= ~(ECHO | ICANON);
+    tcsetattr(mproc->slave_pty, TCSANOW, &tios);
+
+    posix_spawn_file_actions_t actions;
+    posix_spawnattr_t attr;
+    posix_spawn_file_actions_init(&actions);
+    posix_spawnattr_init(&attr);
+    posix_spawn_file_actions_adddup2(&actions, mproc->slave_pty, STDIN_FILENO);
+    posix_spawn_file_actions_adddup2(&actions, mproc->slave_pty, STDOUT_FILENO);
+    posix_spawn_file_actions_adddup2(&actions, mproc->slave_pty, STDERR_FILENO);
+    posix_spawn_file_actions_addclose(&actions, mproc->master_pty);
+    posix_spawnattr_setflags(&attr, POSIX_SPAWN_SETSID | POSIX_SPAWN_SETPGROUP);
+    
+    setenv("TERM", "xterm-256color", 1);
+    setenv("COLORTERM", "truecolor", 1);
+
+    char *const argv[] = { "/bin/sh", "-c", mproc->command, NULL };
+    char *const environment[] = {
+        "TERM=xterm-256color", 
+        "COLORTERM=truecolor",
+        NULL
+    };
+
+    int ret = posix_spawnp(&mproc->pid, argv[0], &actions, &attr, argv, environment);
+    close(mproc->slave_pty);
+
+    posix_spawn_file_actions_destroy(&actions);
+    posix_spawnattr_destroy(&attr);
+
+    pthread_mutex_unlock(&processes_lock);
+
+    if (ret != 0) {
+        close(mproc->master_pty);
+        CT_PUSH(tx_command_type_stoped, ret, mproc->tid, 1, CT_LAUNCH_FAIL);
+        mproc->inuse = 0;
+        return NULL;
+    }
+
+    fcntl(mproc->master_pty, F_SETFL, O_NONBLOCK);
+    mproc->stdin_fd = mproc->master_pty;
+
+    char buf[VMP_STRBUF_LEN];
+    ssize_t nread;
+    const char *exit_reason = "unknown";
+    int8_t exit_error = 0;
+    int64_t exit_magic = 0;
+
+    while (1) {
+        do {
+            bzero(buf, sizeof(buf));
+            nread = read(mproc->master_pty, buf, sizeof(buf));
+            if (nread > 0) {
+                tx_command cmd = {
+                    .type = tx_command_type_stdout,
+                    .tid = mproc->tid,
+                    .error = 0,
+                    .magic = 0,
+                    .sstdout_len = nread
+                };
+                bzero(&cmd.sstdout[0], VMP_STRBUF_LEN);
+                memcpy(cmd.sstdout, buf, nread);
+                tx_push(cmd);
+            }
+        }
+        while (nread == sizeof(buf)); // has next unread
+
+        int pid_status;
+        pid_t result = waitpid(mproc->pid, &pid_status, WNOHANG);
+        if (result == -1) {
+            exit_reason = "err_waitpid";
+            break;
+        }
+        if (result != 0) {
+            if (WIFEXITED(pid_status)) {
+                exit_reason = "normal";
+                exit_magic = WEXITSTATUS(pid_status);
+            }
+            else if (WIFSIGNALED(pid_status)) {
+                exit_reason = "sig";
+                exit_error = WIFSIGNALED(pid_status);
+            }
+            else {
+                exit_reason = "exit_unknown";
+            }
+            break;
+        }
+        usleep(100);
+    }
+
+    CT_PUSH(tx_command_type_stoped, exit_magic, mproc->tid, exit_error, exit_reason);
+    mproc->inuse = 0;
+}
+
+int8_t find_unused_mproc_nolock() {
+    for (int8_t tid = 0; tid < VMP_TID_MAX; tid++) {
+        if (!processes[tid].inuse) {
+            bzero(&processes[tid], sizeof(management_process));
+            return tid;
+        }
+    }
+    return -1;
+}
+
+void rx_process(rx_command cmd) {
+    debug_print_rx(cmd);
+    switch (cmd.type) {
+        case rx_command_type_runproc: {
+            pthread_mutex_lock(&processes_lock);
+            int8_t tid = find_unused_mproc_nolock();
+            if (tid < 0) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_NO_TID);
+                break;
+            }
+
+            management_process mproc;
+            bzero(&mproc, sizeof(management_process));
+            memcpy(&mproc.command[0], cmd.sstdin, sizeof(mproc.command));
+
+            mproc.tid = tid;
+            mproc.inuse = 1;
+            processes[tid] = mproc;
+            mproc.win_size = cmd.win_size;
+
+            CT_PUSH(tx_command_type_cb, cmd.magic, tid, 0, CB_SUCC);
+            pthread_create(&mproc.io_thread, NULL, &mproc_io_thread, &processes[tid]);
+            // processes_lock will unlock in mproc_io_thread
+            break;
+        }
+        case rx_command_type_killproc: {
+            if (cmd.tid < 0 || cmd.tid >= VMP_TID_MAX) {
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            pthread_mutex_lock(&processes_lock);
+            management_process *mproc = &processes[cmd.tid];
+            if (!mproc->inuse) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            
+            kill(mproc->pid, SIGKILL);
+            pthread_mutex_unlock(&processes_lock);
+            CB_PUSH(cmd.magic, 0, CB_SUCC);
+            break;
+        }
+        case rx_command_type_lsproc: {
+            char bytemap[VMP_TID_MAX];
+            bzero(bytemap, sizeof(bytemap));
+            pthread_mutex_lock(&processes_lock);
+            for (int tid = 0; tid < VMP_TID_MAX; tid++) {
+                bytemap[tid] = processes[tid].inuse;
+            }
+            pthread_mutex_unlock(&processes_lock);
+            tx_command tx = {
+                .type = tx_command_type_cb,
+                .tid = 0,
+                .error = 0,
+                .magic = cmd.magic,
+                .sstdout_len = VMP_TID_MAX
+            };
+            bzero(&tx.sstdout, VMP_STRBUF_LEN);
+            memcpy(&tx.sstdout, bytemap, VMP_TID_MAX);
+            tx_push(tx);
+            break;
+        }
+        case rx_command_type_sstdin: {
+            if (cmd.tid < 0 || cmd.tid >= VMP_TID_MAX) {
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            pthread_mutex_lock(&processes_lock);
+            management_process *mproc = &processes[cmd.tid];
+            if (!mproc->inuse) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            write(mproc->stdin_fd, cmd.sstdin, cmd.sstdin_len);
+            pthread_mutex_unlock(&processes_lock);
+            CB_PUSH(cmd.magic, 0, CB_SUCC);
+            break;
+        }
+        case rx_command_type_winsize: {
+            if (cmd.tid < 0 || cmd.tid >= VMP_TID_MAX) {
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            pthread_mutex_lock(&processes_lock);
+            management_process *mproc = &processes[cmd.tid];
+            if (!mproc->inuse) {
+                pthread_mutex_unlock(&processes_lock);
+                CB_PUSH(cmd.magic, 1, CB_TID_KILLED);
+                break;
+            }
+            ioctl(mproc->stdin_fd, TIOCGWINSZ, &cmd.win_size);
+            pthread_mutex_unlock(&processes_lock);
+            CB_PUSH(cmd.magic, 0, CB_SUCC);
+            break;
+        }
+        case rx_command_type_ping: {
+            CB_PUSH(cmd.magic, 0, "PONG");
+            break;
+        }
+    }
+}
+
+int main() {
+    printf("Boot Success\n");
+    printf("Welcome to XCVMKit-OS!\n");
+    RX = open(VMP_DEVICE_RX, 1101824);
+    TX = open(VMP_DEVICE_TX, 1101825);
+    if (RX < 0) {
+        printf("vmp: unable to open rx");
+        return -1;
+    }
+    if (TX < 0) {
+        printf("vmp: unable to open tx");
+        return -1;
+    }
+    pthread_mutex_init(&tx_lock, NULL);
+    pthread_mutex_init(&processes_lock, NULL);
+    pthread_t tx_thr;
+    pthread_create(&tx_thr, NULL, tx_thread, NULL);
+    
+    tx_command initial_cmd = {
+        .type = tx_command_type_online,
+        .tid = 0,
+        .magic = 0,
+        .sstdout_len = 0
+    };
+    bzero(&initial_cmd.sstdout, VMP_STRBUF_LEN);
+    tx_push(initial_cmd);
+
+    while (1) {
+        rx_command command;
+        size_t read_size = read(RX, &command, sizeof(rx_command));
+        if (read_size == sizeof(rx_command)) {
+            rx_process(command);
+        }
+        usleep(100);
+    }
+    return 0;
+}

+ 1 - 0
package/Config.in

@@ -8,6 +8,7 @@ menu "Target packages"
 	source "package/skeleton-init-openrc/Config.in"
 	source "package/skeleton-init-systemd/Config.in"
 	source "package/skeleton-init-sysv/Config.in"
+	source "package/0xcvmkitosboot/Config.in"
 
 menu "Audio and video applications"
 	source "package/alsa-utils/Config.in"