diff --git a/.gitignore b/.gitignore index f161ad5..922937d 100644 --- a/.gitignore +++ b/.gitignore @@ -111,4 +111,5 @@ modules.xml # End of https://www.toptal.com/developers/gitignore/api/cmake,jetbrains+all -*.old \ No newline at end of file +*.old +**/__pycache__ \ No newline at end of file diff --git a/kernel/drivers/keyboard.c b/kernel/drivers/keyboard.c index dc0d5fe..e059ea0 100644 --- a/kernel/drivers/keyboard.c +++ b/kernel/drivers/keyboard.c @@ -7,31 +7,142 @@ #include #include #include +#include +#include +#include -char scancodes_ascii[] = { - 0, 0, - '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, - 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0, - 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', - 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, - '*', - 0, ' ', - 0, - 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10 - 0, 0, - '7', '8', '9', '-', - '4', '5', '6', '+', - '1', '2', '3', - '0', 0, - 0, // sysrq - 0, 0, // weird - 0, 0, // F11 F12 - // weid + +const char scancode_map_lowercase[] = { + 0, 0, '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', 0, 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', 0, '\\', 'z', 'x', 'c', + 'v', 'b', 'n', 'm', ',', '.', '/', 0, 0, 0, ' ', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0 }; +const char scancode_map_uppercase[] = { + 0, 0, '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', '_', '+', 0, 0, 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', + 'O', 'P', '{', '}', 0, 0, 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', ':', '"', '~', 0, '|', 'Z', 'X', 'C', + 'V', 'B', 'N', 'M', '<', '>', '?', 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0 +}; + +// +//char scancodes_ascii[] = { +// 0, 0, +// '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', '-', '=', 0, +// 0, 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', '[', ']', 0, +// 0, 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', '\'', '`', +// 0, '\\', 'z', 'x', 'c', 'v', 'b', 'n', 'm', ',', '.', '/', 0, +// '*', +// 0, ' ', +// 0, +// 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // F1-F10 +// 0, 0, +// '7', '8', '9', '-', +// '4', '5', '6', '+', +// '1', '2', '3', +// '0', 0, +// 0, // sysrq +// 0, 0, // weird +// 0, 0, // F11 F12 +// // weid +//}; + +struct { + u8 shift: 1; + u8 ctrl: 1; + u8 alt: 1; + u8 extended: 1; +} keyboard_state; + +void *keyboard_event_buffer = NULL; + char *MSG_KEY = "Clicked on key 'x'\n"; -void print_scancode(unsigned char scancode); +char getc() { + while (true) { + KeyEvent* event = get_next_event(); + char retval = 0; + if (event == NULL) { + goto _getc_end; + } + if (event->is_release) { + goto _getc_end; + } + if (event->scancode == 0x1C) { + retval = '\n'; + goto _getc_end; + } + if (event->ascii_code != 0) { + retval = event->ascii_code; + goto _getc_end; + } + _getc_end: + free_event(event); + if (retval != 0) { + return retval; + } + } +} + +KeyEvent *get_next_event() { + KeyEvent *target = malloc(sizeof(KeyEvent)); + if (!ring_buffer_get(keyboard_event_buffer, target)) { + free(target); + return NULL; + } + return target; +}; + +void free_event(KeyEvent *event) { + free(event); +} + +//void print_scancode(unsigned char scancode); + +void handle_modifier_keys(unsigned char scancode, bool is_release) { + switch (scancode) { + case 42: + case 54: + keyboard_state.shift = !is_release; + break; + case 29: + keyboard_state.ctrl = !is_release; + break; + case 56: + keyboard_state.alt = !is_release; + break; + default: + // not an modifier key + break; + } +} + +void publish_key_event(unsigned char scan_code) { + bool is_release = false; + if (scan_code > 0x80) { + is_release = true; + scan_code -= 0x80; + } + handle_modifier_keys(scan_code, is_release); + + char ascii_char = scancode_map_lowercase[scan_code]; + if (keyboard_state.shift) { + if (scancode_map_uppercase[scan_code] != 0) { + ascii_char = scancode_map_uppercase[scan_code]; + } + } + + KeyEvent event = { + .scancode = scan_code, + .ascii_code = ascii_char, + .is_release = !is_release, + .shift = keyboard_state.shift, + .alt = keyboard_state.alt, + .ctrl = keyboard_state.ctrl, + }; + ring_buffer_put(keyboard_event_buffer, &event); +} static void keyboard_callback(registers_t regs) { unsigned char status = port_byte_in(PORT_PS2_STATUS); @@ -40,31 +151,37 @@ static void keyboard_callback(registers_t regs) { return; } unsigned char scancode = port_byte_in(PORT_PS2_DATA); - print_scancode(scancode); + publish_key_event(scancode); +// print_scancode(scancode); } void init_keyboard() { register_interrupt_handler(IRQ1, keyboard_callback); + keyboard_state.shift = 0; + keyboard_state.ctrl = 0; + keyboard_state.alt = 0; + keyboard_state.extended = 0; + keyboard_event_buffer = create_buffer(256, sizeof(KeyEvent)); } -void print_scancode(unsigned char scancode) { - char msg[256]; - char release = 0; - if (scancode > 0x80) { - // release - release = 1; - scancode -= 0x80; - } - char code = scancodes_ascii[scancode]; - if (code == 0) { - // special - } else { - if (release && code > 0x60 && code < 0x7B) { - code -= 0x20; // to lowercase - } - - strcpy(msg, MSG_KEY); - msg[strlen(msg) - 3] = code; - kprint(msg); - } -} \ No newline at end of file +//void print_scancode(unsigned char scancode) { +// char msg[256]; +// char release = 0; +// if (scancode > 0x80) { +// // release +// release = 1; +// scancode -= 0x80; +// } +// char code = scancodes_ascii[scancode]; +// if (code == 0) { +// // special +// } else { +// if (release && code > 0x60 && code < 0x7B) { +// code -= 0x20; // to lowercase +// } +// +// strcpy(msg, MSG_KEY); +// msg[strlen(msg) - 3] = code; +// kprint(msg); +// } +//} \ No newline at end of file diff --git a/kernel/drivers/keyboard.h b/kernel/drivers/keyboard.h index 3027fed..dbf107d 100644 --- a/kernel/drivers/keyboard.h +++ b/kernel/drivers/keyboard.h @@ -5,6 +5,26 @@ #ifndef MY_KERNEL_KEYBOARD_H #define MY_KERNEL_KEYBOARD_H +#include + +typedef struct KeyEvent_t { +// KeyCode key; + u32 scancode; + char ascii_code; + u8 is_release: 1; + u8 shift: 1; + u8 alt: 1; + u8 ctrl: 1; +} KeyEvent; + +char getc(); + void init_keyboard(); +//const char *key_code_to_string(KeyCode key); + +KeyEvent *get_next_event(); + +void free_event(KeyEvent *event); + #endif //MY_KERNEL_KEYBOARD_H diff --git a/kernel/kernel.c b/kernel/kernel.c index 84dd133..c8e00ff 100644 --- a/kernel/kernel.c +++ b/kernel/kernel.c @@ -1,6 +1,7 @@ #include #include #include +#include #include #include #include @@ -8,9 +9,12 @@ #include #include #include +#include +#include char *msg_booted = "Booted Successfully!\n"; +void main_loop(); void kmain(multiboot_info_t *multiboot_info) { isr_install(); @@ -37,9 +41,39 @@ void kmain(multiboot_info_t *multiboot_info) { init_timer(50); init_keyboard(); - print_mmap_info(); +// print_mmap_info(); + while (true) { + main_loop(); + } // vga_set_raw(pos * 2, 'X'); // vga_set_raw(pos * 2 + 1, 0xf); do {} while (1); } + +const char* newline = "\n"; +const char* msg_unknown_command = "Unknown command: "; + +const char* cmd_echo = "echo"; +const char* cmd_print_mmap = "print_mmap"; + +void main_loop() { + char* msg = readline(NULL); + char* args = strchr(msg, ' ') + 1; + args[-1] = 0; + if (strcmp(cmd_echo, msg) == 0) { + kprint(args); + kprint(newline); + goto _main_loop_end; + } + if (strcmp(cmd_print_mmap, msg) == 0) { + print_mmap_info(); + goto _main_loop_end; + } + + kprint(msg_unknown_command); + kprint(msg); + kprint(newline); +_main_loop_end: + free(msg); +} \ No newline at end of file diff --git a/kernel/kprint.c b/kernel/kprint.c index 21b21b9..48ae623 100644 --- a/kernel/kprint.c +++ b/kernel/kprint.c @@ -27,7 +27,7 @@ void kprint_register(kprint_handler handler) { // todo handle } -void kprint(char *msg) { +void kprint(const char *msg) { for (int i = 0; i < MAX_HANDLERS; ++i) { if (handlers[i] == NULL) { continue; diff --git a/kernel/kprint.h b/kernel/kprint.h index d638b29..afd47df 100644 --- a/kernel/kprint.h +++ b/kernel/kprint.h @@ -13,4 +13,4 @@ typedef void (*kprint_handler)(const char *); void kprint_register(kprint_handler); -void kprint(char *msg); \ No newline at end of file +void kprint(const char *msg); \ No newline at end of file diff --git a/kernel/libc/libc.c b/kernel/libc/libc.c index 9702d7d..a3a2aa2 100644 --- a/kernel/libc/libc.c +++ b/kernel/libc/libc.c @@ -14,10 +14,6 @@ int memcpy(char *dst, char *src, int amount) { return 0; } -int strcpy(char *dst, char *src) { - return memcpy(dst, src, strlen(src) + 1); -} - int memset(char *dst, char data, int amount) { for (int i = 0; i < amount; ++i) { dst[i] = data; @@ -34,11 +30,9 @@ int itoa(int i, char *target) { return 0; } -int strlen(char *str) { - int length = 0; - while (str[length] != 0) { - length++; +int maxi(int a, int b) { + if (a >= b) { + return a; } - return length; + return b; } - diff --git a/kernel/libc/libc.h b/kernel/libc/libc.h index 67f8a97..04f5582 100644 --- a/kernel/libc/libc.h +++ b/kernel/libc/libc.h @@ -10,12 +10,10 @@ int memcpy(char *dst, char *src, int amount); -int strcpy(char *dst, char *src); - int memset(char *dst, char data, int amount); int itoa(int i, char *target); -int strlen(char *str); +int maxi(int a, int b); #endif /* KERNEL_LIBC_LIBC_H_ */ diff --git a/kernel/libc/readline.c b/kernel/libc/readline.c new file mode 100644 index 0000000..52ca847 --- /dev/null +++ b/kernel/libc/readline.c @@ -0,0 +1,30 @@ +// +// Created by rick on 01-02-21. +// + +#include "readline.h" +#include +#include +#include +#include +#include + +#define RESULT_SIZE 256 + +const char* default_msg = "> "; + +char* readline(const char *prompt) { + kprint(prompt == NULL ? default_msg : prompt); + + char* result = malloc(RESULT_SIZE); + memset(result, 0, RESULT_SIZE); + for (int i = 0; i < RESULT_SIZE; ++i) { + result[i] = getc(); + kprint(&result[i]); + if (result[i] == '\n') { + result[i] = 0; + break; + } + } + return result; +} diff --git a/kernel/libc/readline.h b/kernel/libc/readline.h new file mode 100644 index 0000000..68fc180 --- /dev/null +++ b/kernel/libc/readline.h @@ -0,0 +1,10 @@ +// +// Created by rick on 01-02-21. +// + +#ifndef NEW_KERNEL_READLINE_H +#define NEW_KERNEL_READLINE_H + +char* readline(const char *prompt); + +#endif //NEW_KERNEL_READLINE_H diff --git a/kernel/libc/ringqueue.c b/kernel/libc/ringqueue.c new file mode 100644 index 0000000..77bee9b --- /dev/null +++ b/kernel/libc/ringqueue.c @@ -0,0 +1,57 @@ +// +// Created by rick on 30-01-21. +// + +#include "ringqueue.h" +#include +#include + +#define calc_pos(buffer, index) ((buffer->object_size) * (index)) + +typedef struct { + int object_size; + int count; + int read_pos; + int write_pos; + void *mem; +} ring_buffer_t; + +void *create_buffer(int count, int object_size) { + ring_buffer_t *buffer = malloc(sizeof(ring_buffer_t)); + if (buffer == NULL) { + return NULL; + } + buffer->object_size = object_size; + buffer->count = count; + buffer->read_pos = 0; + buffer->write_pos = 0; + buffer->mem = malloc(count * object_size); + if (buffer->mem == NULL) { + free(buffer); + return NULL; + } + return buffer; +}; + +void free_buffer(void *buffer) { + free(((ring_buffer_t *) buffer)->mem); + free(buffer); +} + +void ring_buffer_put(void *buffer, void *item) { + ring_buffer_t *ring_buffer = (ring_buffer_t *) buffer; + // todo check if this write would overwrite the current reading pos + // todo handle the above case + memcpy(ring_buffer->mem + calc_pos(ring_buffer, ring_buffer->write_pos), item, ring_buffer->object_size); + ring_buffer->write_pos++; +}; + +bool ring_buffer_get(void *buffer, void* target) { + ring_buffer_t *ring_buffer = (ring_buffer_t *) buffer; + if (ring_buffer->read_pos == ring_buffer->write_pos) { + // nothing to read + return false; + } + memcpy(target, ring_buffer->mem + calc_pos(ring_buffer, ring_buffer->read_pos++), ring_buffer->object_size); + return true; +}; diff --git a/kernel/libc/ringqueue.h b/kernel/libc/ringqueue.h new file mode 100644 index 0000000..7a5ad39 --- /dev/null +++ b/kernel/libc/ringqueue.h @@ -0,0 +1,19 @@ +// +// Created by rick on 30-01-21. +// + +#ifndef NEW_KERNEL_RINGQUEUE_H +#define NEW_KERNEL_RINGQUEUE_H + +#include +#include + +void *create_buffer(int count, int object_size); + +void free_buffer(void *buffer); + +void ring_buffer_put(void *buffer, void *item); + +bool ring_buffer_get(void *buffer, void* target); + +#endif //NEW_KERNEL_RINGQUEUE_H diff --git a/kernel/libc/stdbool.c b/kernel/libc/stdbool.c new file mode 100644 index 0000000..5642a82 --- /dev/null +++ b/kernel/libc/stdbool.c @@ -0,0 +1,5 @@ +// +// Created by rick on 31-01-21. +// + +#include "stdbool.h" diff --git a/kernel/libc/stdbool.h b/kernel/libc/stdbool.h new file mode 100644 index 0000000..9e71ef7 --- /dev/null +++ b/kernel/libc/stdbool.h @@ -0,0 +1,15 @@ +// +// Created by rick on 31-01-21. +// + +#ifndef NEW_KERNEL_STDBOOL_H +#define NEW_KERNEL_STDBOOL_H + +#define TRUE 1 +#define true 1 +#define FALSE 0 +#define false 0 + +typedef unsigned char bool; + +#endif //NEW_KERNEL_STDBOOL_H diff --git a/kernel/libc/string.c b/kernel/libc/string.c new file mode 100644 index 0000000..e266212 --- /dev/null +++ b/kernel/libc/string.c @@ -0,0 +1,60 @@ +// +// Created by rick on 01-02-21. +// + +#include "string.h" +#include "stdbool.h" +#include +#include + +int strcpy(char *dst, char *src) { + return memcpy(dst, src, strlen(src) + 1); +} + +int strlen(const char *str) { + int length = 0; + while (str[length] != 0) { + length++; + } + return length; +} + +int strcmp(const char *s1, const char *s2) { + int len1 = strlen(s1); + int len2 = strlen(s1); + return strncmp(s1, s2, maxi(len1, len2)); +} + +const char *strchr(const char *s, char c) { + int index = 0; + while (true) { + if (s[index] == c) { + return &s[index]; + } + if (s[index] == 0) { + return NULL; + } + index++; + } +} + +int strncmp(const char *s1, const char *s2, int n) { + for (int i = 0; i < n; ++i) { + if (s1[i] == 0 && s2[i] == 0) { + return 0; + } + if (s1[i] == 0) { + return -1; + } + if (s2[i] == 0) { + return 1; + } + if (s1[i] > s2[i]) { + return -1; + } + if (s2[i] < s1[i]) { + return 1; + } + } + return 0; +} diff --git a/kernel/libc/string.h b/kernel/libc/string.h new file mode 100644 index 0000000..234daad --- /dev/null +++ b/kernel/libc/string.h @@ -0,0 +1,18 @@ +// +// Created by rick on 01-02-21. +// + +#ifndef NEW_KERNEL_STRING_H +#define NEW_KERNEL_STRING_H + +int strcpy(char *dst, char *src); + +int strlen(const char *str); + +const char *strchr(const char *s, char c); + +int strcmp(const char *s1, const char *s2); + +int strncmp(const char *s1, const char *s2, int n); + +#endif //NEW_KERNEL_STRING_H diff --git a/kernel/mem/mem.c b/kernel/mem/mem.c index 943ac20..26a4706 100644 --- a/kernel/mem/mem.c +++ b/kernel/mem/mem.c @@ -7,6 +7,27 @@ #include #include +#define MEMMAP_ENTRIES 16 + +#define MMAP_TYPE_UNDEFINED 0 +#define MMAP_TYPE_AVAILABLE 1 +#define MMAP_TYPE_RESERVED 2 +#define MMAP_TYPE_ACPI_RECLAIMABLE 3 +#define MMAP_TYPE_NVS 4 +#define MMAP_TYPE_BADRAM 5 +#define MMAP_TYPE_KERNEL 6 +#define MMAP_TYPE_MALLOC 7 + +#define MALLOC_TYPE_FREE 0 +#define MALLOC_TYPE_USED 1 + +#define kilobyte (1024) +//#define kernel_start (one_meg) +#define kernel_size (32 * kilobyte) +#define kernel_end (kernel_start + kernel_size) +extern void *kernel_start; +//extern void *kernel_end; + char *msg_index = "Idx: "; char *msg_addr = "Address: "; char *msg_len = "Length: "; @@ -14,20 +35,18 @@ char *msg_type = "Type: "; char *msg_nl = "\n"; typedef struct { - u64 address; - u64 length; -#define MMAP_TYPE_UNDEFINED 0 -#define MMAP_TYPE_AVAILABLE 1 -#define MMAP_TYPE_RESERVED 2 -#define MMAP_TYPE_ACPI_RECLAIMABLE 3 -#define MMAP_TYPE_NVS 4 -#define MMAP_TYPE_BADRAM 5 + void *address; + u32 length; u32 type; } __attribute((packed)) mmap_entry; char *msg_lu = "0123456789ABCDEF"; -mmap_entry memmap[16] = { +int malloc_entries = 0; +int malloc_used = 0; + +int last_memmap_entry = 0; +mmap_entry memmap[MEMMAP_ENTRIES] = { {0, 0, 0}, {0, 0, 0}, {0, 0, 0}, @@ -46,14 +65,107 @@ mmap_entry memmap[16] = { {0, 0, 0}, }; -void init_mmap(struct multiboot_mmap_entry *entries, u32 count) { - for (u32 i = 0; i < count; ++i) { - memmap[i].address = entries[i].addr; - memmap[i].length = entries[i].len; - memmap[i].type = entries[i].type; +typedef struct malloc_map { + struct malloc_map *next; + struct malloc_map *pref; + u32 size; + int type; +} malloc_map; + +void use_mmap_entry(struct multiboot_mmap_entry *entry) { + mmap_entry *mm_entry = &memmap[last_memmap_entry++]; + mm_entry->address = (void *) entry->addr; + mm_entry->length = entry->len; + mm_entry->type = entry->type; + if (last_memmap_entry == 1) { + // not using first map entry for now + return; + } + // check if the entry overlaps with the kernel address space + if (kernel_start >= mm_entry->address && kernel_start <= mm_entry->address + mm_entry->length) { + // todo make this something proper + struct multiboot_mmap_entry extra_entry; + extra_entry.size = entry->size; + extra_entry.type = entry->type; + extra_entry.addr = entry->addr + kernel_size; + extra_entry.len = entry->size - kernel_size; + use_mmap_entry(&extra_entry); + + mm_entry->length = kernel_size; + mm_entry->type = MMAP_TYPE_KERNEL; + } + if (mm_entry->type == MMAP_TYPE_AVAILABLE && (unsigned int) mm_entry->length > sizeof(malloc_map)) { + mm_entry->type = MMAP_TYPE_MALLOC; + malloc_map *map = (malloc_map *) mm_entry->address; + map->type = MALLOC_TYPE_FREE; + map->size = mm_entry->length - sizeof(malloc_map); + map->pref = map; + map->next = map; + malloc_entries++; } } +void init_mmap(struct multiboot_mmap_entry *entries, u32 count) { + for (u32 i = 0; i < count; ++i) { + use_mmap_entry(&entries[i]); + } +} + +void split_malloc_map(malloc_map *entry, unsigned int size) { + malloc_entries++; + malloc_map *new_entry = entry + sizeof(malloc_map) + size; + new_entry->size = entry->size - size - sizeof(malloc_map); + new_entry->next = entry->next; + new_entry->pref = entry; + new_entry->type = MALLOC_TYPE_FREE; + entry->next->pref = new_entry; + entry->next = new_entry; + entry->size = size; +} + +void *malloc(unsigned int size) { + // todo replace this horrible mess! + // this lacks any page alignment and what so ever + for (int i = 0; i < MEMMAP_ENTRIES; ++i) { + if (memmap[i].type != MMAP_TYPE_MALLOC) { + continue; + } + // get first first_map of address + malloc_map *first_map = (malloc_map *) memmap[i].address; + malloc_map *current_map = first_map; + // iterate through maps + do { + if (current_map->type == MALLOC_TYPE_USED) { + goto malloc_find_next; + } + if ((unsigned int) current_map->size < size) { + goto malloc_find_next; + } + if ((unsigned int) current_map->size > (size + sizeof(malloc_map))) { + // big enough to split + split_malloc_map(current_map, size); + } + malloc_used++; + current_map->type = MALLOC_TYPE_USED; + return ((void*)current_map) + sizeof(malloc_map); + + malloc_find_next: + current_map = current_map->next; + } while (current_map != first_map); + } + return NULL; +} + +void free(void *mem) { + if (mem == NULL) { + return; + } + malloc_used--; + malloc_map *map = (mem - sizeof(malloc_map)); + map->type = MALLOC_TYPE_FREE; +}; + + void print_hex_u64(u64 input) { char msg[18] = "0x0000000000000000"; for (int i = 0; i < 16; ++i) { @@ -74,10 +186,10 @@ void print_mmap_info() { kprint(tmp_str); kprint(msg_nl); kprint(msg_addr); - print_hex_u64(memmap[i].address); + print_hex_u64((u64) memmap[i].address); kprint(msg_nl); kprint(msg_len); - print_hex_u64(memmap[i].length); + print_hex_u64((u64) memmap[i].length); kprint(msg_nl); kprint(msg_type); itoa(memmap[i].type, tmp_str); diff --git a/kernel/mem/mem.h b/kernel/mem/mem.h index 8ca778c..f017b81 100644 --- a/kernel/mem/mem.h +++ b/kernel/mem/mem.h @@ -11,4 +11,7 @@ void init_mmap(struct multiboot_mmap_entry *entries, u32 count); void print_mmap_info(); +void* malloc(unsigned int size); +void free(void* mem); + #endif //NEW_KERNEL_MEM_H diff --git a/linker.ld b/linker.ld index f61e130..7591e42 100644 --- a/linker.ld +++ b/linker.ld @@ -9,6 +9,7 @@ SECTIONS /* Begin putting sections at 1 MiB, a conventional place for kernels to be loaded at by the bootloader. */ . = 1M; + kernel_start = .; /* First put the multiboot header, as it is required to be put very early early in the image or the bootloader won't recognize the file format. @@ -38,6 +39,13 @@ SECTIONS *(.bss) } + /DISCARD/ : { + *(.eh_frame); + *(.comment); + *(.gnu.hash); + *(.note.gnu.build-id); + } + /* The compiler may produce other sections, by default it will put them in a segment with the same name. Simply add stuff here as needed. */ } \ No newline at end of file diff --git a/qemu-debug.sh b/qemu-debug.sh index 1cecd86..a198355 100755 --- a/qemu-debug.sh +++ b/qemu-debug.sh @@ -1,3 +1,3 @@ #!/bin/bash -nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -d guest_errors,int -m 1G & +nohup qemu-system-i386 -S -s -kernel cmake-build-debug/my-kernel.bin -d guest_errors,int -m 1G > /dev/null & disown diff --git a/scancodes/set1.json b/scancodes/set1.json new file mode 100644 index 0000000..d9d7fbc --- /dev/null +++ b/scancodes/set1.json @@ -0,0 +1,810 @@ +[ + [ + "1", + "29/A9", + "0E/F0 0E", + "0E/F0 0E", + "`", + "~" + ], + [ + "2", + "02/82", + "16/F0 16", + "16/F0 16", + "1", + "!" + ], + [ + "3", + "03/83", + "1E/F0 1E", + "1E/F0 1E", + "2", + "@" + ], + [ + "4", + "04/84", + "26/F0 26", + "26/F0 26", + "3", + "#" + ], + [ + "5", + "05/85", + "25/F0 25", + "25/F0 25", + "4", + "$" + ], + [ + "6", + "06/86", + "2E/F0 2E", + "2E/F0 2E", + "5", + "%" + ], + [ + "7", + "07/87", + "36/F0 36", + "36/F0 36", + "6", + "^" + ], + [ + "8", + "08/88", + "3D/F0 3D", + "3D/F0 3D", + "7", + "&" + ], + [ + "9", + "09/89", + "3E/F0 3E", + "3E/F0 3E", + "8", + "*" + ], + [ + "10", + "0A/8A", + "46/F0 46", + "46/F0 46", + "9", + "(" + ], + [ + "11", + "0B/8B", + "45/F0 45", + "45/F0 45", + "0", + ")" + ], + [ + "12", + "0C/8C", + "4E/F0 4E", + "4E/F0 4E", + "-", + "_" + ], + [ + "13", + "0D/8D", + "55/F0 55", + "55/F0 55", + "=", + "+" + ], + [ + "15", + "0E/8E", + "66/F0 66", + "66/F0 66", + "Backspace", + "" + ], + [ + "16", + "0F/8F", + "0D/F0 0D", + "0D/F0 0D", + "Tab", + "" + ], + [ + "17", + "10/90", + "15/F0 15", + "15/F0 15", + "q", + "Q" + ], + [ + "18", + "11/91", + "1D/F0 1D", + "1D/F0 1D", + "w", + "W" + ], + [ + "19", + "12/92", + "24/F0 24", + "24/F0 24", + "e", + "E" + ], + [ + "20", + "13/93", + "2D/F0 2D", + "2D/F0 2D", + "r", + "R" + ], + [ + "21", + "14/94", + "2C/F0 2C", + "2C/F0 2C", + "t", + "T" + ], + [ + "22", + "15/95", + "35/F0 35", + "35/F0 35", + "y", + "Y" + ], + [ + "23", + "16/96", + "3C/F0 3C", + "3C/F0 3C", + "u", + "U" + ], + [ + "24", + "17/97", + "43/F0 43", + "43/F0 43", + "i", + "I" + ], + [ + "25", + "18/98", + "44/F0 44", + "44/F0 44", + "o", + "O" + ], + [ + "26", + "19/99", + "4D/F0 4D", + "4D/F0 4D", + "p", + "P" + ], + [ + "27", + "1A/9A", + "54/F0 54", + "54/F0 54", + "[", + "{" + ], + [ + "28", + "1B/9B", + "5B/F0 5B", + "5B/F0 5B", + "]", + "}" + ], + [ + "30", + "3A/BA", + "58/F0 58", + "58/F0 58", + "Caps Lock", + "" + ], + [ + "31", + "1E/9E", + "1C/F0 1C", + "1C/F0 1C", + "a", + "A" + ], + [ + "32", + "1F/9F", + "1B/F0 1B", + "1B/F0 1B", + "s", + "S" + ], + [ + "33", + "20/A0", + "23/F0 23", + "23/F0 23", + "d", + "D" + ], + [ + "34", + "21/A1", + "2B/F0 2B", + "2B/F0 2B", + "f", + "F" + ], + [ + "35", + "22/A2", + "34/F0 34", + "34/F0 34", + "g", + "G" + ], + [ + "36", + "23/A3", + "33/F0 33", + "33/F0 33", + "h", + "H" + ], + [ + "37", + "24/A4", + "3B/F0 3B", + "3B/F0 3B", + "j", + "J" + ], + [ + "38", + "25/A5", + "42/F0 42", + "42/F0 42", + "k", + "K" + ], + [ + "39", + "26/A6", + "4B/F0 4B", + "4B/F0 4B", + "l", + "L" + ], + [ + "40", + "27/A7", + "4C/F0 4C", + "4C/F0 4C", + ";", + ":" + ], + [ + "41", + "28/A8", + "52/F0 52", + "52/F0 52", + "'", + "\"" + ], + [ + "43", + "1C/9C", + "5A/F0 5A", + "5A/F0 5A", + "Enter", + "Enter" + ], + [ + "44", + "2A/AA", + "12/F0 12", + "12/F0 12", + "Left Shift", + "" + ], + [ + "46", + "2C/AC", + "1A/F0 1A", + "1A/F0 1A", + "z", + "Z" + ], + [ + "47", + "2D/AD", + "22/F0 22", + "22/F0 22", + "x", + "X" + ], + [ + "48", + "2E/AE", + "21/F0 21", + "21/F0 21", + "c", + "C" + ], + [ + "49", + "2F/AF", + "2A/F0 2A", + "2A/F0 2A", + "v", + "V" + ], + [ + "50", + "30/B0", + "32/F0 32", + "32/F0 32", + "b", + "B" + ], + [ + "51", + "31/B1", + "31/F0 31", + "31/F0 31", + "n", + "N" + ], + [ + "52", + "32/B2", + "3A/F0 3A", + "3A/F0 3A", + "m", + "M" + ], + [ + "53", + "33/B3", + "41/F0 41", + "41/F0 41", + ",", + "<" + ], + [ + "54", + "34/B4", + "49/F0 49", + "49/F0 49", + ".", + ">" + ], + [ + "55", + "35/B5", + "4A/F0 4A", + "4A/F0 4A", + "/", + "?" + ], + [ + "57", + "36/B6", + "59/F0 59", + "59/F0 59", + "Right Shift", + "" + ], + [ + "58", + "1D/9D", + "14/F0 14", + "11/F0 11", + "Left Ctrl", + "" + ], + [ + "60", + "38/B8", + "11/F0 11", + "19/F0 19", + "Left Alt", + "" + ], + [ + "61", + "39/B9", + "29/F0 29", + "29/F0 29", + "Spacebar", + "" + ], + [ + "62", + "E0 38/E0 B8", + "E0 11/E0 F0 11", + "39/F0 39", + "Right Alt", + "" + ], + [ + "64", + "E0 1D/E0 9D", + "E0 14/E0 F0 14", + "58/F0 58", + "Right Ctrl", + "" + ], + [ + "75", + "E0 52/E0 D2 (base)", + "E0 70/E0 F0 70 (base)", + "67/F0 67", + "Insert", + "" + ], + [ + "76", + "E0 4B/E0 CB (base)", + "E0 71/E0 F0 71 (base)", + "64/F0 64", + "Delete", + "" + ], + [ + "79", + "E0 4B/E0 CB (base)", + "E0 6B/E0 F0 6B (base)", + "61/F0 61", + "Left Arrow", + "" + ], + [ + "80", + "E0 47/E0 C7 (base)", + "E0 6C/E0 F0 6C (base)", + "6E/F0 6E", + "Home", + "" + ], + [ + "81", + "E0 4F/E0 CF (base)", + "E0 69/E0 F0 69 (base)", + "65/F0 65", + "End", + "" + ], + [ + "83", + "E0 48/E0 C8 (base)", + "E0 75/E0 F0 75 (base)", + "63/F0 63", + "Up Arrow", + "" + ], + [ + "84", + "E0 50/E0 D0 (base)", + "E0 72/E0 F0 72 (base)", + "60/F0 60", + "Down Arrow", + "" + ], + [ + "85", + "E0 49/E0 C9 (base)", + "E0 7D/E0 F0 7D (base)", + "6F/F0 6F", + "Page Up", + "" + ], + [ + "86", + "E0 51/E0 D1 (base)", + "E0 7A/E0 F0 7A (base)", + "6D/F0 6D", + "Page Down", + "" + ], + [ + "89", + "E0 4D/E0 CD (base)", + "E0 74/E0 F0 74 (base)", + "6A/F0 6A", + "Right Arrow", + "" + ], + [ + "90", + "45/C5", + "77/F0 77", + "76/F0 76", + "Num Lock", + "" + ], + [ + "91", + "47/C7", + "6C/F0 6C", + "6C/F0 6C", + "Keypad 7", + "" + ], + [ + "92", + "4B/CB", + "6B/F0 6B", + "6B/F0 6B", + "Keypad 4", + "" + ], + [ + "93", + "4F/CF", + "69/F0 69", + "69/F0 69", + "Keypad 1", + "" + ], + [ + "95", + "E0 35/E0 B5 (base)", + "E0 4A/E0 F0 4A (base)", + "77/F0 77", + "Keypad /", + "" + ], + [ + "96", + "48/C8", + "75/F0 75", + "75/F0 75", + "Keypad 8", + "" + ], + [ + "97", + "4C/CC", + "73/F0 73", + "73/F0 73", + "Keypad 5", + "" + ], + [ + "98", + "50/D0", + "72/F0 72", + "72/F0 72", + "Keypad 2", + "" + ], + [ + "99", + "52/D2", + "70/F0 70", + "70/F0 70", + "Keypad 0", + "" + ], + [ + "100", + "37/B7", + "7C/F0 7C", + "7E/F0 7E", + "Keypad *", + "" + ], + [ + "101", + "49/C9", + "7D/F0 7D", + "7D/F0 7D", + "Keypad 9", + "" + ], + [ + "102", + "4D/CD", + "74/F0 74", + "74/F0 74", + "Keypad 6", + "" + ], + [ + "103", + "51/D1", + "7A/F0 7A", + "7A/F0 7A", + "Keypad 3", + "" + ], + [ + "104", + "53/D3", + "71/F0 71", + "71/F0 71", + "Keypad .", + "" + ], + [ + "105", + "4A/CA", + "7B/F0 7B", + "84/F0 84", + "Keypad -", + "" + ], + [ + "106", + "4E/CE", + "79/F0 79", + "7C/F0 7C", + "Keypad +", + "" + ], + [ + "108", + "E0 1C/E0 9C", + "E0 5A/E0 F0 5A", + "79/F0 79", + "Keypad Enter", + "" + ], + [ + "110", + "01/81", + "76/F0 76", + "08/F0 08", + "Esc", + "" + ], + [ + "112", + "3B/BB", + "05/F0 05", + "07/F0 07", + "F1", + "" + ], + [ + "113", + "3C/BC", + "06/F0 06", + "0F/F0 0F", + "F2", + "" + ], + [ + "114", + "3D/BD", + "04/F0 04", + "17/F0 17", + "F3", + "" + ], + [ + "115", + "3E/BE", + "0C/F0 0C", + "1F/F0 1F", + "F4", + "" + ], + [ + "116", + "3F/BF", + "03/F0 03", + "27/F0 27", + "F5", + "" + ], + [ + "117", + "40/C0", + "0B/F0 0B", + "2F/F0 2F", + "F6", + "" + ], + [ + "118", + "41/C1", + "83/F0 83", + "37/F0 37", + "F7", + "" + ], + [ + "119", + "42/C2", + "0A/F0 0A", + "3F/F0 3F", + "F8", + "" + ], + [ + "120", + "43/C3", + "01/F0 01", + "47/F0 47", + "F9", + "" + ], + [ + "121", + "44/C4", + "09/F0 09", + "4F/F0 4F", + "F10", + "" + ], + [ + "122", + "57/D7", + "78/F0 78", + "56/F0 56", + "F11", + "" + ], + [ + "123", + "58/D8", + "07/F0 07", + "5E/F0 5E", + "F12", + "" + ], + [ + "124", + "E0 2A E0 37/E0 B7 E0 AA", + "E0 12 E0 7C/E0 F0 7C E0 F0 12", + "57/F0 57", + "Print Screen", + "" + ], + [ + "125", + "46/C6", + "7E/F0 7E", + "5F/F0 5F", + "Scroll Lock", + "" + ], + [ + "126", + "E1 1D 45/E1 9D C5", + "E1 14 77 E1/F0 14 F0 77", + "62/F0 62", + "Pause Break", + "" + ], + [ + "29 or 42*", + "2B/AB", + "5D/F0 5D", + "5C/F0 5C or 53/F0 53", + "\\", + "|" + ] +] \ No newline at end of file diff --git a/scancodes/transform_scancodes.py b/scancodes/transform_scancodes.py new file mode 100644 index 0000000..9ff9e22 --- /dev/null +++ b/scancodes/transform_scancodes.py @@ -0,0 +1,124 @@ +#!/usr/bin/env python3 +import functools +import itertools +import json +import unicodedata +from typing import NamedTuple, List, Optional +import pyperclip + + +class KeyCode(NamedTuple): + scan_code: int + name_lower: str + name_upper: str + ascii_lower: Optional[str] + ascii_upper: Optional[str] + + +# scancodes retrieved from https://wiki.osdev.org/PS/2_Keyboard +# scancodes transformed with https://www.convertjson.com/html-table-to-json.htm + + +blacklist_names = {'(zero)'} + +special_map = { + '\\': 'forwardSlash', + '/': 'backSlash', + '[': 'bracketLeft', + ']': 'bracketRight', + ';': 'colonPressed', + "'": None, + '`': None, + ',': 'comma', + '.': 'dot', + # todo keypad * + '-': 'dash', + '=': 'equals', +} + + +def get_unknown(i): + return KeyCode(i, f"Unknown{i:02x}Lower", f"Unknown{i:02x}Upper", None, None) + + +def not_in_blacklist(name: str) -> bool: + return name not in blacklist_names + + +def remove_braces(name: str) -> str: + name = name.lstrip('(').rstrip(')') + if name in special_map: + return special_map[name] + return name + + +def key_name_to_name(names: List[str]) -> str: + _names: List[str] = list(filter(lambda i: i is not None, map(remove_braces, filter(not_in_blacklist, names)))) + _names_cap = itertools.chain([_names[0][0].lower() + _names[0][1:]], + map(lambda i: i[0].upper() + i[1:], _names[1:])) + return ''.join(_names_cap) + + +def get_name(item: str): + item = item.replace(' ', ' ') + if len(item) == 1: + item = unicodedata.name(item).title() + if item.startswith('Latin'): + return 'Letter' + item.split()[-1] + return item.replace(' ', '_') if item else None + + +def transform_set1(path): + codes = [] + with open(path) as f: + data = json.load(f) + + for ibm_number, make_break_1, _, _, lower, upper in data: + make_code, break_code = make_break_1.split('/') + if make_code.startswith('E0') or make_code.startswith('E1'): + # skipping multi codes for now + continue + make_code_i = int(make_code, base=16) + break_code_i = int(break_code, base=16) + if make_code_i != break_code_i ^ 0x80: + raise ValueError("Make/Break not equal" + ibm_number) + codes.append(KeyCode( + make_code_i, + get_name(lower), + get_name(upper), + lower, + upper, + )) + + codes_map = {} + + for code in codes: + if code.scan_code in codes_map: + raise ValueError(f"Duplicate code {code!r}") + codes_map[code.scan_code] = code + + # max_val = functools.reduce(lambda a, b: max(a, b), map(lambda x: x.scan_code, codes), 0) + return codes_map + # txts = [] + # for i in range(max_val): + # code = codes_map.get(i) or get_unknown(i) + # txts.append(f'{code.scan_code}\t{code.name_lower}\t{code.name_upper}\t{code.ascii_lower or None}\t{code.ascii_upper or None}') + # pyperclip.copy('\n'.join(txts)) + + +def get_ascii_val(val: str): + if not val: + return 'NULL' + if len(val) > 1: + return 'NULL' + if val == "'": + return "'\\''" + return repr(val) + + +def main(): + transform_set1() + + +if __name__ == '__main__': + main()