2020-01-09 18:32:12 +01:00
|
|
|
#ifndef SHELL_C
|
|
|
|
#define SHELL_C
|
|
|
|
|
|
|
|
#define SHELL_CMD_BUFFER_SIZE 128
|
|
|
|
|
|
|
|
#include <stddef.h>
|
|
|
|
|
|
|
|
#include "terminal.c"
|
2020-01-10 02:23:59 +01:00
|
|
|
#include "inline_asm.c"
|
2020-01-09 18:32:12 +01:00
|
|
|
#include "drivers/keyboard/keyboard.c"
|
2020-01-28 23:10:35 +01:00
|
|
|
#include "memory.c"
|
2020-01-09 18:32:12 +01:00
|
|
|
|
|
|
|
char buffer[SHELL_CMD_BUFFER_SIZE];
|
|
|
|
int buffer_idx = 0;
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int echo(char *input) {
|
2020-01-09 18:32:12 +01:00
|
|
|
terminal_writestring(input);
|
|
|
|
terminal_putchar('\n');
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int hello(char *unused) {
|
2020-01-09 18:32:12 +01:00
|
|
|
terminal_writestring("Hello, world!\n");
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int cls(char *unused) {
|
2020-01-09 18:32:12 +01:00
|
|
|
terminal_initialize();
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int get_gdt(char *unused) {
|
|
|
|
gdt_desc desc = {2, 2};
|
2020-01-10 02:23:59 +01:00
|
|
|
sgdt(&desc);
|
|
|
|
terminal_writestring("limit = ");
|
|
|
|
terminal_writeint(desc.limit, 10);
|
|
|
|
terminal_writestring("\nbase = 0x");
|
|
|
|
terminal_writeint(desc.base, 16);
|
|
|
|
terminal_putchar('\n');
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
gdt_entry *entries = (gdt_entry *) desc.base;
|
|
|
|
int num_entries = (desc.limit + 1) / 8;
|
2020-01-10 02:23:59 +01:00
|
|
|
for (int entry_num = 0; entry_num < num_entries; entry_num++) {
|
|
|
|
gdt_entry entry = entries[entry_num];
|
|
|
|
uint32_t base = entry.base_lower | entry.base_middle << 16 | entry.base_higher << 24;
|
|
|
|
uint32_t limit = entry.limit_lower | (entry.flags_limit_higher & 0x0f) << 16;
|
|
|
|
uint8_t flags = (entry.flags_limit_higher >> 4);
|
2020-01-10 10:05:19 +01:00
|
|
|
bool is_data = ((entry.access_byte & 0b00001000) >> 3) == 0;
|
2020-01-28 23:10:35 +01:00
|
|
|
|
2020-01-10 02:23:59 +01:00
|
|
|
//terminal_writestring("\nEntry ");
|
|
|
|
//terminal_writeint(entry_num, 10);
|
2020-01-28 23:10:35 +01:00
|
|
|
print("base = %x\n", base);
|
|
|
|
print("limit = %x\n", limit);
|
|
|
|
print("flags = %b\n", (entry.flags_limit_higher >> 4));
|
2020-01-10 02:23:59 +01:00
|
|
|
|
|
|
|
if ((flags & 0b1000) == 0) {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(" (byte granularity");
|
2020-01-10 02:23:59 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(" (page granularity");
|
2020-01-10 02:23:59 +01:00
|
|
|
}
|
|
|
|
|
|
|
|
if ((flags & 0b0100) == 0) {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(", 16 bit)");
|
2020-01-10 02:23:59 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(", 32 bit)");
|
2020-01-10 02:23:59 +01:00
|
|
|
}
|
2020-01-28 23:10:35 +01:00
|
|
|
print("\n");
|
2020-01-10 02:23:59 +01:00
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
print("access = %b (ring %d",
|
|
|
|
entry.access_byte,
|
|
|
|
(entry.access_byte & 0b01100000) >> 5
|
|
|
|
);
|
2020-01-10 10:05:19 +01:00
|
|
|
if ((entry.access_byte & 0b00010000) == 0) {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(", System");
|
2020-01-10 10:05:19 +01:00
|
|
|
}
|
|
|
|
if (is_data) {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(", Data");
|
2020-01-10 10:05:19 +01:00
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
if ((entry.access_byte & 0b00000100) == 0) {
|
|
|
|
print(" (growing up, ");
|
2020-01-10 10:05:19 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(" (growing down, ");
|
2020-01-10 10:05:19 +01:00
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
if ((entry.access_byte & 0b00000010) == 0) {
|
|
|
|
print("r--)");
|
2020-01-10 10:05:19 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print("rw-)");
|
2020-01-10 10:05:19 +01:00
|
|
|
}
|
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(", Code");
|
2020-01-10 10:05:19 +01:00
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
if ((entry.access_byte & 0b00000100) == 0) {
|
|
|
|
print(" (non-conforming, ");
|
2020-01-10 10:05:19 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print(" (conforming, ");
|
2020-01-10 10:05:19 +01:00
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
if ((entry.access_byte & 0b00000010) == 0) {
|
|
|
|
print("--x)");
|
2020-01-10 10:05:19 +01:00
|
|
|
} else {
|
2020-01-28 23:10:35 +01:00
|
|
|
print("r-x)");
|
2020-01-10 10:05:19 +01:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
print(")\n");
|
2020-01-10 02:23:59 +01:00
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int ree(char *unused) {
|
2020-01-09 18:32:12 +01:00
|
|
|
terminal_initialize();
|
|
|
|
terminal_putchar('R');
|
|
|
|
for (int i = 1; i < VGA_WIDTH * VGA_HEIGHT; i++) {
|
|
|
|
terminal_putchar('e');
|
|
|
|
}
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int save_text(char *text) {
|
2020-01-28 23:24:51 +01:00
|
|
|
char *mem_block = alloc(strlen(text) * sizeof(char));
|
|
|
|
char *c;
|
|
|
|
int i = 0;
|
|
|
|
for (c = text; *c != '\0'; c++) {
|
|
|
|
mem_block[i] = *c;
|
|
|
|
i++;
|
|
|
|
}
|
2020-01-28 23:10:35 +01:00
|
|
|
}
|
|
|
|
|
2020-01-10 09:28:31 +01:00
|
|
|
// TODO This is ugly, fix this
|
2020-01-28 23:10:35 +01:00
|
|
|
const char *shell_commands_strings[] = {
|
|
|
|
"echo",
|
|
|
|
"hello",
|
|
|
|
"cls",
|
|
|
|
"ree",
|
|
|
|
"getgdt",
|
|
|
|
"memdump",
|
2020-01-28 23:24:51 +01:00
|
|
|
"savetext",
|
2020-01-28 23:10:35 +01:00
|
|
|
NULL
|
2020-01-10 09:28:31 +01:00
|
|
|
};
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int (*shell_commands_functions[])(char *) = {
|
|
|
|
echo,
|
|
|
|
hello,
|
|
|
|
cls,
|
|
|
|
ree,
|
|
|
|
get_gdt,
|
|
|
|
command_mem_dump,
|
2020-01-28 23:24:51 +01:00
|
|
|
save_text
|
2020-01-10 09:28:31 +01:00
|
|
|
};
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
int run_command(char *buffer) {
|
2020-01-09 18:32:12 +01:00
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
if (buffer[0] == 0) {
|
2020-01-09 18:32:12 +01:00
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
char command[SHELL_CMD_BUFFER_SIZE] = {0};
|
|
|
|
int i = 0;
|
|
|
|
while (buffer[i] != 0 && buffer[i] != ' ') {
|
|
|
|
command[i] = buffer[i];
|
|
|
|
i++;
|
|
|
|
}
|
|
|
|
|
|
|
|
int command_idx = 0;
|
|
|
|
|
2020-01-28 23:10:35 +01:00
|
|
|
while (shell_commands_strings[command_idx] != NULL) {
|
2020-01-09 18:32:12 +01:00
|
|
|
int check_idx = 0;
|
2020-01-28 23:10:35 +01:00
|
|
|
while (command[check_idx] != 0 && shell_commands_strings[command_idx][check_idx] == command[check_idx]) {
|
2020-01-09 18:32:12 +01:00
|
|
|
check_idx++;
|
|
|
|
}
|
|
|
|
if (command[check_idx] == 0 && shell_commands_strings[command_idx][check_idx] == 0) {
|
|
|
|
return (shell_commands_functions[command_idx])(buffer + i + 1);
|
|
|
|
}
|
|
|
|
command_idx++;
|
|
|
|
}
|
|
|
|
return -1;
|
|
|
|
}
|
|
|
|
|
|
|
|
void shell_step() {
|
|
|
|
char curr_char = getchar();
|
|
|
|
|
|
|
|
if (curr_char == '\n') {
|
|
|
|
terminal_putchar(curr_char);
|
|
|
|
buffer[buffer_idx] = 0;
|
|
|
|
int result = run_command(buffer);
|
|
|
|
for (int i = 0; i < SHELL_CMD_BUFFER_SIZE; i++) {
|
|
|
|
buffer[i] = 0;
|
|
|
|
}
|
|
|
|
buffer_idx = 0;
|
|
|
|
|
|
|
|
if (result == -1) {
|
2020-01-28 23:10:35 +01:00
|
|
|
print("No such command\n");
|
2020-01-09 18:32:12 +01:00
|
|
|
}
|
|
|
|
} else if (curr_char == 0x08) {
|
|
|
|
if (buffer_idx != 0) {
|
|
|
|
buffer_idx--;
|
|
|
|
buffer[buffer_idx] = 0;
|
|
|
|
terminal_putchar(curr_char);
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
buffer[buffer_idx] = curr_char;
|
|
|
|
buffer_idx++;
|
|
|
|
terminal_putchar(curr_char);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
#endif //SHELL_C
|