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
|
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:
|
||||||
|
|
|
@ -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.
|
||||||
|
|
|
@ -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;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -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
|
|
@ -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;
|
||||||
|
|
|
@ -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
|
||||||
|
|
Loading…
Reference in a new issue