summaryrefslogtreecommitdiff
path: root/src/kernel
diff options
context:
space:
mode:
authorBenji Dial <benji6283@gmail.com>2020-09-13 03:19:57 -0400
committerBenji Dial <benji6283@gmail.com>2020-09-13 03:19:57 -0400
commit1e4a254674f668839e5de273916024c16814b045 (patch)
tree6774f4d4398a29c4aafb4120070975d864ffcde4 /src/kernel
parentb8284137d4e0eec11c78bc14047243fce6a51373 (diff)
downloadportland-os-1e4a254674f668839e5de273916024c16814b045.tar.gz
(basic, not much tested) keyboard, better panic
Diffstat (limited to 'src/kernel')
-rw-r--r--src/kernel/drive.c6
-rw-r--r--src/kernel/elf.c16
-rw-r--r--src/kernel/elf.h2
-rw-r--r--src/kernel/fat.c10
-rw-r--r--src/kernel/ide.c26
-rw-r--r--src/kernel/idt.c55
-rw-r--r--src/kernel/isrs.asm27
-rw-r--r--src/kernel/kbd.c285
-rw-r--r--src/kernel/kbd.h10
-rw-r--r--src/kernel/main.c8
-rw-r--r--src/kernel/paging.c41
-rw-r--r--src/kernel/paging.h3
-rw-r--r--src/kernel/panic.c12
-rw-r--r--src/kernel/panic.h6
-rw-r--r--src/kernel/pci.c6
-rw-r--r--src/kernel/task.c22
16 files changed, 461 insertions, 74 deletions
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 <stdint.h>
#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 <stdint.h>
+#include <stdbool.h>
+#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 <stdint.h>
+
+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 <stdint.h>
+
+#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;