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 --- doc/ints.txt | 26 ++-- doc/keys.txt | 73 +++++++++- fs-skel/sys/startup.rc | 2 +- makefile | 31 +++-- qemu-debug.gdb | 1 - 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 +++++++++++----- 32 files changed, 730 insertions(+), 179 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 diff --git a/doc/ints.txt b/doc/ints.txt index cd91f60..dd47d81 100644 --- a/doc/ints.txt +++ b/doc/ints.txt @@ -9,31 +9,33 @@ syscall is int 0x30 system call number in eax args in ebx, ecx, edx, esi, edi result in eax - note: do not assume eax is unmodified if there is no value to be returned modifies ecx, edx +modifies eax even if no value is returned see table 1 file system calls have units of bytes unless otherwise specified functions returning handles or pointers use 0 to indicate error functions returning "success" use 1 for success and 0 for failure see keys.txt for the return type of the "get key" system call +the edx register of "start task" is a pointer to a null-terminated string. + a pointer to a readonly copy of this string is put into the new task's edx. invalid system call numbers change eax to -1, and have no other effect. table 1: - function | eax | eax out | ebx | ecx | edx | esi | edi ----------------|-----|---------------|---------------|-------------|-------|--------|----- - open file | 0x0 | handle | drive number | path | | | - close file | 0x1 | | handle | | | | - file read | 0x2 | read | handle | file offset | count | buffer | - get file size | 0x3 | size | handle | | | | - start task | 0x4 | success | drive number | path | | | - log string | 0x5 | | sz string | | | | - get key | 0x6 | keycode | | | | | - allocate ram | 0x7 | start pointer | pages | | | | - memory info | 0x8 | see table 2 | see table 2 | | | | + function | eax | eax out | ebx | ecx | edx | esi | edi +---------------|-----|---------------|---------------|-------------|-----------|--------|----- + open file | 0x0 | handle | drive number | path | | | + close file | 0x1 | | handle | | | | + file read | 0x2 | read | handle | file offset | count | buffer | + get file size | 0x3 | size | handle | | | | + start task | 0x4 | success | drive number | path | passed sz | | + log string | 0x5 | | sz string | | | | + get key | 0x6 | keycode | | | | | + allocate ram | 0x7 | start pointer | pages | | | | + memory info | 0x8 | see table 2 | see table 2 | | | | table 2: diff --git a/doc/keys.txt b/doc/keys.txt index a083eba..8deb480 100644 --- a/doc/keys.txt +++ b/doc/keys.txt @@ -2,7 +2,7 @@ keycodes are 32-bit integers. the low byte indicates the key itself. for printable characters (and keys with reasonable translations to ascii control codes), this is the ascii code. for -other ones, something in the range of 0x80 to 0xff is used, seen in table 1. +other ones, something in the range of 0x80 to 0xef is used, seen in table 1. the top 24 bits indicate several flags. these are seen in table 2, where bit 0 is the lowest bit of the second lowest byte of the keycode, and bit 23 is the @@ -18,10 +18,73 @@ user.c of the "knob" library for an example of this. table 1: code | key -------|----- - 0x80 | - .... | - 0xff | +------|--------------- + 0x80 | caps lock + 0x81 | insert + 0x82 | num lock + 0x83 | scroll lock + 0x84 | left shift + 0x85 | right shift + 0x86 | left alt + 0x87 | right alt + 0x88 | left control + 0x89 | right control + 0x8a | left meta + 0x8b | right meta + 0x8c | reserved + .... | reserved + 0x97 | reserved + 0x98 | unassigned + .... | unassigned + 0x9f | unassigned + 0xa0 | F1 + 0xa1 | F2 + 0xa2 | F3 + 0xa3 | F4 + 0xa4 | F5 + 0xa5 | F6 + 0xa6 | F7 + 0xa7 | F8 + 0xa8 | F9 + 0xa9 | F10 + 0xaa | F11 + 0xab | F12 + 0xac | unassigned + .... | unassigned + 0xaf | unassigned + 0xb0 | numpad 0 + 0xb1 | numpad 1 + 0xb2 | numpad 2 + 0xb3 | numpad 3 + 0xb4 | numpad 4 + 0xb5 | numpad 5 + 0xb6 | numpad 6 + 0xb7 | numpad 7 + 0xb8 | numpad 8 + 0xb9 | numpad 9 + 0xba | numpad * + 0xbb | numpad + + 0xbc | numpad Enter + 0xbd | numpad - + 0xbe | numpad . + 0xbf | numpad / + 0xc0 | unassigned + 0xc1 | delete + 0xc2 | home + 0xc3 | end + 0xc4 | page up + 0xc5 | page down + 0xc6 | up + 0xc7 | down + 0xc8 | left + 0xc9 | right + 0xca | escape + 0xcb | menu + 0xcc | pause + 0xcd | print screen + 0xce | unassigned + .... | unassigned + 0xef | unassigned table 2: diff --git a/fs-skel/sys/startup.rc b/fs-skel/sys/startup.rc index c13d593..ba7174f 100644 --- a/fs-skel/sys/startup.rc +++ b/fs-skel/sys/startup.rc @@ -1,2 +1,2 @@ BIN/MEMINFO.ELF -BIN/HELLO.ELF \ No newline at end of file +BIN/HIGHWAY.ELF \ No newline at end of file diff --git a/makefile b/makefile index 8ddce57..aec355f 100644 --- a/makefile +++ b/makefile @@ -1,12 +1,14 @@ -kgccargs = -Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const -Wsuggest-attribute=malloc -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables +kgccargs = -Wall -Wsuggest-attribute=pure -Wsuggest-attribute=const -m32 -Og -ffreestanding -fno-asynchronous-unwind-tables ugccargs = ${kgccargs} -Isrc/user/include nasmargs = -f elf32 partlink = -r -m elf_i386 out/disk.vdi: out/disk.img + rm out/disk.vdi || true VBoxManage convertfromraw out/disk.img out/disk.vdi --uuid a61929ed-3bf2-45ff-b98a-44f87c616dba out/disk.img: out/kernel.bin out/boot.bin out/fs + #TODO: have this regenerate after out/fs mkdir -p obj /sbin/mkfs.fat -C -f 1 -F 16 -n "PORTLAND OS" -R 65 -s 1 -S 512 obj/shadow.img 8192 echo -n -e '\xeb\x3c' > obj/jmp.bin @@ -22,12 +24,13 @@ debug: out/disk.img clean: rm -r obj out || true -out/fs: obj/hello.elf obj/init.elf obj/meminfo.elf - mkdir -p out/fs/bin +out/fs/bin/%.elf: obj/%.elf + mkdir -p $(shell dirname $@) + objcopy -S $< $@ + +out/fs: out/fs/bin/init.elf out/fs/bin/meminfo.elf out/fs/bin/highway.elf + mkdir -p out/fs cp -r fs-skel/* out/fs/ - objcopy -S obj/hello.elf out/fs/bin/hello.elf - objcopy -S obj/init.elf out/fs/bin/init.elf - objcopy -S obj/meminfo.elf out/fs/bin/meminfo.elf obj/kernel/%.ko: src/kernel/%.c mkdir -p $(shell dirname $@) @@ -42,7 +45,7 @@ out/kernel.bin: obj/kernel/drive.ko obj/kernel/fat.ko obj/kernel/ide.ko \ obj/kernel/main2.ko obj/kernel/pmap.ko obj/kernel/paging.ko \ obj/kernel/panic.ko obj/kernel/pci.ko obj/kernel/elf.ko \ obj/kernel/serial.ko obj/kernel/task.ko obj/kernel/util.ko \ - obj/kernel/vga.ko obj/kernel/isrs.kao + obj/kernel/vga.ko obj/kernel/isrs.kao obj/kernel/kbd.ko mkdir -p out ld -T src/kernel/elf-link.ld obj/kernel/* -o obj/kernel.elf objcopy -O binary obj/kernel.elf out/kernel.bin @@ -59,16 +62,16 @@ obj/%.ao: src/user/%.asm mkdir -p $(shell dirname $@) nasm ${nasmargs} $< -o $@ -obj/knob.so: obj/knob/env.o obj/knob/file.o obj/knob/format.o \ - obj/knob/heap.o obj/knob/quit.o obj/knob/user.o \ - obj/knob/task.o obj/knob/entry.ao +obj/knob.so: obj/knob/env.o obj/knob/file.o obj/knob/format.o \ + obj/knob/heap.o obj/knob/quit.o obj/knob/user.o \ + obj/knob/task.o obj/knob/entry.ao obj/knob/block.o ld ${partlink} obj/knob/* -o obj/knob.so -obj/hello.elf: obj/hello/hello.o obj/knob.so - ld -T src/user/elf.ld obj/hello/* obj/knob.so -o obj/hello.elf - obj/init.elf: obj/init/init.o obj/knob.so ld -T src/user/elf.ld obj/init/* obj/knob.so -o obj/init.elf obj/meminfo.elf: obj/meminfo/meminfo.o obj/knob.so - ld -T src/user/elf.ld obj/meminfo/* obj/knob.so -o obj/meminfo.elf \ No newline at end of file + ld -T src/user/elf.ld obj/meminfo/* obj/knob.so -o obj/meminfo.elf + +obj/highway.elf: obj/highway/highway.o obj/knob.so + ld -T src/user/elf.ld obj/highway/* obj/knob.so -o obj/highway.elf \ No newline at end of file diff --git a/qemu-debug.gdb b/qemu-debug.gdb index 2bb5c40..958eb89 100644 --- a/qemu-debug.gdb +++ b/qemu-debug.gdb @@ -4,5 +4,4 @@ set disassembly-flavor intel layout reg break main break panic -break _before_start_task cont 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