diff --git a/bootloader/main.asm b/bootloader/main.asm index aea9181..e4e633a 100644 --- a/bootloader/main.asm +++ b/bootloader/main.asm @@ -210,15 +210,18 @@ or eax, 1 mov cr0, eax ; jump to 32 bit code -jmp 0x08:.clear_pipe +jmp 0x08:.clear_cs [BITS 32] -.clear_pipe: +.clear_cs: -; set Data Segment and Stack segment -mov ax, 10h +; set Data Segment, Stack Segment and other segments +mov ax, 0x10 mov ds, ax mov ss, ax +mov es, ax +mov fs, ax +mov gs, ax ; set up stack mov esp, 0x090000 @@ -286,6 +289,8 @@ repnz movsd jmp [.entrypoint] .end: +cli +hlt jmp .end .invalid_elf: @@ -306,22 +311,22 @@ times 66 - (.file_end - .data) db 0 .data: .gdt: -dd 0 -dd 0 +dd 0x00000000 +dd 0x00000000 -dw 0FFFFh -dw 0 -db 0 -db 10011010b -db 11001111b -db 0 +dw 0xffff +dw 0x0000 +db 0x00 +db 0b10011010 +db 0b11001111 +db 0x00 -dw 0FFFFh -dw 0 -db 0 -db 10010010b -db 11001111b -db 0 +dw 0xffff +dw 0x0000 +db 0x00 +db 0b10010010 +db 0b11001111 +db 0x00 .gdt_end: .gdt_desc: diff --git a/docs/bootloader.md b/docs/bootloader.md index 0b55dc0..26c7344 100644 --- a/docs/bootloader.md +++ b/docs/bootloader.md @@ -10,10 +10,17 @@ | 0x07c00 | 0x07dff | Bootloader | | 0x07e00 | 0x07fff | _free space_ | | 0x08000 | 0x0ffff | **ELF file** (64 sectors) | -| 0x10000 | 0x7ffff | **kernel space** | +| 0x00000 | 0x7ffff | _free space_ | | 0x80000 | 0x9ffff | EDBA, partially usable | | 0xa0000 | 0xfffff | unusable | +## Higher Memory + +| start | end | use | +|----------|----------|---------------------------| +| 0x00000 | 0xfffff | Low memory | +| 0x100000 | 0x200000 | **Kernel space** | + ## Bootsector layout (all addresses are offsets from 0x7C00) @@ -38,6 +45,14 @@ | ??? | 0x00ffffff | SFS index area | | 0x01000000 | end | Unused (Disk size is set to 16MiB) | +## GDT + +| Entry | Base | Limit | Flags | Access | Purpose | +|-------|-------------|---------|--------|------------|--------------| +| 0x0 | 0x00000000 | 0x00000 | 0b0000 | 0b00000000 | Null Segment | +| 0x8 | 0x00000000 | 0xfffff | 0b1100 | 0b10011010 | Code Segment | +| 0x10 | 0x00000000 | 0xfffff | 0b1100 | 0b10010010 | Data Segment | + ## Known issues ### Stack setup @@ -47,3 +62,7 @@ As I don't quite get how segments work in real mode, there are most likely error ### Kernel is not a file I reserve 32KiB of SFS reserved area for the ELF file of the kernel. This is currently for "historic reasons" (a.k.a. I'm too lazy to load the filesystem in the bootloader). The kernel then handles the filesystem. + +### Second ELF program header does not get loaded + +This will most likely fix the issue of missing global strings. diff --git a/kernel/drivers/keyboard/keyboard.c b/kernel/drivers/keyboard/keyboard.c index 3fc8b27..4785aff 100644 --- a/kernel/drivers/keyboard/keyboard.c +++ b/kernel/drivers/keyboard/keyboard.c @@ -65,7 +65,9 @@ int getchar_nonblocking() { char getchar() { int curr = KEY_QUEUE_EMPTY; - while ((curr = getchar_nonblocking()) == KEY_QUEUE_EMPTY) {} + while ((curr = getchar_nonblocking()) == KEY_QUEUE_EMPTY) { + asm("hlt"); // And don't catch fire + } return (char) curr; } diff --git a/kernel/inline_asm.c b/kernel/inline_asm.c index db3de1b..2757685 100644 --- a/kernel/inline_asm.c +++ b/kernel/inline_asm.c @@ -3,6 +3,22 @@ #include +#include "memory.c" + +typedef struct { + uint16_t limit; + uint32_t base; +}__attribute__((packed)) gdt_desc; + +typedef struct { + uint16_t limit_lower; + uint16_t base_lower; + uint8_t base_middle; + uint8_t access_byte; + uint8_t flags_limit_higher; + uint8_t base_higher; +}__attribute__((packed)) gdt_entry; + static inline void outb(uint16_t port, uint8_t val) { asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); } @@ -41,4 +57,8 @@ static inline int cpuid_string(int code, uint32_t where[4]) { return (int)where[0]; } +static inline void sgdt(gdt_desc* ret) { + asm volatile ("sgdt %0" : : "m"(*ret) : "memory"); +} + #endif //INLINE ASM_C \ No newline at end of file diff --git a/kernel/shell.c b/kernel/shell.c index a404a8c..eaa76b5 100644 --- a/kernel/shell.c +++ b/kernel/shell.c @@ -6,6 +6,7 @@ #include #include "terminal.c" +#include "inline_asm.c" #include "drivers/keyboard/keyboard.c" char buffer[SHELL_CMD_BUFFER_SIZE]; @@ -27,6 +28,61 @@ int cls(char* unused) { return 0; } +int get_gdt(char* unused) { + gdt_desc desc = {2,2}; + sgdt(&desc); + terminal_writestring("limit = "); + terminal_writeint(desc.limit, 10); + terminal_writestring("\nbase = 0x"); + terminal_writeint(desc.base, 16); + terminal_putchar('\n'); + + gdt_entry* entries = (gdt_entry*) desc.base; + int num_entries = (desc.limit+1) / 8; + for (int entry_num = 0; entry_num < num_entries; entry_num++) { + gdt_entry entry = entries[entry_num]; + uint32_t base = entry.base_lower | entry.base_middle << 16 | entry.base_higher << 24; + uint32_t limit = entry.limit_lower | (entry.flags_limit_higher & 0x0f) << 16; + uint8_t flags = (entry.flags_limit_higher >> 4); + + //terminal_writestring("\nEntry "); + //terminal_writeint(entry_num, 10); + terminal_writestring("base = 0x"); + terminal_writeint(base, 16); + terminal_writestring("\nlimit = 0x"); + terminal_writeint(limit, 16); + terminal_writestring("\nflags = 0b"); + terminal_writeint((entry.flags_limit_higher >> 4), 2); + + if ((flags & 0b1000) == 0) { + terminal_writestring(" (byte granularity"); + } else { + terminal_writestring(" (page granularity"); + } + + if ((flags & 0b0100) == 0) { + terminal_writestring(", 16 bit)"); + } else { + terminal_writestring(", 32 bit)"); + } + + terminal_writestring("\naccess = 0b"); + terminal_writeint(entry.access_byte, 2); + terminal_writestring(" (ring "); + terminal_writeint((entry.access_byte & 0b01100000) >> 5, 10); + terminal_writestring(", S = "); + terminal_writeint((entry.access_byte & 0b00010000) >> 4, 2); + terminal_writestring(", EX = "); + terminal_writeint((entry.access_byte & 0b00001000) >> 3, 2); + terminal_writestring(", DC = "); + terminal_writeint((entry.access_byte & 0b00000100) >> 2, 2); + terminal_writestring(", RW = "); + terminal_writeint((entry.access_byte & 0b00000010) >> 1, 2); + terminal_writestring(")\n"); + } + return 0; +} + int ree(char* unused) { terminal_initialize(); terminal_putchar('R'); @@ -82,7 +138,6 @@ int run_command(char* buffer) { void shell_step() { char curr_char = getchar(); - if (curr_char == '\n') { terminal_putchar(curr_char); buffer[buffer_idx] = 0; diff --git a/kernel/wrapper.asm b/kernel/wrapper.asm index 4659f69..d329686 100644 --- a/kernel/wrapper.asm +++ b/kernel/wrapper.asm @@ -54,10 +54,6 @@ _start: ; stack (as it grows downwards on x86 systems). This is necessarily done ; in assembly as languages such as C cannot function without a stack. mov esp, stack_top - - mov al, 0xff - out 0xa1, al - out 0x21, al ; This is a good place to initialize crucial processor state before the ; high-level kernel is entered. It's best to minimize the early