306 lines
6.9 KiB
C
306 lines
6.9 KiB
C
//
|
|
// Created by rick on 23-02-21.
|
|
//
|
|
#ifdef ENABLE_K_SHELL
|
|
#include <attributes.h>
|
|
#include <stdbool.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <sys/types.h>
|
|
#include <readline/readline.h>
|
|
|
|
#include <myke/command.h>
|
|
#include <myke/cpu/pit.h>
|
|
#include <myke/drivers/pci/ide.h>
|
|
#include <myke/drivers/pci/pci.h>
|
|
#include <myke/vfs/blockdev.h>
|
|
#include <myke/vfs/part/mbr.h>
|
|
#include <myke/libk/libk.h>
|
|
#include <myke/mem/malloc.h>
|
|
#include <myke/mem/mem.h>
|
|
#include <myke/tasks/task.h>
|
|
#include <myke/util/power.h>
|
|
#include <myke/vfs/vfs.h>
|
|
|
|
#ifdef ENABLE_SELF_TEST
|
|
|
|
#include <myke/debug/debug.h>
|
|
#include <myke/util/slingurl.h>
|
|
#include <myke/libk/syscall.h>
|
|
#include <myke/util/init.h>
|
|
|
|
#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);
|
|
}
|
|
}
|
|
|
|
|
|
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 |