// // Created by rick on 23-02-21. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_SELF_TEST #include #include #include #include #endif #define BOOTLOADER_NAME_MAX_LENGTH 64 #define CMDLINE_MAX_LENGTH 256 char bootloader_name[BOOTLOADER_NAME_MAX_LENGTH]; char cmdline[CMDLINE_MAX_LENGTH]; typedef void (*cmd_handler_func)(const char *); typedef struct { char *cmd; cmd_handler_func handler; } cmd_handler; void print(const char *arg); void ide(const char *arg); void echo(const char *arg); void help(const char *args); void shutdown(const char *args); void ps(const char *args); void mount(const char *args); void ls(const char *args); void cat(const char *args); #ifdef ENABLE_SELF_TEST void explode(const char *args); void kill_self(const char *args); void exec_self_test(const char *args); void smash(const char *args); void slingurl(const char *args); #endif cmd_handler cmd_handlers[] = { {"help", help}, {"echo", echo}, {"print", print}, {"ide", ide}, {"shutdown", shutdown}, {"ps", ps}, {"mount", mount}, {"ls", ls}, {"cat", cat}, #ifdef ENABLE_SELF_TEST {"slingurl", slingurl}, {"kill-self", kill_self}, {"self-test", exec_self_test}, {"smash", smash}, {"explode", explode}, #endif {NULL, NULL}, }; #ifdef ENABLE_SELF_TEST void slingurl(const char *args) { slingurl_decompose(args); } void smash(const char *args) { // smash the stack, should trigger the stack protector char data[16]; memset(data, 'A', 32); } void kill_self(const char *args) { syscall_kill_self(); } void exec_self_test(const char *args) { // unit tests self_test(); } void explode(const char *args) { // trigger a divide by zero exception uint32_t x = 0; uint32_t y = 0; __asm__("div %%ebx" : "=a" (x), "=b" (y)); } #endif void shutdown(const char *args) { power_shutdown(); } void ps(const char *args) { task_print_all(); } void print_bootinfo() { printf("Bootloader name: %s\n" "cmdline: %s\n", (bootloader_name[0] == 0 ? "NULL" : bootloader_name), (cmdline[0] == 0 ? "NULL" : cmdline)); } void help(const char *arg) { printf("Available commands:\n"); int index = 0; while (true) { if (cmd_handlers[index].cmd == NULL) { break; } printf("%s\n", cmd_handlers[index].cmd); index += 1; } } void echo(const char *arg) { printf("%s\n", arg); } void print(const char *arg) { if (strcmp(arg, "mmap") == 0) { print_mmap_info(); } else if (strcmp(arg, "malloc") == 0) { print_malloc_info(); } else if (strcmp(arg, "tick") == 0) { print_current_tick(); } else if (strcmp(arg, "bootinfo") == 0) { print_bootinfo(); } else if (strcmp(arg, "pci") == 0) { pci_print_info(); } else if (strcmp(arg, "pci_caps") == 0) { pci_dump_caps(); #ifdef ENABLE_PCIPP } else if (strcmp(arg, "pcipp") == 0) { pci_pretty_print(); #endif } else if (strcmp(arg, "ide") == 0) { ide_print_devices(); } else { printf("Unknown print %s\n", arg); } } void ide(const char *arg) { if (strcmp(arg, "block_devices") == 0) { block_dev_print_info(); } else if (strcmp(arg, "ide_devices") == 0) { ide_print_devices(); } else if (strcmp(arg, "mbr") == 0) { mbr_read_from_ide(0); } else { printf("Unknown print %s\n", arg); } } void mount(const char *arg) { vfs_mount("/", "ide0p0", "ext2"); } void ls(const char *arg) { vfs_fd_t *fd = vfs_open("/", 0, 0); if (fd == NULL) { printf("could not open /\n"); return; } void *data = malloc(1024); if (data == NULL) { printf("malloc fail\n"); vfs_close(fd); return; } uint32_t num = 0; while ((num = vfs_getdents(fd, data, 1024)) > 0) { vfs_dirent_t *ent = data; while (true) { printf("%s\n", ent->name); if (ent->offset_next >= 1024) { break; } ent = &data[ent->offset_next]; } } free(data); vfs_close(fd); } void cat(const char *arg) { vfs_fd_t *fd = vfs_open("/sda1", 0, 0); vfs_close(fd); fd = vfs_open("/test.txt", 0, 0); if (fd == NULL) { printf("could not open /test.txt\n"); return; } char *data = malloc(1024); if (data == NULL) { printf("no mem\n"); vfs_close(fd); return; } int read = vfs_read(fd, data, 1024); if (read < 0) { printf("Failed to read\n"); } else if (read == 0) { printf("emtpy file\n"); } else { printf("first 10 chars %10s\n", data); } free(data); vfs_close(fd); } void store_bootloader_info(multiboot_info_t *multiboot_info) { // get bootloader and cmdline if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) { size_t cmdline_length = strlen((const char *) multiboot_info->cmdline); if (cmdline_length > CMDLINE_MAX_LENGTH) { k_panics("cmdline to long!\n"); } memcpy(cmdline, (char *) multiboot_info->cmdline, cmdline_length); } if (multiboot_info->flags & MULTIBOOT_INFO_BOOT_LOADER_NAME) { size_t bootloader_length = strlen((const char *) multiboot_info->boot_loader_name); if (bootloader_length > BOOTLOADER_NAME_MAX_LENGTH) { k_panics("bootloader name to long!\n"); } memcpy(bootloader_name, (char *) multiboot_info->boot_loader_name, bootloader_length); } } void att_noreturn main_loop(void *data) { while (true) { char *msg = readline(NULL); char *args = strchr(msg, ' '); args[0] = 0; args = &args[1]; int test_index = 0; while (true) { if (cmd_handlers[test_index].cmd == 0) { printf("Unknown command: %s\n", msg); break; } if (strcmp(cmd_handlers[test_index].cmd, msg) == 0) { cmd_handlers[test_index].handler(args); break; } test_index++; } free(msg); } } #ifdef K_SHELL void main_loop_start() { task_spawn(main_loop, NULL, "main"); } INIT_FUNCTION(100) = { .name = "main-task", .stage = INIT_STAGE_PRE_TASKING, .init = main_loop_start, }; #endif