Add getgdt, struggle a bit, give up, cry...

This commit is contained in:
Robbe Van Herck 2020-01-10 02:23:59 +01:00
parent 2a82f01493
commit a0883e95d0
No known key found for this signature in database
GPG key ID: A66F76F7B81BD784
6 changed files with 122 additions and 25 deletions

View file

@ -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:

View file

@ -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.

View file

@ -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;
}

View file

@ -3,6 +3,22 @@
#include <stdint.h>
#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

View file

@ -6,6 +6,7 @@
#include <stddef.h>
#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;

View file

@ -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