// // Created by rick on 23-02-21. // #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #include #ifdef ENABLE_SELF_TEST #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); #ifdef ENABLE_SELF_TEST void explode(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}, {"slingurl", slingurl}, #ifdef ENABLE_SELF_TEST {"self-test", exec_self_test}, {"smash", smash}, {"explode", explode}, #endif {NULL, NULL}, }; void slingurl(const char *args) { slingurl_decompose(args); } #ifdef ENABLE_SELF_TEST void smash(const char *args) { // smash the stack, should trigger the stack protector char data[16]; memset(data, 'A', 32); } 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 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 store_bootloader_info(multiboot_info_t *multiboot_info) { // get bootloader and cmdline if (multiboot_info->flags & MULTIBOOT_INFO_CMDLINE) { int 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) { int 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); } }