From 1e4a254674f668839e5de273916024c16814b045 Mon Sep 17 00:00:00 2001 From: Benji Dial Date: Sun, 13 Sep 2020 03:19:57 -0400 Subject: (basic, not much tested) keyboard, better panic --- src/kernel/drive.c | 6 +- src/kernel/elf.c | 16 ++- src/kernel/elf.h | 2 +- src/kernel/fat.c | 10 +- src/kernel/ide.c | 26 ++-- src/kernel/idt.c | 55 +++++--- src/kernel/isrs.asm | 27 +++- src/kernel/kbd.c | 285 +++++++++++++++++++++++++++++++++++++++ src/kernel/kbd.h | 10 ++ src/kernel/main.c | 8 +- src/kernel/paging.c | 41 ++++-- src/kernel/paging.h | 3 + src/kernel/panic.c | 12 +- src/kernel/panic.h | 6 +- src/kernel/pci.c | 6 +- src/kernel/task.c | 22 +-- src/user/hello/hello.c | 5 - src/user/highway/highway.c | 21 +++ src/user/include/knob/block.h | 7 + src/user/include/knob/user.h | 3 +- src/user/include/pland/syscall.h | 6 +- src/user/init/init.c | 24 +++- src/user/knob/block.c | 17 +++ src/user/knob/entry.asm | 1 + src/user/knob/quit.c | 25 +--- src/user/knob/task.c | 16 ++- src/user/knob/user.c | 116 +++++++++++----- 27 files changed, 630 insertions(+), 146 deletions(-) create mode 100644 src/kernel/kbd.c create mode 100644 src/kernel/kbd.h delete mode 100644 src/user/hello/hello.c create mode 100644 src/user/highway/highway.c create mode 100644 src/user/include/knob/block.h create mode 100644 src/user/knob/block.c (limited to 'src') diff --git a/src/kernel/drive.c b/src/kernel/drive.c index c3aa5b2..731088c 100644 --- a/src/kernel/drive.c +++ b/src/kernel/drive.c @@ -15,15 +15,15 @@ static file_id_t unknown_get_file(const struct drive *d, const char *path) { } static void unknown_free_file(const struct drive *d, file_id_t fid) { - panic("Free file called on unknown file system"); + PANIC("Free file called on unknown file system."); } static void unknown_load_sector(const struct drive *d, file_id_t fid, uint32_t sector, void *at) { - panic("Load sector called on unknown file system"); + PANIC("Load sector called on unknown file system."); } static uint32_t unknown_get_file_length(const struct drive *d, file_id_t fid) { - panic("Get file length called on unknown file system"); + PANIC("Get file length called on unknown file system."); } __attribute__ ((const)) diff --git a/src/kernel/elf.c b/src/kernel/elf.c index bd2f12d..423d51a 100644 --- a/src/kernel/elf.c +++ b/src/kernel/elf.c @@ -73,7 +73,7 @@ struct ph_entry { uint32_t align; } __attribute__ ((packed)); -bool try_elf_run(const struct drive *d, const char *path) { +bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma) { file_id_t h = d->get_file(d, path); if (!h) return false; @@ -109,9 +109,23 @@ bool try_elf_run(const struct drive *d, const char *path) { free_pages(phtable, phtable_pages); d->free_file(d, h); + const char *pass = vma_to_pma(active_task->page_directory, pass_old_vma); + + uint32_t pass_l = 0; + while (pass[pass_l++]) + ; + + void *pass_vma; + void *pass_pma; + user_allocate_anywhere_readonly_together(pd, ((pass_l - 1) >> 12) + 1, &pass_vma, &pass_pma); + //TODO: handle error condition + + memcpy(pass_pma, pass, pass_l); + struct task_state tstate; tstate.page_directory = pd; tstate.ret_addr = ehead.entry_vma; + tstate.edx = (uint32_t)pass_vma; new_task(tstate); return true; } \ No newline at end of file diff --git a/src/kernel/elf.h b/src/kernel/elf.h index 09aa05c..98489f2 100644 --- a/src/kernel/elf.h +++ b/src/kernel/elf.h @@ -4,6 +4,6 @@ #include #include "drive.h" -bool try_elf_run(const struct drive *d, const char *path); +bool try_elf_run(const struct drive *d, const char *path, const char *pass_old_vma); #endif \ No newline at end of file diff --git a/src/kernel/fat.c b/src/kernel/fat.c index 1b6c52d..c297cab 100644 --- a/src/kernel/fat.c +++ b/src/kernel/fat.c @@ -89,7 +89,7 @@ static struct fat_info *next_fi; static void alloc_next_fi() { if (!((uint32_t)(next_fi = (struct fat_info *)((uint32_t)next_fi + 64)) & 0xfff)) if (!(next_fi = allocate_kernel_pages(1))) - panic("Out of memory in FAT driver."); + PANIC("Out of memory in FAT driver."); } static const struct drive *cur_drive; @@ -183,9 +183,9 @@ static const char *split_path(const char *path, uint8_t *fat_name_buffer) { ++pi; } else - panic("Bad path in FAT16 driver"); + PANIC("Bad path in FAT16 driver."); else if (((fi == 8) && (path[pi - 1] != EXT_SEP_CHAR)) || (fi == 11)) - panic("Bad path in FAT16 driver"); + PANIC("Bad path in FAT16 driver."); else { fat_name_buffer[fi++] = (uint8_t)path[pi++]; } @@ -229,7 +229,7 @@ static file_id_t fat_get_file(const struct drive *d, const char *path) { return n; } - panic("Maximum number of files open reached for FAT drive."); + PANIC("Maximum number of files open reached for FAT drive."); } static void fat_free_file(const struct drive *d, file_id_t fid) { @@ -365,7 +365,7 @@ void init_fat() { bool try_fat_init_drive(struct drive *d) { if (next_id >= MAX_FAT_DRIVES) - panic("Maximum number of FAT drives reached."); + PANIC("Maximum number of FAT drives reached."); if (!d->read_sectors(d, 0, 1, fat_driver_buffer)) return false; diff --git a/src/kernel/ide.c b/src/kernel/ide.c index 70b1dee..4b6443a 100644 --- a/src/kernel/ide.c +++ b/src/kernel/ide.c @@ -24,11 +24,11 @@ static uint8_t wait_for_ready(uint16_t base_port) { for (spinner_t n = -1; n; --n) { uint8_t s = inb(base_port | ATA_REG_STATUS); if (s & ATA_STATUS_ERROR) - panic("Error status in IDE driver."); + PANIC("Error status in IDE driver."); if (s & ATA_STATUS_DRIVE_READY) return s; } - panic("Spun out in IDE driver."); + PANIC("Spun out in IDE driver."); } //returns the status after waiting @@ -38,7 +38,7 @@ static uint8_t wait_for_error_or_ready(uint16_t base_port) { if (s & (ATA_STATUS_DRIVE_READY | ATA_STATUS_ERROR)) return s; } - panic("Spun out in IDE driver."); + PANIC("Spun out in IDE driver."); } //returns the status after waiting @@ -48,9 +48,9 @@ static uint8_t wait_for_data_ready_not_busy(uint16_t base_port) { if (!(s & ATA_STATUS_BUSY) && (s & ATA_STATUS_DATA_READY)) return s; if (s & ATA_STATUS_ERROR) - panic("Error status in IDE driver."); + PANIC("Error status in IDE driver."); } - panic("Spun out in IDE driver."); + PANIC("Spun out in IDE driver."); } static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count, void *buffer) { @@ -62,9 +62,9 @@ static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count return 0; if (start & 0xf0000000) - panic("IDE ATA driver does not support reads starting past 256MiB currently."); + PANIC("IDE ATA driver does not support reads starting past 256MiB currently."); if (count & 0xffffff00) - panic("IDE ATA driver does not support reads over 128kiB in length currently."); + PANIC("IDE ATA driver does not support reads over 128kiB in length currently."); uint32_t lba = start & 0x00ffffff; @@ -92,7 +92,7 @@ static uint32_t ide_ata_rs(const struct drive *d, uint32_t start, uint32_t count } static uint32_t ide_ata_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { - panic("IDE ATA writing not implemented yet"); + PANIC("IDE ATA writing not implemented yet."); return 0; } @@ -104,11 +104,11 @@ static uint32_t ide_atapi_rs(const struct drive *d, uint32_t start, uint32_t cou if (!count) return 0; - + PANIC("IDE ATAPI reading not implemented yet."); } static uint32_t ide_atapi_ws(const struct drive *d, uint32_t start, uint32_t count, const void *buffer) { - panic("IDE ATAPI writing not implemented yet"); + PANIC("IDE ATAPI writing not implemented yet."); return 0; } @@ -122,7 +122,7 @@ struct id_space { static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { if (n_ide_drives == MAX_IDE_DRIVES) - panic("Maximum number of IDE drives reached."); + PANIC("Maximum number of IDE drives reached."); struct ide_drive_info *next = ide_drives + n_ide_drives; struct drive next_d; @@ -161,7 +161,7 @@ static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { else { uint16_t code = inb(base_port | 0x4) + (inb(base_port | 0x5) << 8); if (!code) { - panic("PATA identification aborted."); + PANIC("PATA identification aborted."); } if (code == 0xeb14) { next_d.drive_type = "IDE PATAPI"; @@ -181,7 +181,7 @@ static void test_drive(uint16_t base_port, uint16_t alt_port, bool slave) { //in the future, maybe add support for 48-bit LBA, and/or CHS addressing if (!ids.max_lba) - panic("Encountered ATA drive that doesn't support 28-bit LBA"); + PANIC("Encountered ATA drive that doesn't support 28-bit LBA."); next_d.n_sectors = ids.max_lba; commit_drive(next_d); diff --git a/src/kernel/idt.c b/src/kernel/idt.c index 3d23797..4dc8a36 100644 --- a/src/kernel/idt.c +++ b/src/kernel/idt.c @@ -7,12 +7,11 @@ #include "task.h" #include "paging.h" #include "pmap.h" +#include "kbd.h" enum { IDT_PRESENT = 0x80, - IDT_INT = 0x0e, - IDT_TRAP = 0x0f }; struct idt_entry { @@ -55,21 +54,13 @@ static uint32_t sc_file_read(uint32_t handle, uint32_t file_offset, uint32_t cou return count; } -static bool sc_start_task(uint32_t drive_number, char *path) { +static bool sc_start_task(uint32_t drive_number, char *path, const char *pass) { switch_to_kernel_cr3(); - bool result = try_elf_run(drives + drive_number, path); + bool result = try_elf_run(drives + drive_number, vma_to_pma(active_task->page_directory, path), pass); switch_to_task_cr3(); return result; } -static void sc_log_string(char *sz) { - logsz(sz); -} - -static char sc_get_key() { - panic("TODO: get key system call"); -} - static void *sc_allocate_ram(uint32_t pages) { return pd_user_allocate_anywhere_writable(active_task->page_directory, pages); } @@ -94,7 +85,7 @@ static uint32_t sc_memory_info(enum mi_arg arg) { case MI_USER_LEFT: return user_pages_left; case MI_TASK_LEFT: - panic("TODO: this process memory left"); + PANIC("TODO: memory info task left"); default: return -1; } @@ -106,18 +97,21 @@ void const *syscall_table[] = { &sc_file_read, &sc_file_get_size, &sc_start_task, - &sc_log_string, - &sc_get_key, + &logsz, + &get_key_code, &sc_allocate_ram, &sc_memory_info }; -typedef void isr_t; +//these aren't really void (*)()'s, but gcc complains if we take an address of a void, so we give it a type +typedef void (*isr_t)(); extern isr_t syscall_isr; extern isr_t quit_isr; extern isr_t yield_isr; +extern isr_t kbd_isr; + static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { idt[n].addr_low = (uint32_t)isr & 0xffff; idt[n].addr_high = (uint32_t)isr >> 16; @@ -125,6 +119,17 @@ static void register_int(uint8_t n, isr_t *isr, uint8_t dpl) { idt[n].flags = IDT_PRESENT | (dpl << 5) | IDT_INT; } +enum { + PIC_MCMD = 0x0020, + PIC_MDATA = 0x0021, + PIC_SCMD = 0x00a0, + PIC_SDATA = 0x00a1 +}; + +enum { + PIC_RESET = 0x11 +}; + void init_idt() { for (uint16_t i = 0; i < 256; ++i) { idt[i].flags = 0; @@ -135,8 +140,22 @@ void init_idt() { register_int(0x38, &quit_isr, 3); register_int(0x39, &yield_isr, 3); - outb(0x0021, 0xff); - outb(0x00a1, 0xff); + register_int(0x21, &kbd_isr, 0); + + outb(PIC_MCMD, PIC_RESET); + outb(PIC_SCMD, PIC_RESET); + + outb(PIC_MDATA, 0x20); + outb(PIC_SDATA, 0x28); + + outb(PIC_MDATA, 0x04); + outb(PIC_SDATA, 0x02); + + outb(PIC_MDATA, 0x01); + outb(PIC_SDATA, 0x01); + + outb(PIC_MDATA, 0xfd); + outb(PIC_SDATA, 0xff); asm volatile ( "lidt %0" diff --git a/src/kernel/isrs.asm b/src/kernel/isrs.asm index 82c17fe..9a9600c 100644 --- a/src/kernel/isrs.asm +++ b/src/kernel/isrs.asm @@ -4,12 +4,15 @@ global syscall_isr global quit_isr global yield_isr global _start_user_mode +global kbd_isr extern syscall_table extern active_task extern delete_task extern advance_active_task +extern on_kbd_isr +extern make_sure_tasks n_syscalls equ 0x9 @@ -39,6 +42,7 @@ syscall_isr: quit_isr: push dword [active_task] call delete_task + call make_sure_tasks mov dword [esp], yield_isr.return_to_task jmp advance_active_task @@ -59,7 +63,7 @@ yield_isr: mov dword [eax + 4], edx mov edx, dword [esp + 12] - mov dword [eax + 4], edx + mov dword [eax + 32], edx call advance_active_task @@ -72,8 +76,8 @@ yield_isr: mov edx, dword [eax + 4] mov cr3, edx - mov edx, dword [eax + 4] - mov dword [esp + 24], edx + mov edx, dword [eax + 32] + mov dword [esp + 12], edx mov ebx, dword [eax + 8] mov ecx, dword [eax + 12] @@ -94,4 +98,19 @@ _start_user_mode: push dword 0x00000200;interrupt flag push dword 0x23 sub esp, 4 - jmp yield_isr.return_to_task \ No newline at end of file + jmp yield_isr.return_to_task + +kbd_isr: + push eax + push ecx + push edx + + call on_kbd_isr + + mov al, 0x20 + out 0x0020, al + + pop edx + pop ecx + pop eax + iret \ No newline at end of file diff --git a/src/kernel/kbd.c b/src/kernel/kbd.c new file mode 100644 index 0000000..73a5ec6 --- /dev/null +++ b/src/kernel/kbd.c @@ -0,0 +1,285 @@ +#include +#include +#include "panic.h" +#include "log.h" +#include "util.h" + +static uint32_t *kbd_in_pointer; +static uint32_t *kbd_out_pointer; + +#define KBD_BUFFER_LENGTH 1024 +static uint32_t kbd_buffer[KBD_BUFFER_LENGTH]; + +static uint32_t mod_mask; + +enum { + PS2_CMD = 0x64, + PS2_DATA = 0x60 +}; + +enum { + PS2C_READ_CONFIG = 0x20, + PS2C_WRITE_CONFIG = 0x60, + PS2C_DISABLE = 0xad, + PS2C_ENABLE = 0xae +}; + +enum { + PS2S_CODE_READY = 0x01 +}; + +enum { + PS2G_XT_COMPAT = 0x40 +}; + +void init_kbd() { + outb(PS2_CMD, PS2C_READ_CONFIG); + uint8_t config = inb(PS2_DATA); + outb(PS2_CMD, PS2C_WRITE_CONFIG); + outb(PS2_DATA, config | PS2G_XT_COMPAT); + + kbd_in_pointer = kbd_buffer; + kbd_out_pointer = kbd_buffer; + mod_mask = 0; +} + +uint32_t get_key_code() { + if (kbd_in_pointer == kbd_out_pointer) + return 0; + uint32_t code = *kbd_out_pointer; + if (++kbd_out_pointer == kbd_buffer + KBD_BUFFER_LENGTH) + kbd_out_pointer = kbd_buffer; + return code; +} + +enum { + MOD_LSHIFT = 0x00100, + MOD_RSHIFT = 0x00200, + MOD_CAPS = 0x00400, + MOD_INSERT = 0x00800, + MOD_NUMPAD = 0x01000, + MOD_SCROLL = 0x02000, + MOD_LALT = 0x04000, + MOD_RALT = 0x08000, + MOD_LCTRL = 0x10000, + MOD_RCTRL = 0x20000, + MOD_LMETA = 0x40000, + MOD_RMETA = 0x80000 +}; + +enum { + CODE_CAPS = 0x80, + CODE_INSERT, + CODE_NUMPAD, + CODE_SCROLL, + CODE_LSHIFT, + CODE_RSHIFT, + CODE_LALT, + CODE_RALT, + CODE_LCTRL, + CODE_RCTRL, + CODE_LMETA, + CODE_RMETA, + /* 0x8c - 0x97 reserved */ + /* 0x98 - 0x9f unassigned */ + CODE_F1 = 0xa0, + CODE_F2, + CODE_F3, + CODE_F4, + CODE_F5, + CODE_F6, + CODE_F7, + CODE_F8, + CODE_F9, + CODE_F10, + CODE_F11, + CODE_F12, + /* 0xac - 0xaf unassigned */ + CODE_NUM0 = 0xb0, + CODE_NUM1, + CODE_NUM2, + CODE_NUM3, + CODE_NUM4, + CODE_NUM5, + CODE_NUM6, + CODE_NUM7, + CODE_NUM8, + CODE_NUM9, + CODE_NTIMES, + CODE_NPLUS, + CODE_NENTER, + CODE_NMINUS, + CODE_NDOT, + CODE_NSLASH, + /* 0xc0 unassigned */ + CODE_DELETE, + CODE_HOME, + CODE_END, + CODE_PUP, + CODE_PDOWN, + CODE_UP, + CODE_DOWN, + CODE_LEFT, + CODE_RIGHT, + CODE_ESC, + CODE_MENU, + CODE_PAUSE, + CODE_PRSCR, + /* 0xce - 0xef unassigned */ + CODE_END_LSHIFT = 0xf0, + CODE_END_RSHIFT, + CODE_END_LALT, + CODE_END_RALT, + CODE_END_LCTRL, + CODE_END_RCTRL, + CODE_END_LMETA, + CODE_END_RMETA +}; + +static const uint32_t mod_bits[] = { + MOD_CAPS, + MOD_INSERT, + MOD_NUMPAD, + MOD_SCROLL, + MOD_LSHIFT, + MOD_RSHIFT, + MOD_LALT, + MOD_RALT, + MOD_LCTRL, + MOD_RCTRL, + MOD_LMETA, + MOD_RMETA +}; + +static const uint32_t *const unmod_bits = mod_bits + 4; + +//in these tables, 0x00 represents an unknown key, +// and 0xff represents a key release. + +static const uint8_t codes[] = { + 0, CODE_ESC, '1', '2', '3', '4', '5', '6', + '7', '8', '9', '0', '-', '=', '\b', '\t', + 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', + 'o', 'p', '[', ']', '\n', CODE_LCTRL, 'a', 's', + 'd', 'f', 'g', 'h', 'j', 'k', 'l', ';', + '\'', '`', CODE_LSHIFT, '\\', 'z', 'x', 'c', 'v', + 'b', 'n', 'm', ',', '.', '/', CODE_RSHIFT, CODE_NTIMES, + CODE_LALT, ' ', CODE_CAPS, CODE_F1, CODE_F2, CODE_F3, CODE_F4, CODE_F5, + CODE_F6, CODE_F7, CODE_F8, CODE_F9, CODE_F10, CODE_NUMPAD, CODE_SCROLL, CODE_NUM7, + CODE_NUM8, CODE_NUM9, CODE_NMINUS, CODE_NUM4, CODE_NUM5, CODE_NUM6, CODE_NPLUS, CODE_NUM1, + CODE_NUM2, CODE_NUM3, CODE_NUM0, CODE_NDOT, 0, 0, 0, CODE_F11, + CODE_F12, 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, 0, 0, 0, 0, 0, + + 0, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_LCTRL, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, CODE_END_LSHIFT, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, CODE_END_RSHIFT, 0xff, + CODE_END_LALT, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, + 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0xff, + 0xff, 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, 0, 0, 0, 0, 0 +}; + +static const uint8_t codes_e0[] = { + 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, CODE_NENTER, CODE_RCTRL, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, CODE_NSLASH, 0, 0, + CODE_RALT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, CODE_HOME, + CODE_UP, CODE_PUP, 0, CODE_LEFT, 0, CODE_RIGHT, 0, CODE_END, + CODE_DOWN, CODE_PDOWN, CODE_INSERT, CODE_DELETE, 0, 0, 0, 0, + 0, 0, 0, CODE_LMETA, CODE_RMETA, CODE_MENU, 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, + + 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, 0xff, CODE_END_RCTRL, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0xff, 0, 0, + CODE_END_RALT, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0xff, + 0xff, 0xff, 0, 0xff, 0, 0xff, 0, 0xff, + 0xff, 0xff, 0xff, 0xff, 0, 0, 0, 0, + 0, 0, 0, CODE_END_LMETA, CODE_END_RMETA, 0xff, 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 +}; + +void on_kbd_isr() { + while (inb(PS2_CMD) & PS2S_CODE_READY) { + uint8_t code = inb(PS2_DATA); + if (code == 0xe1) { + code = inb(PS2_DATA); + if (code == 0x1d) { + if (inb(PS2_DATA) != 0x45) + code = 0; + else + code = CODE_PAUSE; + } + else if (code == 0x9d) { + if (inb(PS2_DATA) != 0xc5) + code = 0; + else + code = 0xff; + } + else + code = 0; + } + else if (code == 0xe0) { + code = inb(PS2_DATA); + if (code == 0x2a) { + if ((inb(PS2_DATA) != 0xe0) || + (inb(PS2_DATA) != 0x37)) + code = 0; + else + code = CODE_PRSCR; + } + else if (code == 0xb7) { + if ((inb(PS2_DATA) != 0xe0) || + (inb(PS2_DATA) != 0xaa)) + code = 0; + else + code = 0xff; + } + else + code = codes_e0[code]; + } + else + code = codes[code]; + + if (!code) + PANIC("Unknown scancode."); + + if (code < 0xf0) + *kbd_in_pointer++ = mod_mask | code; + if ((code >= 0x80) && (code <= 0x83)) + mod_mask ^= mod_bits[code & 0x03]; + else if ((code >= 0x84) && (code <= 0x8b)) + mod_mask |= mod_bits[code & 0x0f]; + else if (code >= 0xf0) + mod_mask &= ~unmod_bits[code & 0x0f]; + } +} \ No newline at end of file diff --git a/src/kernel/kbd.h b/src/kernel/kbd.h new file mode 100644 index 0000000..8a4ed8b --- /dev/null +++ b/src/kernel/kbd.h @@ -0,0 +1,10 @@ +#ifndef KBD_H +#define KBD_H + +#include + +void init_kbd(); +uint32_t get_key_code(); +void on_kbd_isr(); + +#endif \ No newline at end of file diff --git a/src/kernel/main.c b/src/kernel/main.c index d99b595..e2a23e8 100644 --- a/src/kernel/main.c +++ b/src/kernel/main.c @@ -13,6 +13,7 @@ #include "elf.h" #include "log.h" #include "vga.h" +#include "kbd.h" void reset_tree(); void tree(struct drive *d); @@ -32,8 +33,6 @@ void main() { logsz("Portland v0.0.11\n\n"); - //list vesa modes? - pci_init(); u16_dec(n_pci_devices, nbuf); @@ -137,9 +136,10 @@ void main() { logsz(nbuf); logsz("k\n\n"); - if (!try_elf_run(drives, "BIN/INIT.ELF")) - panic("Failed to load init program."); + if (!try_elf_run(drives, "BIN/INIT.ELF", "")) + PANIC("Failed to load init program."); + init_kbd(); init_idt(); logsz("Switching to init task.\n"); diff --git a/src/kernel/paging.c b/src/kernel/paging.c index 36fb8a7..a0f7c3d 100644 --- a/src/kernel/paging.c +++ b/src/kernel/paging.c @@ -77,27 +77,47 @@ void *new_task_pd() { void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable) { void *pma = allocate_user_pages(pages); if (!pma) - panic("Could not allocate user pages."); + PANIC("Could not allocate user pages."); for (uint32_t i = 0; i < pages; ++i) pd_map(pd, (uint32_t)pma + (i << 12), vma + (i << 12), writable); return pma; } -void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages) { +__attribute__ ((pure)) +static void *find_user_vma_run(void *pd, uint32_t pages) { uint32_t run = 0; for (void *vma = (void *)KERNEL_END; vma; vma += 4096) { if (pd_is_mapped(pd, (uint32_t)vma)) run = 0; - else if (++run == pages) { - vma -= (pages - 1) * 4096; - for (uint32_t i = 0; i < pages; ++i) - pd_map(pd, (uint32_t)allocate_user_pages(1), (uint32_t)vma + 4096 * i, true); - return vma; - } + else if (++run == pages) + return vma - (pages - 1) * 4096; } return 0; } +void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages) { + void *vma = find_user_vma_run(pd, pages); + if (!vma) + return 0; + for (uint32_t i = 0; i < pages; ++i) + pd_map(pd, (uint32_t)allocate_user_pages(1), (uint32_t)vma + 4096 * i, true); + return vma; +} + +void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **vma_out, void **pma_out) { + *vma_out = find_user_vma_run(pd, pages); + if (!*vma_out) { + *pma_out = 0; + return; + } + *pma_out = allocate_user_pages(pages); + if (!*pma_out) { + *vma_out = 0; + return; + } + pd_map(pd, (uint32_t)*pma_out, (uint32_t)*vma_out, false); +} + #define KPAGE_DIR ((uint32_t *)0x00005000) #define KPAGE_TABLE_0 ((uint32_t *)0x00400000) @@ -118,6 +138,11 @@ void init_paging() { : : : "eax"); } +__attribute__ ((pure)) +void *vma_to_pma(void *pd, const void *vma) { + return (void *)(((uint32_t *)(((uint32_t *)pd)[(uint32_t)vma >> 22] & PE_ADDR_MASK))[((uint32_t)vma >> 12) % 1024] & PE_ADDR_MASK) + (uint32_t)vma % 4096; +} + void switch_to_kernel_cr3() { asm volatile ( "mov $0x00005000, %%eax\n" diff --git a/src/kernel/paging.h b/src/kernel/paging.h index e39b3f2..07bf386 100644 --- a/src/kernel/paging.h +++ b/src/kernel/paging.h @@ -11,6 +11,9 @@ void free_task_pd(void *pd); void *new_task_pd(); void *pd_user_allocate(void *pd, uint32_t vma, uint32_t pages, bool writable); void *pd_user_allocate_anywhere_writable(void *pd, uint32_t pages); +void user_allocate_anywhere_readonly_together(void *pd, uint32_t pages, void **vma_out, void **pma_out); + +void *vma_to_pma(void *pd, const void *vma) __attribute__ ((pure)); void switch_to_kernel_cr3(); void switch_to_task_cr3(); \ No newline at end of file diff --git a/src/kernel/panic.c b/src/kernel/panic.c index a2e68e3..5d32bf7 100644 --- a/src/kernel/panic.c +++ b/src/kernel/panic.c @@ -1,11 +1,17 @@ -#include "panic.h" #include "log.h" #include "vga.h" +#include "util.h" -void panic(const char *message) { +__attribute__ ((noreturn)) +void panic(const char *filename, uint32_t line, const char *message) { set_log_mode(LOG_PANIC); vga_blank(); - logsz("Kernel panic: "); + logsz("Kernel panic ["); + logsz(filename); + char nbuf[12] = ":"; + u32_dec(line, nbuf + 1); + logsz(nbuf); + logsz("]: "); logsz(message); logsz("\nHalting."); while (1) diff --git a/src/kernel/panic.h b/src/kernel/panic.h index 08328f2..6a8609f 100644 --- a/src/kernel/panic.h +++ b/src/kernel/panic.h @@ -1,6 +1,10 @@ #ifndef PANIC_H #define PANIC_H -void panic(const char *message) __attribute__ ((noreturn)); +#include + +#define PANIC(msg) panic(__FILE__, __LINE__, msg) + +void panic(const char *filename, uint32_t line, const char *message) __attribute__ ((noreturn)); #endif \ No newline at end of file diff --git a/src/kernel/pci.c b/src/kernel/pci.c index 9e33e49..14e24a4 100644 --- a/src/kernel/pci.c +++ b/src/kernel/pci.c @@ -32,7 +32,7 @@ struct pci_device *find_pci_device_from_class_and_subclass(uint8_t class, uint8_ static struct pci_device *next_pci_device() { if (!(n_pci_devices % PCI_DEVICES_PER_PAGE)) if (!(pci_device_pages[n_pci_devices / PCI_DEVICES_PER_PAGE] = allocate_kernel_pages(1))) - panic("Out of memory in PCI enumeration"); + PANIC("Out of memory in PCI enumeration."); return nth_pci_device(n_pci_devices++); } @@ -64,9 +64,9 @@ static void pci_device_check(uint16_t number) { void pci_init() { if (!(BOOT_INFO->support_flags & BIS_PCI)) - panic("No PCI support detected."); + PANIC("No PCI support detected."); if (!(BOOT_INFO->pci_hw_char & PHC_CS_M1)) - panic("No PCI Mechanism 1 support"); + PANIC("No PCI Mechanism 1 support."); n_pci_devices = 0; diff --git a/src/kernel/task.c b/src/kernel/task.c index 2a1f4c4..e2c19ca 100644 --- a/src/kernel/task.c +++ b/src/kernel/task.c @@ -70,24 +70,26 @@ void new_task(struct task_state state) { tasks[n] = state; return; } - panic("Maximum number of tasks reached."); + PANIC("Maximum number of tasks reached."); } void advance_active_task() { - struct task_state *prev_task = active_task; - do { + do if (++active_task == tasks + MAX_TASKS) active_task = tasks; - if (active_task == prev_task) { - set_log_mode(LOG_SYSTEM); - logsz("No active tasks, halting."); - while (1) - asm ("hlt"); - } - } while (!active_task->page_directory); } +void make_sure_tasks() { + for (uint8_t n = 0; n < MAX_TASKS; ++n) + if (tasks[n].page_directory) + return; + set_log_mode(LOG_SYSTEM); + logsz("No active tasks, halting."); + while (1) + asm ("hlt"); +} + void delete_task(struct task_state *state) { free_task_pd(state->page_directory); state->page_directory = 0; diff --git a/src/user/hello/hello.c b/src/user/hello/hello.c deleted file mode 100644 index 00d33b5..0000000 --- a/src/user/hello/hello.c +++ /dev/null @@ -1,5 +0,0 @@ -#include - -void main() { - tell_user_sz("Hello, world!\n"); -} \ No newline at end of file diff --git a/src/user/highway/highway.c b/src/user/highway/highway.c new file mode 100644 index 0000000..effc131 --- /dev/null +++ b/src/user/highway/highway.c @@ -0,0 +1,21 @@ +#include +#include +#include + +//TODO: load a user environment file containing a PATH-like setting. +//TODO: have an active disk and/or directory + +void main() { + char path_buf[1024 + 4] = "BIN/"; + char *const line_buf = path_buf + 4; + while (1) { + tell_user_sz("> "); + ask_user_line_sz(line_buf, 1023); + if (blockequ(line_buf, "exit", 5)) + return; + if (try_run_command(path_buf)) + yield_task(); + else + tell_user_sz("An error occured trying to run that command.\n"); + } +} \ No newline at end of file diff --git a/src/user/include/knob/block.h b/src/user/include/knob/block.h new file mode 100644 index 0000000..2aa2b36 --- /dev/null +++ b/src/user/include/knob/block.h @@ -0,0 +1,7 @@ +#ifndef KNOB_BLOCK_H +#define KNOB_BLOCK_H + +void blockcpy(void *to, const void *from, uint32_t size); +bool blockequ(void *a, void *b, uint32_t size) __attribute__ ((__pure__)); + +#endif \ No newline at end of file diff --git a/src/user/include/knob/user.h b/src/user/include/knob/user.h index c4ec7db..45caab4 100644 --- a/src/user/include/knob/user.h +++ b/src/user/include/knob/user.h @@ -6,7 +6,8 @@ void tell_user_sz(const char *sz); void tell_user_n(uint32_t n); -//return value and max_length both include null terminator +//return value and max_length don't include null terminator +//returns the real length of the string uint32_t ask_user_line_sz(char *sz, uint32_t max_length); #endif \ No newline at end of file diff --git a/src/user/include/pland/syscall.h b/src/user/include/pland/syscall.h index 298fc51..c597e2b 100644 --- a/src/user/include/pland/syscall.h +++ b/src/user/include/pland/syscall.h @@ -97,7 +97,7 @@ static inline uint32_t _sc5(enum _scn eax, uint32_t ebx, uint32_t ecx, uint32_t static inline void _yield_task() { asm ( "int $0x39" - ); + : : : "eax"); } __attribute__ ((noreturn)) @@ -124,8 +124,8 @@ static inline uint32_t _file_size(_file_handle_t handle) { return _sc1(_SCN_FILE_SIZE, handle); } -static inline bool _start_task(_drive_number_t drive_number, const char *path) { - return (bool)_sc2(_SCN_START_TASK, drive_number, (uint32_t)path); +static inline bool _start_task(_drive_number_t drive_number, const char *path, const char *pass) { + return (bool)_sc3(_SCN_START_TASK, drive_number, (uint32_t)path, (uint32_t)pass); } static inline void _log_string(const char *sz) { diff --git a/src/user/init/init.c b/src/user/init/init.c index b8536be..64c534e 100644 --- a/src/user/init/init.c +++ b/src/user/init/init.c @@ -2,13 +2,27 @@ #include #include +void start(const char *cmd) { + tell_user_sz(cmd); + tell_user_sz(": "); + tell_user_sz( + try_run_command(cmd) + ? "success\n" + : "failed\n" + ); +} + +#define STARTUP_FILE_PATH "SYS/STARTUP.RC" + void main() { - struct file *f = open_file("SYS/STARTUP.RC"); + struct file *f = open_file(STARTUP_FILE_PATH); if (!f) { - tell_user_sz("Could not open SYS/STARTUP.RC\n"); + tell_user_sz("Could not open " STARTUP_FILE_PATH "\n"); return; } + tell_user_sz("[init] Reading from " STARTUP_FILE_PATH ":\n"); + char buf[1024]; char *bufp = buf; while (read_from_file(f, 1, bufp)) { @@ -16,7 +30,7 @@ void main() { if (bufp == buf) continue; *bufp = '\0'; - try_run_command(buf); + start(buf); bufp = buf; } else @@ -24,8 +38,10 @@ void main() { } if (bufp != buf) { *bufp = '\0'; - try_run_command(buf); + start(buf); } close_file(f); + + tell_user_sz("[init] Done.\n"); } diff --git a/src/user/knob/block.c b/src/user/knob/block.c new file mode 100644 index 0000000..e890fa1 --- /dev/null +++ b/src/user/knob/block.c @@ -0,0 +1,17 @@ +#include +#include + +//unsophisticated, should copy by dwords where available +void blockcpy(void *to, const void *from, uint32_t size) { + for (uint32_t i = 0; i < size; ++i) + *(uint8_t *)(to++) = *(const uint8_t *)(from++); +} + +//unsophisticated, should check by dwords wheere available +__attribute__ ((__pure__)) +bool blockequ(void *a, void *b, uint32_t size) { + for (uint32_t i = 0; i < size; ++i) + if (*(uint8_t *)(a++) != *(uint8_t *)(b++)) + return false; + return true; +} \ No newline at end of file diff --git a/src/user/knob/entry.asm b/src/user/knob/entry.asm index ae024c4..18faf7f 100644 --- a/src/user/knob/entry.asm +++ b/src/user/knob/entry.asm @@ -10,6 +10,7 @@ extern current_disk section .text _entry: mov esp, stack + push edx ;TODO: heap stuff? ;TODO: determine current_disk diff --git a/src/user/knob/quit.c b/src/user/knob/quit.c index a2ef5aa..7c20bdd 100644 --- a/src/user/knob/quit.c +++ b/src/user/knob/quit.c @@ -1,29 +1,6 @@ #include -#include - -struct quit_list_node { - struct quit_list_node *prev; - void (*f)(); -}; - -static struct quit_list_node head = { - .f = &_exit_task -}; - -static struct quit_list_node *last = &head; - -void on_quit(void (*run_f)()) { - struct quit_list_node *new = get_block(sizeof(struct quit_list_node)); - new->prev = last; - new->f = run_f; - last = new; -} __attribute__ ((noreturn)) void quit() { - struct quit_list_node *node = last; - while (1) { - node->f(); - node = node->prev; - } + _exit_task(); } \ No newline at end of file diff --git a/src/user/knob/task.c b/src/user/knob/task.c index aa18eab..598bee2 100644 --- a/src/user/knob/task.c +++ b/src/user/knob/task.c @@ -1,11 +1,25 @@ #include #include #include +#include +#include bool try_run_command(const char *path) { uint8_t dn; path = remove_prefix(path, &dn); - return _start_task(dn, path); + + for (const char *ptr = path; *ptr; ++ptr) + if (*ptr == ' ') { + char *new_path = get_block(ptr - path + 1); + blockcpy(new_path, path, ptr - path); + new_path[ptr - path] = '\0'; + + bool succeded = _start_task(dn, new_path, ptr + 1); + free_block(new_path); + return succeded; + } + + return _start_task(dn, path, ""); } void yield_task() { diff --git a/src/user/knob/user.c b/src/user/knob/user.c index fb39851..4ef3321 100644 --- a/src/user/knob/user.c +++ b/src/user/knob/user.c @@ -19,9 +19,25 @@ static const uint8_t caps_and_shift[] = { 0x7e, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6a, 0x6b, 0x6c, 0x6d, 0x6e, 0x6f, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77, - 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 - - //TODO: higher + 0x78, 0x79, 0x7a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t caps_no_shift[] = { @@ -41,9 +57,25 @@ static const uint8_t caps_no_shift[] = { 0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 - - //TODO: higher + 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static const uint8_t shifted[] = { @@ -63,28 +95,39 @@ static const uint8_t shifted[] = { 0x7e, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4a, 0x4b, 0x4c, 0x4d, 0x4e, 0x4f, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57, - 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00 - - //TODO: higher + 0x58, 0x59, 0x5a, 0x7b, 0x7c, 0x7d, 0x7e, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 }; static char get_key_char() { _key_code_t key; while (!(key = _get_key())) _yield_task(); - return (char)( - (key & (_KEY_ALT | _KEY_CTRL | _KEY_META)) - ? 0 - : (key & _KEY_CAPS) - ? (key & _KEY_SHIFT) - ? caps_and_shift[key & 0xff] - : caps_no_shift[key & 0xff] - : (key & _KEY_SHIFT) - ? shifted[key & 0xff] - : (key & 0x80) - ? 0 - : (key & 0x7f) - ); + return + key & _KEY_CAPS + ? key & _KEY_SHIFT + ? caps_and_shift[key & 0xff] + : caps_no_shift[key & 0xff] + : key & _KEY_SHIFT + ? shifted[key & 0xff] + : key & 0xff; } void tell_user_sz(const char *sz) { @@ -115,18 +158,23 @@ uint32_t ask_user_line_sz(char *sz, uint32_t max_length) { uint32_t i; for (i = 0; i != max_length; ++i) { - char key = get_key_char(); - if (key) { - log_buf[0] = key; - _log_string(log_buf); - - if (key == '\b') - i -= i ? 2 : 1; - else if (key == '\n') - break; - else - sz[i] = key; - } + char key; + replace: + key = get_key_char(); + if (!key) + goto replace; + if (key & 0x80) + goto replace;//TODO + + log_buf[0] = key; + _log_string(log_buf); + + if (key == '\b') + i -= i ? 2 : 1; + else if (key == '\n') + break; + else + sz[i] = key; } sz[i] = '\0'; -- cgit v1.2.3