Add getgdt, struggle a bit, give up, cry...
This commit is contained in:
parent
2a82f01493
commit
a0883e95d0
6 changed files with 122 additions and 25 deletions
|
@ -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:
|
||||
|
|
|
@ -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.
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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
|
|
@ -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;
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in a new issue