#include #include #include #include #include #include #include #include #include const char* shell_version = "0.0.2"; char* prompt = NULL; int command = -1; bool _debug = false; int execute(void); static void print_intro(void) { printf("Espresso kshell, ver %s on Espresso %s", shell_version, KERNEL_VERSION); #ifdef _DEBUG printf(" DEBUG BUILD"); #endif printf("\nSSE level: "); command = 1; execute(); extern char* get_cpu_vendor_string(void); extern char* get_cpu_brand_string(void); /* XXX: NOTE: these do not need freeing. */ char* temp_ = get_cpu_vendor_string(); char* _temp = get_cpu_brand_string(); printf("CPU: %s\n", _temp == NULL ? "No info" : _temp); printf("CPU vendor: %s\n", temp_ == NULL ? "No info" : temp_); printf("\nCopyright 2025 David J Goeke\n"); } static void parse_opts(int argc, char** argv) { for (int i = 0; i < argc; i++) { if (strcmp(argv[i], "--color") == 0) { } } } static char* commands[] = { "kinfo", "sseinfo", "kernelmem", "sectionmem", "enable_debug", "disable_debug", "toggle_debug", "get_debug", "dumpregs", "dumpgprs", "testascii", "printrandom", "acm", /* ACcess Memory */ "testfat16", NULL, }; #define NUM_COMMANDS 15 /* Yes, including the NULL */ int kshell_start(int argc, char** argv) { (void)argc; (void)argv; prompt = strdup(">"); char* i = NULL; print_intro(); command = -1; do { printf("%s ", prompt); i = gets(); command = -1; if (strcmp(i, "") == 0) { continue; } else if (strcmp(i, "exit") == 0 || strcmp(i, "quit") == 0) { break; } for (int j = 0; j < NUM_COMMANDS; j++) { if (strcmp(i, commands[j]) == 0) { command = j; break; } } if (command == -1) { printf("Unknown command %s len %i\n", i, strlen(i)); } else if (command == 4) { _debug = true; } else if (command == 5) { _debug = false; } else if (command == 6) { _debug = !_debug; } else if (command == 7) { printf("Debugging: %s\n", _debug == true ? "On" : "Off"); } if (_debug) { printf(" ASCII -> "); size_t len = strlen(i) + 1; for (size_t n = 0; n < len; n++) { printf("%02X ", (int) i[n]); } printf("\n"); } printf("C: %s; %i\n", commands[command], command); execute(); } while (1); if (i != NULL) { free(i); } printf("Goodbye!\n"); return 0; } /* static char* commands[] = { "kinfo", "sseinfo", "kernelmem", "sectionmem", "enable_debug", "disable_debug", "toggle_debug", "get_debug", "dumpregs", "dumpgprs", "testascii", "printrandom", "acm", NULL, }; */ int execute(void) { switch (command) { case 0: { printf("Espresso %s ", KERNEL_VERSION); #ifdef _DEBUG printf("DEBUG BUILD"); #endif printf("\n"); break; } case 1: { extern int sse_initialized; switch (sse_initialized) { case 0: printf("No SSE support"); break; case 1: printf("SSE1"); break; case 2: printf("SSE2"); break; case 3: printf("SSE3"); break; case 4: printf("SSSE3"); break; case 5: printf("SSE4.1"); break; case 6: printf("SSE4.2"); break; default: printf("WARNING: sse_initialized is in a invalid state!"); break; } printf("\n"); break; } case 2: { extern uint8_t __kernel_start; extern uint8_t __kernel_end; size_t kernel_size = (size_t)&__kernel_end - (size_t)&__kernel_start; printf("Kernel start: 0x%x\n", (&__kernel_start)); printf("Kernel end: 0x%x\n", (&__kernel_end)); printf("Kernel size (bytes): %llu\n", (uint64_t) kernel_size); printf("Kernel size (kbytes): %llu\n", (((uint64_t) kernel_size) / 1000)); printf("Kernel size (mbytes): %f\n", (((uint64_t) kernel_size) / 1000.0) / 1000.0); break; } case 3: { extern uint8_t __kernel_text_start; extern uint8_t __kernel_text_end; extern uint8_t __kernel_rodata_start; extern uint8_t __kernel_rodata_end; extern uint8_t __kernel_data_start; extern uint8_t __kernel_data_end; extern uint8_t __bss_start; extern uint8_t __bss_end; printf(".text: %i\n.data: %i\n.rodata: %i\n.bss: %i\n", ((&__kernel_text_end) - (&__kernel_text_start)), ((&__kernel_data_end) - (&__kernel_data_start)), ((&__kernel_rodata_end) - (&__kernel_rodata_start)), ((&__bss_end) - (&__bss_start))); break; } case 8: { print_all_regs(); break; } case 9: { print_gprs(); break; } case 10: { /*extern void terminal_clear(void);*/ terminal_clear(); printf("Printing ASCII chars 0x00 through 0xFE, hit enter to exit\n"); sleep(2500); terminal_clear(); for (int i = 0x00; i < 0xFF; i++) { printf("%c", (char) i); } printf("\n\n\\/ Cool ASCII art \\/\n%c%c\n%c%c\n", 0xDA, 0xBF, 0xC0, 0xD9); gets(); break; } case 11: { extern void seed_rand(uint32_t seed); extern uint32_t ulrand(void); uint64_t v = rdtsc(); seed_rand((uint32_t) v); printf("%ull\n", ulrand()); break; } case 12: { printf("Enter hexadecimal address to access: "); char* g = gets(); int val = atoi(g); if (val == 0) { printf("Improper/Malformed string entered\n"); break; } else if (val < 0x100000) { printf("Invalid address, must be higher than 0x100000\n"); break; } int val_ = *((int*) val); printf("value at %u: %i\n", val, val_); break; } case 13: { int retv = fat16_mount(0); if (retv != 0) { printf("There was an error while mounting volume 0.\n"); break; } printf("Volume 0 mounted successfully.\n"); char fat_name[12]; fat16_file_t file; filename_to_83("test.txt", fat_name); retv = fat16_create_file(fat_name, &file); if (retv != 0) { printf("There was an error while creating a file on volume 0.\n"); break; } uint8_t buf[512]; memset(buf, 0, sizeof(buf)); strcpy((char*) buf, "fg"); retv = fat16_write_file(&file, buf, (strlen((char*) buf))); if (retv != 0) { printf("There was an error while writing to a file on volume 0.\n"); break; } uint8_t rbuf[512]; memset(rbuf, 0, sizeof(rbuf)); retv = fat16_read_file(&file, rbuf); if (retv != 0) { printf("There was an error while reading from a file on volume 0.\n"); break; } printf("The data read should be: %s\n", (char*) buf); printf("Read data: %s\n", (char*) rbuf); printf("Deleting test file\n"); fat16_delete_file(fat_name); break; } } return 0; }