#include #include #include #include #include #include #include #include #include #include #include #include const char* shell_version = "0.0.2"; char* prompt = NULL; int command = -1; bool _debug = true; 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 %s David J Goeke\n", KERNEL_RELEASE_YEAR); } static char* commands[] = { "kinfo", "sseinfo", "kernelmem", "sectionmem", "enable_debug", "disable_debug", "toggle_debug", "get_debug", "dumpregs", "dumpgprs", "testascii", "printrandom", "testfat16", "printc", "testscheduler", "readfat16", "help", "exec", "int16test", NULL, }; const int NUM_COMMANDS = 19; /* Yes, including the NULL */ void kshell_start(void) { printf("Welcome to the kshell!\n"); prompt = strdup(">"); char* i = NULL; print_intro(); command = -1; do { printf("%s ", prompt); /*i = gets();*/ int j = 0; i = gets_new(&j); if (j == 0) { printf("Error?\n"); break; } i = strnlstrip(i); 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) { free(i); } printf("Goodbye!\n"); return; } /* static char* commands[] = { "kinfo", "sseinfo", "kernelmem", "sectionmem", "enable_debug", "disable_debug", "toggle_debug", "get_debug", "dumpregs", "dumpgprs", "testascii", "printrandom", "testfat16", 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: { 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; } case 13: { printf("Enter char to print in decimal: "); char* g = gets(); int val = atoi(g); if (*g == '\0') { printf("Empty string entered\n"); break; } printf("%c\n", (char) val); break; } case 14: { #if 0 void taskA() { while (1) printf("A"); } void taskB() { while (1) printf("B"); } create_task(taskA); create_task(taskB); #endif break; } case 15: { char* filename = "t.bin"; 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(filename, fat_name); retv = fat16_find_file(fat_name, &file); if (retv != 0) { printf("file %s could not be found\n", filename); break; } uint8_t buffer[256]; memset(buffer, 0, sizeof(buffer)); retv = fat16_read_file(&file, buffer); if (retv != 0) { printf("Could not read file s\n", (char*) filename); break; } printf("read data: %s\n", (char*) buffer); break; } case 16: { printf("Commands:\n"); for (int i = 0; i < NUM_COMMANDS; i++) { printf("%s\n", commands[i]); } break; } case 17: { char* filename = "hello.elf"; printf("Loading and executing file %s\n", filename); 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(filename, fat_name); retv = fat16_find_file(fat_name, &file); if (retv != 0) { printf("file %s could not be found\n", filename); break; } uint8_t* buffer = malloc(file.size); memset(buffer, 0, file.size); retv = fat16_read_file(&file, buffer); if (retv != 0) { printf("Could not read file s\n", (char*) filename); break; } printf("Parsing ELF headers\n"); elf_executable_t* f = load_elf32(buffer); printf("Attempting execution of executable...\n"); retv = f->entry_point(); printf("\nreturn value: %i\n", retv); break; } case 18: { printf("testing int 16\n"); const char* str = "HELLO!\n"; syscall1(SYS_TERMINAL_WRITESTRING, str); printf("test ran\n"); break; } } return 0; }