2025-10-20 21:57:30 -05:00
|
|
|
#include <string.h>
|
|
|
|
|
#include <stdlib.h>
|
|
|
|
|
#include <stdio.h>
|
|
|
|
|
#include <drivers/ps2_keyboard.h>
|
|
|
|
|
#include <tty.h>
|
|
|
|
|
#include <kernel/ksh_debug.h>
|
2026-02-12 20:33:46 -06:00
|
|
|
#include <arch/x86/intrin.h>
|
|
|
|
|
|
|
|
|
|
#include <fs/fat16.h>
|
2025-10-20 21:57:30 -05:00
|
|
|
|
|
|
|
|
#include <kernel/kshell.h>
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
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: ");
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
command = 1;
|
2025-10-20 21:57:30 -05:00
|
|
|
|
|
|
|
|
execute();
|
|
|
|
|
|
|
|
|
|
extern char* get_cpu_vendor_string(void);
|
|
|
|
|
extern char* get_cpu_brand_string(void);
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
/* XXX: NOTE: these do not need freeing. */
|
2025-10-20 21:57:30 -05:00
|
|
|
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)
|
|
|
|
|
{
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
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 */
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
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;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
|
|
|
|
|
for (int j = 0; j < NUM_COMMANDS; j++)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
2026-02-12 20:33:46 -06:00
|
|
|
if (strcmp(i, commands[j]) == 0)
|
|
|
|
|
{
|
|
|
|
|
command = j;
|
|
|
|
|
break;
|
|
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
|
|
|
|
|
if (command == -1)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
2026-02-12 20:33:46 -06:00
|
|
|
printf("Unknown command %s len %i\n", i, strlen(i));
|
2025-10-20 21:57:30 -05:00
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
else if (command == 4)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
|
|
|
|
_debug = true;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
else if (command == 5)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
|
|
|
|
_debug = false;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
else if (command == 6)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
|
|
|
|
_debug = !_debug;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
else if (command == 7)
|
2025-10-20 21:57:30 -05:00
|
|
|
{
|
|
|
|
|
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");
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
printf("C: %s; %i\n", commands[command], command);
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
execute();
|
|
|
|
|
|
|
|
|
|
} while (1);
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
if (i != NULL)
|
|
|
|
|
{
|
|
|
|
|
free(i);
|
|
|
|
|
}
|
2025-10-20 21:57:30 -05:00
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
printf("Goodbye!\n");
|
2025-10-20 21:57:30 -05:00
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
/*
|
|
|
|
|
static char* commands[] = {
|
|
|
|
|
"kinfo",
|
|
|
|
|
"sseinfo",
|
|
|
|
|
"kernelmem",
|
|
|
|
|
"sectionmem",
|
|
|
|
|
|
|
|
|
|
"enable_debug",
|
|
|
|
|
"disable_debug",
|
|
|
|
|
"toggle_debug",
|
|
|
|
|
"get_debug",
|
|
|
|
|
|
|
|
|
|
"dumpregs",
|
|
|
|
|
"dumpgprs",
|
|
|
|
|
|
|
|
|
|
"testascii",
|
|
|
|
|
|
|
|
|
|
"printrandom",
|
|
|
|
|
|
|
|
|
|
"acm",
|
|
|
|
|
|
|
|
|
|
NULL,
|
|
|
|
|
};
|
|
|
|
|
*/
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
int execute(void)
|
|
|
|
|
{
|
|
|
|
|
switch (command)
|
|
|
|
|
{
|
|
|
|
|
case 0: {
|
2026-02-12 20:33:46 -06:00
|
|
|
printf("Espresso %s ", KERNEL_VERSION);
|
|
|
|
|
|
|
|
|
|
#ifdef _DEBUG
|
|
|
|
|
printf("DEBUG BUILD");
|
|
|
|
|
#endif
|
|
|
|
|
|
|
|
|
|
printf("\n");
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 1: {
|
2025-10-20 21:57:30 -05:00
|
|
|
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;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
case 3: {
|
2025-10-20 21:57:30 -05:00
|
|
|
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;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
case 8: {
|
|
|
|
|
print_all_regs();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 9: {
|
|
|
|
|
print_gprs();
|
|
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
case 10: {
|
2025-10-20 21:57:30 -05:00
|
|
|
/*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);
|
|
|
|
|
}
|
|
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
printf("\n\n\\/ Cool ASCII art \\/\n%c%c\n%c%c\n", 0xDA, 0xBF, 0xC0, 0xD9);
|
2025-10-20 21:57:30 -05:00
|
|
|
|
|
|
|
|
gets();
|
|
|
|
|
|
|
|
|
|
break;
|
|
|
|
|
}
|
2026-02-12 20:33:46 -06:00
|
|
|
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());
|
2025-10-20 21:57:30 -05:00
|
|
|
|
2026-02-12 20:33:46 -06:00
|
|
|
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);
|
|
|
|
|
|
2025-10-20 21:57:30 -05:00
|
|
|
break;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|