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 mov cr0, eax
; jump to 32 bit code ; jump to 32 bit code
jmp 0x08:.clear_pipe jmp 0x08:.clear_cs
[BITS 32] [BITS 32]
.clear_pipe: .clear_cs:
; set Data Segment and Stack segment ; set Data Segment, Stack Segment and other segments
mov ax, 10h mov ax, 0x10
mov ds, ax mov ds, ax
mov ss, ax mov ss, ax
mov es, ax
mov fs, ax
mov gs, ax
; set up stack ; set up stack
mov esp, 0x090000 mov esp, 0x090000
@ -286,6 +289,8 @@ repnz movsd
jmp [.entrypoint] jmp [.entrypoint]
.end: .end:
cli
hlt
jmp .end jmp .end
.invalid_elf: .invalid_elf:
@ -306,22 +311,22 @@ times 66 - (.file_end - .data) db 0
.data: .data:
.gdt: .gdt:
dd 0 dd 0x00000000
dd 0 dd 0x00000000
dw 0FFFFh dw 0xffff
dw 0 dw 0x0000
db 0 db 0x00
db 10011010b db 0b10011010
db 11001111b db 0b11001111
db 0 db 0x00
dw 0FFFFh dw 0xffff
dw 0 dw 0x0000
db 0 db 0x00
db 10010010b db 0b10010010
db 11001111b db 0b11001111
db 0 db 0x00
.gdt_end: .gdt_end:
.gdt_desc: .gdt_desc:

View file

@ -10,10 +10,17 @@
| 0x07c00 | 0x07dff | Bootloader | | 0x07c00 | 0x07dff | Bootloader |
| 0x07e00 | 0x07fff | _free space_ | | 0x07e00 | 0x07fff | _free space_ |
| 0x08000 | 0x0ffff | **ELF file** (64 sectors) | | 0x08000 | 0x0ffff | **ELF file** (64 sectors) |
| 0x10000 | 0x7ffff | **kernel space** | | 0x00000 | 0x7ffff | _free space_ |
| 0x80000 | 0x9ffff | EDBA, partially usable | | 0x80000 | 0x9ffff | EDBA, partially usable |
| 0xa0000 | 0xfffff | unusable | | 0xa0000 | 0xfffff | unusable |
## Higher Memory
| start | end | use |
|----------|----------|---------------------------|
| 0x00000 | 0xfffff | Low memory |
| 0x100000 | 0x200000 | **Kernel space** |
## Bootsector layout ## Bootsector layout
(all addresses are offsets from 0x7C00) (all addresses are offsets from 0x7C00)
@ -38,6 +45,14 @@
| ??? | 0x00ffffff | SFS index area | | ??? | 0x00ffffff | SFS index area |
| 0x01000000 | end | Unused (Disk size is set to 16MiB) | | 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 ## Known issues
### Stack setup ### 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 ### 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. 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() { char getchar() {
int curr = KEY_QUEUE_EMPTY; 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; return (char) curr;
} }

View file

@ -3,6 +3,22 @@
#include <stdint.h> #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) { static inline void outb(uint16_t port, uint8_t val) {
asm volatile ( "outb %0, %1" : : "a"(val), "Nd"(port) ); 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]; return (int)where[0];
} }
static inline void sgdt(gdt_desc* ret) {
asm volatile ("sgdt %0" : : "m"(*ret) : "memory");
}
#endif //INLINE ASM_C #endif //INLINE ASM_C

View file

@ -6,6 +6,7 @@
#include <stddef.h> #include <stddef.h>
#include "terminal.c" #include "terminal.c"
#include "inline_asm.c"
#include "drivers/keyboard/keyboard.c" #include "drivers/keyboard/keyboard.c"
char buffer[SHELL_CMD_BUFFER_SIZE]; char buffer[SHELL_CMD_BUFFER_SIZE];
@ -27,6 +28,61 @@ int cls(char* unused) {
return 0; 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) { int ree(char* unused) {
terminal_initialize(); terminal_initialize();
terminal_putchar('R'); terminal_putchar('R');
@ -82,7 +138,6 @@ int run_command(char* buffer) {
void shell_step() { void shell_step() {
char curr_char = getchar(); char curr_char = getchar();
if (curr_char == '\n') { if (curr_char == '\n') {
terminal_putchar(curr_char); terminal_putchar(curr_char);
buffer[buffer_idx] = 0; buffer[buffer_idx] = 0;

View file

@ -54,10 +54,6 @@ _start:
; stack (as it grows downwards on x86 systems). This is necessarily done ; stack (as it grows downwards on x86 systems). This is necessarily done
; in assembly as languages such as C cannot function without a stack. ; in assembly as languages such as C cannot function without a stack.
mov esp, stack_top 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 ; This is a good place to initialize crucial processor state before the
; high-level kernel is entered. It's best to minimize the early ; high-level kernel is entered. It's best to minimize the early