diff options
author | Marvin Borner | 2021-07-10 18:36:50 +0200 |
---|---|---|
committer | Marvin Borner | 2021-07-10 18:36:50 +0200 |
commit | 4f1ae4fa4250369919a975f5568425f6791b2489 (patch) | |
tree | aec903e642561edbf6a6cccf513abccff882426f | |
parent | ad56eb28f0614db4b7656ade390f1c79b446cbc9 (diff) |
Fixed interrupts and added keyboard handler
-rw-r--r-- | src/loader/dev.c | 1 | ||||
-rw-r--r-- | src/loader/ent.asm | 4 | ||||
-rw-r--r-- | src/loader/gdt.c | 96 | ||||
-rw-r--r-- | src/loader/impl/mb1.c | 37 | ||||
-rw-r--r-- | src/loader/impl/mb2.c | 17 | ||||
-rw-r--r-- | src/loader/inc/dev.h | 1 | ||||
-rw-r--r-- | src/loader/inc/impl.h | 2 | ||||
-rw-r--r-- | src/loader/inc/int.h | 2 | ||||
-rw-r--r-- | src/loader/inc/log.h | 3 | ||||
-rw-r--r-- | src/loader/int.asm | 4 | ||||
-rw-r--r-- | src/loader/int.c | 12 | ||||
-rw-r--r-- | src/loader/log.c | 7 | ||||
-rw-r--r-- | src/loader/main.c | 1 | ||||
-rw-r--r-- | src/loader/sel.c | 46 |
14 files changed, 144 insertions, 89 deletions
diff --git a/src/loader/dev.c b/src/loader/dev.c index 3cdef10..2a57b02 100644 --- a/src/loader/dev.c +++ b/src/loader/dev.c @@ -14,6 +14,7 @@ static const char *dev_resolve_type(enum dev_type type) return "Disk"; case DEV_FB: return "Framebuffer"; + case DEV_NONE: default: return "Unknown"; } diff --git a/src/loader/ent.asm b/src/loader/ent.asm index 47cf49b..c518aad 100644 --- a/src/loader/ent.asm +++ b/src/loader/ent.asm @@ -18,7 +18,8 @@ _start: sub ecx, bss_begin rep stosb - lgdt [gdt] + lgdt [gdt] ; Load GDT + jmp 0x18:.reload_cs .reload_cs: @@ -29,5 +30,4 @@ _start: mov gs, ax mov ss, ax - cli jmp start diff --git a/src/loader/gdt.c b/src/loader/gdt.c index 853b793..ea91c33 100644 --- a/src/loader/gdt.c +++ b/src/loader/gdt.c @@ -2,48 +2,54 @@ #include <gdt.h> -static struct gdt_desc gdt_descs[] = { { 0 }, - - { .limit = 0xffff, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x9a, - .granularity = 0x00, - .base_hi = 0x00 }, - - { .limit = 0xffff, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x92, - .granularity = 0x00, - .base_hi = 0x00 }, - - { .limit = 0xffff, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x9a, - .granularity = 0xcf, - .base_hi = 0x00 }, - - { .limit = 0xffff, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x92, - .granularity = 0xcf, - .base_hi = 0x00 }, - - { .limit = 0x0000, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x9a, - .granularity = 0x20, - .base_hi = 0x00 }, - - { .limit = 0x0000, - .base_low = 0x0000, - .base_mid = 0x00, - .access = 0x92, - .granularity = 0x00, - .base_hi = 0x00 } }; - -REAL struct gdtr gdt = { sizeof(gdt_descs) - 1, (u32)gdt_descs, 0 }; +static struct gdt_desc gdt_descs[] = { + { 0 }, + + { .limit = 0xffff, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x9a, + .granularity = 0x00, + .base_hi = 0x00 }, + + { .limit = 0xffff, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x92, + .granularity = 0x00, + .base_hi = 0x00 }, + + { .limit = 0xffff, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x9a, + .granularity = 0xcf, + .base_hi = 0x00 }, + + { .limit = 0xffff, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x92, + .granularity = 0xcf, + .base_hi = 0x00 }, + + { .limit = 0x0000, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x9a, + .granularity = 0x20, + .base_hi = 0x00 }, + + { .limit = 0x0000, + .base_low = 0x0000, + .base_mid = 0x00, + .access = 0x92, + .granularity = 0x00, + .base_hi = 0x00 }, +}; + +REAL struct gdtr gdt = { + sizeof(gdt_descs) - 1, + (u32)gdt_descs, + 0, +}; diff --git a/src/loader/impl/mb1.c b/src/loader/impl/mb1.c index e713dd7..c02aa50 100644 --- a/src/loader/impl/mb1.c +++ b/src/loader/impl/mb1.c @@ -10,15 +10,20 @@ // The address where data gets stored #define MB1_LOAD_ADDRESS 0x10000 +#define MB1_FLAG_PAGE_ALIGN (1 << 0) // Align modules with page boundaries (4K) +#define MB1_FLAG_MEMORY_INFO (1 << 1) // Load/store all mem_* fields and mmap_* structs +#define MB1_FLAG_VIDEO_MODE (1 << 2) // Load/store video mode table +#define MB1_FLAG_MANUAL_ADDRESSES (1 << 16) // Use specified load addresses + struct mb1_entry { u32 magic; u32 flags; u32 checksum; // Everything after that is optional - u32 header_addr; - u32 load_addr; - u32 load_end_addr; - u32 bss_end_addr; - u32 entry_addr; + u32 header_addr; // Unsupported + u32 load_addr; // Unsupported + u32 load_end_addr; // Unsupported + u32 bss_end_addr; // Unsupported + u32 entry_addr; // Unsupported u32 mode_type; u32 width; u32 height; @@ -40,8 +45,9 @@ static u32 mb1_store(void *data, u32 size) return MB1_LOAD_ADDRESS + (offset - size); } -static void mb1_store_mmap(struct mb1_info *info) +static void mb1_store_memory_info(struct mb1_info *info) { + // TODO: Store mem_lower and mem_upper struct mem_map *mem_map = mem_map_get(); info->flags |= MB1_INFO_MEM_MAP; info->mmap_length = mem_map->count * sizeof(struct mb1_mmap_entry); @@ -59,8 +65,6 @@ static void mb1_store_mmap(struct mb1_info *info) // Load the mb1 structs into memory static void mb1_load(struct mb1_entry *entry) { - (void)entry; - struct mb1_info info_struct = { 0 }; struct mb1_info *info = (void *)mb1_store(&info_struct, sizeof(info_struct)); @@ -73,9 +77,9 @@ static void mb1_load(struct mb1_entry *entry) char loader_name[] = "SegelBoot"; info->boot_loader_name = mb1_store(loader_name, sizeof(loader_name)); - // Set memory map - /* if (entry->flags & 2) TODO */ - mb1_store_mmap(info); + // Store memory info + if (entry->flags & MB1_FLAG_MEMORY_INFO) + mb1_store_memory_info(info); } // Jump to kernel with correct info pointer in eax @@ -120,18 +124,21 @@ u8 mb1_detect(struct cfg_entry *cfg) return 0; cfg->impl.type = IMPL_MB1; - cfg->impl.start = entry; + cfg->impl.offset = (u32)entry - (u32)header; return 1; } -#include <pic.h> - // Execute mb1 type kernel void mb1_exec(struct cfg_entry *cfg) { + struct mb1_entry mb1_entry = { 0 }; + s32 ret = cfg->dev->p.disk.fs.read(cfg->path, &mb1_entry, cfg->impl.offset, + sizeof(mb1_entry), cfg->dev); + assert(ret == sizeof(mb1_entry)); + mb1_load(&mb1_entry); + u32 entry = elf_load(cfg->dev, cfg->path); - mb1_load(cfg->impl.start); // This is a kind of hacky parameter stack pushing thing, just disable warning :) #pragma GCC diagnostic ignored "-Wpedantic" diff --git a/src/loader/impl/mb2.c b/src/loader/impl/mb2.c index f46310b..09f69ea 100644 --- a/src/loader/impl/mb2.c +++ b/src/loader/impl/mb2.c @@ -9,7 +9,7 @@ // The address where data gets stored #define MB2_LOAD_ADDRESS 0x10000 -struct multiboot_entry { +struct mb2_entry { u32 magic; u32 flags; u32 header_length; @@ -18,7 +18,7 @@ struct multiboot_entry { }; // The (really simple) multiboot checksum algorithm -/* static u32 mb2_checksum(struct multiboot_entry *entry) */ +/* static u32 mb2_checksum(struct mb2_entry *entry) */ /* { */ /* return -(entry->magic + entry->flags); */ /* } */ @@ -33,7 +33,7 @@ static u32 mb2_store(void *data, u32 size) } // Load the mb2 structs into memory -static void mb2_load(struct multiboot_entry *entry) +static void mb2_load(struct mb2_entry *entry) { (void)mb2_store; (void)entry; @@ -64,7 +64,7 @@ u8 mb2_detect(struct cfg_entry *cfg) return 0; // Find start of multiboot entry by searching for magic - struct multiboot_entry *entry = 0; + struct mb2_entry *entry = 0; for (u32 i = 0; i < sizeof(header); i++) { u32 *p = (u32 *)&header[i]; if (*p == MB2_MAGIC) { @@ -82,7 +82,7 @@ u8 mb2_detect(struct cfg_entry *cfg) /* return 0; */ cfg->impl.type = IMPL_MB2; - cfg->impl.start = entry; + cfg->impl.offset = (u32)entry - (u32)header; return 1; } @@ -90,8 +90,13 @@ u8 mb2_detect(struct cfg_entry *cfg) // Execute mb2 type kernel void mb2_exec(struct cfg_entry *cfg) { + struct mb2_entry mb2_entry = { 0 }; + s32 ret = cfg->dev->p.disk.fs.read(cfg->path, &mb2_entry, cfg->impl.offset, + sizeof(mb2_entry), cfg->dev); + assert(ret == sizeof(mb2_entry)); + mb2_load(&mb2_entry); + u32 entry = elf_load(cfg->dev, cfg->path); - mb2_load(cfg->impl.start); // This is a kind of hacky parameter stack pushing thing, just disable warning :) #pragma GCC diagnostic ignored "-Wpedantic" diff --git a/src/loader/inc/dev.h b/src/loader/inc/dev.h index 7120a83..cbefe99 100644 --- a/src/loader/inc/dev.h +++ b/src/loader/inc/dev.h @@ -7,6 +7,7 @@ #include <dsk.h> enum dev_type { + DEV_NONE, DEV_DISK, DEV_FB, }; diff --git a/src/loader/inc/impl.h b/src/loader/inc/impl.h index c7b1261..58ae706 100644 --- a/src/loader/inc/impl.h +++ b/src/loader/inc/impl.h @@ -13,7 +13,7 @@ enum impl_type { struct impl { enum impl_type type; - void *start; // Of header/entry + u32 offset; // Of header/entry void (*load)(struct dev *, const char *); }; diff --git a/src/loader/inc/int.h b/src/loader/inc/int.h index 8336cd8..ccd9ea8 100644 --- a/src/loader/inc/int.h +++ b/src/loader/inc/int.h @@ -43,8 +43,6 @@ struct idt_ptr { void *base; } PACKED; -extern struct idt_ptr idt; - void idt_install(void); void int_event_handler_add(u32 int_no, void (*handler)(void)); diff --git a/src/loader/inc/log.h b/src/loader/inc/log.h index c40ce50..cb1acd8 100644 --- a/src/loader/inc/log.h +++ b/src/loader/inc/log.h @@ -3,9 +3,12 @@ #ifndef LOG_H #define LOG_H +#include <def.h> + void serial_install(void); void serial_print(const char *data); +void vga_put_at(char ch, u8 x, u8 y, u8 color); void vga_clear(void); void log(const char *format, ...); diff --git a/src/loader/int.asm b/src/loader/int.asm index f6e66ae..4805448 100644 --- a/src/loader/int.asm +++ b/src/loader/int.asm @@ -1,7 +1,5 @@ ; MIT License, Copyright (c) 2021 Marvin Borner -bits 32 - %macro INT_REGISTER 1 dd int%1 %endmacro @@ -29,7 +27,7 @@ int_common: push fs push gs - mov ax, 0x10 + mov ax, 0x20 mov ds, ax mov es, ax mov fs, ax diff --git a/src/loader/int.c b/src/loader/int.c index 8fc0ae3..d4e4841 100644 --- a/src/loader/int.c +++ b/src/loader/int.c @@ -11,21 +11,21 @@ extern u32 int_table[]; static struct idt_entry idt_entries[256] = { 0 }; -REAL struct idt_ptr idt = { .size = sizeof(idt_entries) - 1, .base = &idt_entries }; +REAL static struct idt_ptr idt = { .size = sizeof(idt_entries) - 1, .base = idt_entries }; void idt_install(void) { for (u8 i = 0; i < 3; i++) - idt_entries[i] = IDT_ENTRY(int_table[i], 0x08, INT_GATE); + idt_entries[i] = IDT_ENTRY(int_table[i], 0x18, INT_GATE); - idt_entries[3] = IDT_ENTRY(int_table[3], 0x08, INT_TRAP); - idt_entries[4] = IDT_ENTRY(int_table[4], 0x08, INT_TRAP); + idt_entries[3] = IDT_ENTRY(int_table[3], 0x18, INT_TRAP); + idt_entries[4] = IDT_ENTRY(int_table[4], 0x18, INT_TRAP); for (u8 i = 5; i < 48; i++) - idt_entries[i] = IDT_ENTRY(int_table[i], 0x08, INT_GATE); + idt_entries[i] = IDT_ENTRY(int_table[i], 0x18, INT_GATE); // Load table - __asm__ volatile("lidt %0" : : "m"(idt)); + __asm__ volatile("lidt %0" : : "m"(idt) : "memory"); } /** diff --git a/src/loader/log.c b/src/loader/log.c index ff4feff..3a4167f 100644 --- a/src/loader/log.c +++ b/src/loader/log.c @@ -120,6 +120,13 @@ void vga_clear(void) out[i] = 0; } +void vga_put_at(char ch, u8 x, u8 y, u8 color) +{ + u8 *out = (u8 *)(VGA_ADDRESS + 2 * (x + y * VGA_WIDTH)); + *out++ = ch; + *out++ = color; +} + static void vga_put(char ch) { static u8 x = 0; diff --git a/src/loader/main.c b/src/loader/main.c index 54f35be..97fc8ef 100644 --- a/src/loader/main.c +++ b/src/loader/main.c @@ -40,6 +40,7 @@ int start(u8 disk) sel_draw(); // Sleep and wait for interrupts + __asm__ volatile("sti"); while (1) __asm__ volatile("hlt"); diff --git a/src/loader/sel.c b/src/loader/sel.c index acdc783..9052712 100644 --- a/src/loader/sel.c +++ b/src/loader/sel.c @@ -2,7 +2,9 @@ // Selection interface #include <cfg.h> +#include <cpu.h> #include <def.h> +#include <int.h> #include <log.h> #include <pnc.h> #include <sel.h> @@ -22,29 +24,55 @@ static u8 sel_entry_add(struct cfg_entry *entry) return 0; } -// TODO: Keyboard listener +static u8 sel_entry_exists(u8 entry) +{ + return !!sel_entries[entry].cfg; +} + static void sel_entry_select(u8 entry) { - cfg_exec(sel_entries[entry].cfg); + if (sel_entry_exists(entry)) + cfg_exec(sel_entries[entry].cfg); + else + log("Invalid selection\n"); } static void sel_entries_draw(void) { - for (u8 i = 0; i < COUNT(sel_entries); i++) { - if (!sel_entries[i].cfg) - break; - + for (u8 i = 0; sel_entry_exists(i); i++) vga_log("> '%s' (%s)\n", sel_entries[i].cfg->name, sel_entries[i].cfg->path); - } +} + +// Using PS2 magic +static void sel_keyboard_handler(void) +{ + static u8 row = 0; + + while (!(inb(0x64) & 1)) // Wait for data (bit 0 gets set) + ; + u8 data = inb(0x60); + + // Reset previous selection + vga_put_at('>', 0, row + 2, 0x07); + + if (data == 0x24 && sel_entry_exists(row + 1)) // j/down key + row++; + else if (data == 0x25 && row > 0) // k/up key + row--; + else if (data == (0x1c | 0x80)) // enter key release (| 0x80) + sel_entry_select(row); + + // Draw selection + vga_put_at('#', 0, row + 2, 0x03); } void sel_draw(void) { vga_clear(); + vga_log("SegelBoot by Marvin Borner\n\n"); cfg_foreach(&sel_entry_add); sel_entries_draw(); - // Just for testing - sel_entry_select(0); + int_event_handler_add(1, &sel_keyboard_handler); } |