Finish up GDT, get linear address space working
The GDT is now finally set and produces a linear address space. Execution continues at 'stage2_true_entry'.
This commit is contained in:
parent
fa818435a2
commit
44ca45e8f1
|
@ -4,12 +4,12 @@
|
||||||
; If something has to be included, include it at the bottom!
|
; If something has to be included, include it at the bottom!
|
||||||
|
|
||||||
STACK_SIZE equ 32768
|
STACK_SIZE equ 32768
|
||||||
UPPER_STACK_POINTER equ 0x100000
|
UPPER_STACK_POINTER equ 0x20000
|
||||||
LOWER_STACK_POINTER equ (UPPER_STACK_POINTER - STACK_SIZE)
|
LOWER_STACK_POINTER equ (UPPER_STACK_POINTER - STACK_SIZE)
|
||||||
|
|
||||||
bits 16
|
bits 16
|
||||||
org 0x0000
|
org 0xa000
|
||||||
entry:
|
stage_2_setup_entry:
|
||||||
mov ebx, LOWER_STACK_POINTER
|
mov ebx, LOWER_STACK_POINTER
|
||||||
mov ss, ebx
|
mov ss, ebx
|
||||||
mov esp, STACK_SIZE
|
mov esp, STACK_SIZE
|
||||||
|
@ -17,6 +17,10 @@ entry:
|
||||||
push dx
|
push dx
|
||||||
cli
|
cli
|
||||||
|
|
||||||
|
mov ah, 0x00
|
||||||
|
mov al, 0x03 ;0x13
|
||||||
|
int 0x10
|
||||||
|
|
||||||
.check_a20:
|
.check_a20:
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
|
@ -30,46 +34,37 @@ entry:
|
||||||
|
|
||||||
.a20_is_enabled:
|
.a20_is_enabled:
|
||||||
|
|
||||||
; Reset Display
|
|
||||||
mov ah, 0x00
|
|
||||||
mov al, 0x03
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
mov ah, 0x0b
|
|
||||||
mov bh, 0x00
|
|
||||||
mov bl, 0
|
|
||||||
int 0x10
|
|
||||||
|
|
||||||
mov edi, ebp
|
mov edi, ebp
|
||||||
mov esi, esp
|
mov esi, esp
|
||||||
push ebp
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
push .flat_gdt_loaded
|
; push dword after_gdt_loaded
|
||||||
call load_flat_gdt
|
call load_flat_gdt
|
||||||
mov esp, ebp
|
mov esp, ebp
|
||||||
pop ebp
|
pop ebp
|
||||||
.flat_gdt_loaded:
|
|
||||||
mov ebp, edi
|
|
||||||
mov esp, esi
|
|
||||||
|
|
||||||
; push ebp
|
|
||||||
; mov ebp, esp
|
|
||||||
; call setup_drivers
|
|
||||||
; mov esp, ebp
|
|
||||||
; pop ebp
|
|
||||||
|
|
||||||
cli
|
cli
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
some_text:
|
some_text:
|
||||||
db "This is some text.", 0x00
|
db "This is some text.", 0x00
|
||||||
|
|
||||||
; Utilities
|
; Utilities
|
||||||
%include "utility/math.asm"
|
|
||||||
%include "utility/memory.asm"
|
|
||||||
|
|
||||||
; Memory Management
|
; Memory Management
|
||||||
%include "memory/a20.asm"
|
%include "memory/a20.asm"
|
||||||
%include "memory/gdt.asm"
|
%include "memory/gdt.asm"
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
bits 32
|
||||||
|
stage2_true_entry:
|
||||||
|
mov [dword 0xb8000], byte 'X'
|
||||||
|
mov [dword 0xb8000 + 1], byte 0x31
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
%include "utility/math.asm"
|
||||||
|
%include "utility/memory.asm"
|
||||||
|
|
||||||
; Driver Manager
|
; Driver Manager
|
||||||
; %include "drivers/manager.asm"
|
; %include "drivers/manager.asm"
|
||||||
|
|
|
@ -0,0 +1,414 @@
|
||||||
|
|
||||||
|
GDT_MEMORY_AREA equ 0x7e00
|
||||||
|
GDT_ENTRY_COUNT equ 3
|
||||||
|
|
||||||
|
; Arguments (note: all arguments are 4-byte padded):
|
||||||
|
; [Furthest from EBP]
|
||||||
|
;
|
||||||
|
; 4. uint32 privilege_level
|
||||||
|
; - Only 0 to 3; 0 being kernel and 3 being userland.
|
||||||
|
; Everything above 3 is an error.
|
||||||
|
;
|
||||||
|
; 3 uint32 num_pages
|
||||||
|
; - Only 20 bits are usable. Everything above will
|
||||||
|
; be cut off to be written to the segment descriptor.
|
||||||
|
;
|
||||||
|
; 2. ptr32 base_address
|
||||||
|
;
|
||||||
|
; 1. uint32 segment_index
|
||||||
|
; Note:
|
||||||
|
; - Zero is NOT usable and will throw an error.
|
||||||
|
; the highest theoretical value for this is 8191,
|
||||||
|
; but generally, one should stick to GDT_ENTRY_COUNT.
|
||||||
|
;
|
||||||
|
; [Nearest to EBP]
|
||||||
|
make_regular_data_segment_in_gdt:
|
||||||
|
.prolog:
|
||||||
|
push esi
|
||||||
|
add esp, 64
|
||||||
|
mov esi, esp
|
||||||
|
|
||||||
|
mov [esi + (64 - 4)], eax
|
||||||
|
mov [esi + (64 - 8)], ebx
|
||||||
|
mov [esi + (64 - 12)], ecx
|
||||||
|
mov [esi + (64 - 16)], edx
|
||||||
|
mov [esi + (64 - 20)], edi
|
||||||
|
|
||||||
|
.get_arguments:
|
||||||
|
mov eax, [ebp - 4] ; segment_index
|
||||||
|
mov ebx, [ebp - 8] ; base_address
|
||||||
|
mov ecx, [ebp - 12] ; num_pages
|
||||||
|
mov edx, [ebp - 16] ; privilege_level
|
||||||
|
|
||||||
|
mov [esi + 16], eax ; segment_index
|
||||||
|
mov [esi + 20], ebx ; base_address
|
||||||
|
mov [esi + 24], ecx ; num_pages
|
||||||
|
mov [esi + 28], edx ; privilege_level
|
||||||
|
|
||||||
|
.validate_arguments:
|
||||||
|
cmp eax, 8191
|
||||||
|
ja .segment_index_too_tall
|
||||||
|
cmp eax, 0
|
||||||
|
je .segment_index_is_zero
|
||||||
|
|
||||||
|
cmp edx, 3
|
||||||
|
ja .privilege_level_too_large
|
||||||
|
|
||||||
|
.calculate_work_address:
|
||||||
|
shl eax, 3 ; Entry offset from table start
|
||||||
|
add eax, GDT_MEMORY_AREA ; Entry address
|
||||||
|
mov [esi + 12], eax
|
||||||
|
|
||||||
|
.write_segment_limit:
|
||||||
|
mov [eax], cx
|
||||||
|
shr ecx, 16
|
||||||
|
and ecx, 0x0f
|
||||||
|
mov [eax + 6], cl
|
||||||
|
|
||||||
|
.write_base_address:
|
||||||
|
mov [eax + 2], bx
|
||||||
|
shr bx, 16
|
||||||
|
mov [eax + 4], bl
|
||||||
|
mov [eax + 7], bh
|
||||||
|
|
||||||
|
.set_default_flags:
|
||||||
|
or [eax + 6], byte (0b1100 << 4)
|
||||||
|
|
||||||
|
.set_data_segment_specific_access_byte:
|
||||||
|
mov al, 0b1001
|
||||||
|
; OR the privilege level into the access byte
|
||||||
|
mov dl, [ebp - 16]
|
||||||
|
shl dl, 1
|
||||||
|
and dl, 0b0110
|
||||||
|
or al, dl
|
||||||
|
shl al, 4 ; Move the 4 bits of general flags to their place
|
||||||
|
|
||||||
|
; Data-segment specific part
|
||||||
|
or al, 0b0010 ; DATA | HEAP | READ_WRITE | NOT_ACCESSED
|
||||||
|
|
||||||
|
mov ebx, [esi + 12]
|
||||||
|
mov [ebx + 5], al ; Write to the final destination
|
||||||
|
|
||||||
|
.epilog:
|
||||||
|
mov edi, [esi + (64 - 20)]
|
||||||
|
mov edx, [esi + (64 - 16)]
|
||||||
|
mov ecx, [esi + (64 - 12)]
|
||||||
|
mov ebx, [esi + (64 - 8)]
|
||||||
|
mov eax, [esi + (64 - 4)]
|
||||||
|
|
||||||
|
sub esp, 64
|
||||||
|
pop esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
.segment_index_too_tall:
|
||||||
|
.segment_index_is_zero:
|
||||||
|
.privilege_level_too_large:
|
||||||
|
; todo(logs): Write debug message.
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; Arguments (note: all arguments are 4-byte padded):
|
||||||
|
; [Furthest from EBP]
|
||||||
|
;
|
||||||
|
; 4. uint32 privilege_level
|
||||||
|
; - Only 0 to 3; 0 being kernel and 3 being userland.
|
||||||
|
; Everything above 3 is an error.
|
||||||
|
;
|
||||||
|
; 3 uint32 num_pages
|
||||||
|
; - Only 20 bits are usable. Everything above will
|
||||||
|
; be cut off to be written to the segment descriptor.
|
||||||
|
;
|
||||||
|
; 2. ptr32 base_address
|
||||||
|
;
|
||||||
|
; 1. uint32 segment_index
|
||||||
|
; Note:
|
||||||
|
; - Zero is NOT usable and will throw an error.
|
||||||
|
; the highest theoretical value for this is 8191,
|
||||||
|
; but generally, one should stick to GDT_ENTRY_COUNT.
|
||||||
|
;
|
||||||
|
; [Nearest to EBP]
|
||||||
|
; COMMENTED OUT DUE TO BEING BUGGY!
|
||||||
|
; make_stack_segment_in_gdt:
|
||||||
|
; .prolog:
|
||||||
|
; push esi
|
||||||
|
; add esp, 64
|
||||||
|
; mov esi, esp
|
||||||
|
|
||||||
|
; mov [esi + (64 - 4)], eax
|
||||||
|
; mov [esi + (64 - 8)], ebx
|
||||||
|
; mov [esi + (64 - 12)], ecx
|
||||||
|
; mov [esi + (64 - 16)], edx
|
||||||
|
; mov [esi + (64 - 20)], edi
|
||||||
|
|
||||||
|
; .get_arguments:
|
||||||
|
; mov eax, [ebp - 4] ; segment_index
|
||||||
|
; mov ebx, [ebp - 8] ; base_address
|
||||||
|
; mov ecx, [ebp - 12] ; num_pages
|
||||||
|
; mov edx, [ebp - 16] ; privilege_level
|
||||||
|
|
||||||
|
; mov [esi + 16], eax ; segment_index
|
||||||
|
; mov [esi + 20], ebx ; base_address
|
||||||
|
; mov [esi + 24], ecx ; num_pages
|
||||||
|
; mov [esi + 28], edx ; privilege_level
|
||||||
|
|
||||||
|
; .validate_arguments:
|
||||||
|
; cmp eax, 8191
|
||||||
|
; ja .segment_index_too_tall
|
||||||
|
; cmp eax, 0
|
||||||
|
; je .segment_index_is_zero
|
||||||
|
|
||||||
|
; cmp edx, 3
|
||||||
|
; ja .privilege_level_too_large
|
||||||
|
|
||||||
|
; .calculate_work_address:
|
||||||
|
; shl eax, 3 ; Entry offset from table start
|
||||||
|
; add eax, GDT_MEMORY_AREA ; Entry address
|
||||||
|
; mov [esi + 12], eax
|
||||||
|
|
||||||
|
; .write_segment_limit:
|
||||||
|
; mov [eax], cx
|
||||||
|
; shr ecx, 16
|
||||||
|
; and ecx, 0x0f
|
||||||
|
; mov [eax + 6], cl
|
||||||
|
|
||||||
|
; .write_base_address:
|
||||||
|
; mov [eax + 2], bx
|
||||||
|
; shr bx, 16
|
||||||
|
; mov [eax + 4], bl
|
||||||
|
; mov [eax + 7], bh
|
||||||
|
|
||||||
|
; .set_default_flags:
|
||||||
|
; or [eax + 6], word (0b1100 << 4)
|
||||||
|
|
||||||
|
; .set_stack_specific_access_byte:
|
||||||
|
; mov al, 0b1001
|
||||||
|
; ; OR the privilege level into the access byte
|
||||||
|
; mov dl, [ebp - 16]
|
||||||
|
; shl dl, 1
|
||||||
|
; and dl, 0b0110
|
||||||
|
; or al, dl
|
||||||
|
; shl al, 4 ; Move the 4 bits of general flags to their place
|
||||||
|
|
||||||
|
; ; Stack specific part
|
||||||
|
; or al, 0b0110 ; DATA | STACK | READ_WRITE | NOT_ACCESSED
|
||||||
|
|
||||||
|
; mov ebx, [esi + 12]
|
||||||
|
; mov [ebx + 5], al ; Write to the final destination
|
||||||
|
|
||||||
|
; .epilog:
|
||||||
|
; mov edi, [esi + (64 - 20)]
|
||||||
|
; mov edx, [esi + (64 - 16)]
|
||||||
|
; mov ecx, [esi + (64 - 12)]
|
||||||
|
; mov ebx, [esi + (64 - 8)]
|
||||||
|
; mov eax, [esi + (64 - 4)]
|
||||||
|
|
||||||
|
; sub esp, 64
|
||||||
|
; pop esi
|
||||||
|
; ret
|
||||||
|
|
||||||
|
; .segment_index_too_tall:
|
||||||
|
; .segment_index_is_zero:
|
||||||
|
; .privilege_level_too_large:
|
||||||
|
; ; todo(logs): Write debug message.
|
||||||
|
; cli
|
||||||
|
; hlt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
; Arguments (note: all arguments are 4-byte padded):
|
||||||
|
; [Furthest from EBP]
|
||||||
|
;
|
||||||
|
; 4. uint32 privilege_level
|
||||||
|
; - Only 0 to 3; 0 being kernel and 3 being userland.
|
||||||
|
; Everything above 3 is an error.
|
||||||
|
;
|
||||||
|
; 3 uint32 num_pages
|
||||||
|
; - Only 20 bits are usable. Everything above will
|
||||||
|
; be cut off to be written to the segment descriptor.
|
||||||
|
;
|
||||||
|
; 2. ptr32 base_address
|
||||||
|
;
|
||||||
|
; 1. uint32 segment_index
|
||||||
|
; Note:
|
||||||
|
; - Zero is NOT usable and will throw an error.
|
||||||
|
; the highest theoretical value for this is 8191,
|
||||||
|
; but generally, one should stick to GDT_ENTRY_COUNT.
|
||||||
|
;
|
||||||
|
; [Nearest to EBP]
|
||||||
|
make_code_segment_in_gdt:
|
||||||
|
.prolog:
|
||||||
|
push esi
|
||||||
|
add esp, 64
|
||||||
|
mov esi, esp
|
||||||
|
|
||||||
|
mov [esi + (64 - 4)], eax
|
||||||
|
mov [esi + (64 - 8)], ebx
|
||||||
|
mov [esi + (64 - 12)], ecx
|
||||||
|
mov [esi + (64 - 16)], edx
|
||||||
|
mov [esi + (64 - 20)], edi
|
||||||
|
|
||||||
|
.get_arguments:
|
||||||
|
mov eax, [ebp - 4] ; segment_index
|
||||||
|
mov ebx, [ebp - 8] ; base_address
|
||||||
|
mov ecx, [ebp - 12] ; num_pages
|
||||||
|
mov edx, [ebp - 16] ; privilege_level
|
||||||
|
|
||||||
|
mov [esi + 16], eax ; segment_index
|
||||||
|
mov [esi + 20], ebx ; base_address
|
||||||
|
mov [esi + 24], ecx ; num_pages
|
||||||
|
mov [esi + 28], edx ; privilege_level
|
||||||
|
|
||||||
|
.validate_arguments:
|
||||||
|
cmp eax, 8191
|
||||||
|
ja .segment_index_too_tall
|
||||||
|
cmp eax, 0
|
||||||
|
je .segment_index_is_zero
|
||||||
|
|
||||||
|
cmp edx, 3
|
||||||
|
ja .privilege_level_too_large
|
||||||
|
|
||||||
|
.calculate_work_address:
|
||||||
|
shl eax, 3 ; Entry offset from table start
|
||||||
|
add eax, GDT_MEMORY_AREA ; Entry address
|
||||||
|
mov [esi + 12], eax
|
||||||
|
|
||||||
|
.write_segment_limit:
|
||||||
|
mov [eax], cx
|
||||||
|
shr ecx, 16
|
||||||
|
and ecx, 0x0f
|
||||||
|
mov [eax + 6], cl
|
||||||
|
|
||||||
|
.write_base_address:
|
||||||
|
mov [eax + 2], bx
|
||||||
|
shr bx, 16
|
||||||
|
mov [eax + 4], bl
|
||||||
|
mov [eax + 7], bh
|
||||||
|
|
||||||
|
.set_default_flags:
|
||||||
|
or [eax + 6], word (0b1100 << 4)
|
||||||
|
|
||||||
|
.set_code_segment_specific_access_byte:
|
||||||
|
mov al, 0b1001
|
||||||
|
; OR the privilege level into the access byte
|
||||||
|
mov dl, [ebp - 16]
|
||||||
|
shl dl, 1
|
||||||
|
and dl, 0b0110
|
||||||
|
or al, dl
|
||||||
|
shl al, 4 ; Move the 4 bits of general flags to their place
|
||||||
|
|
||||||
|
; Code-segment specific part
|
||||||
|
or al, 0b1010 ; CODE | NON-CONFORMING | READABLE | NOT_ACCESSED
|
||||||
|
|
||||||
|
mov ebx, [esi + 12]
|
||||||
|
mov [ebx + 5], al ; Write to the final destination
|
||||||
|
|
||||||
|
.epilog:
|
||||||
|
mov edi, [esi + (64 - 20)]
|
||||||
|
mov edx, [esi + (64 - 16)]
|
||||||
|
mov ecx, [esi + (64 - 12)]
|
||||||
|
mov ebx, [esi + (64 - 8)]
|
||||||
|
mov eax, [esi + (64 - 4)]
|
||||||
|
|
||||||
|
sub esp, 64
|
||||||
|
pop esi
|
||||||
|
ret
|
||||||
|
|
||||||
|
.segment_index_too_tall:
|
||||||
|
.segment_index_is_zero:
|
||||||
|
.privilege_level_too_large:
|
||||||
|
; todo(logs): Write debug message.
|
||||||
|
cli
|
||||||
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
; [Furthest to EBP]
|
||||||
|
; 1) Return Address
|
||||||
|
; [Nearest to EBP]
|
||||||
|
load_flat_gdt:
|
||||||
|
.prolog:
|
||||||
|
push esi
|
||||||
|
add esp, 64
|
||||||
|
mov esi, esp
|
||||||
|
|
||||||
|
mov [esi + (64 - 4)], eax
|
||||||
|
mov [esi + (64 - 8)], ebx
|
||||||
|
mov [esi + (64 - 12)], ecx
|
||||||
|
mov [esi + (64 - 16)], edx
|
||||||
|
mov [esi + (64 - 20)], edi
|
||||||
|
|
||||||
|
; mov eax, [ebp - 4]
|
||||||
|
; mov [esi], eax
|
||||||
|
|
||||||
|
.set_segments:
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push dword 2 ; Segment Index
|
||||||
|
push dword 0 ; Start Offset
|
||||||
|
push dword 0xfffff ; Page Count
|
||||||
|
push dword 0 ; Required privilege level
|
||||||
|
call make_regular_data_segment_in_gdt
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
; COMMENTED OUT DUE TO BEING BUGGY
|
||||||
|
; push ebp
|
||||||
|
; mov ebp, esp
|
||||||
|
; push dword 3 ; Segment Index
|
||||||
|
; push dword LOWER_STACK_POINTER ; Start Offset
|
||||||
|
; push dword 0xfffff ; Page Count
|
||||||
|
; push dword 0 ; Required privilege level
|
||||||
|
; call make_stack_segment_in_gdt
|
||||||
|
; mov esp, ebp
|
||||||
|
; pop ebp
|
||||||
|
|
||||||
|
push ebp
|
||||||
|
mov ebp, esp
|
||||||
|
push dword 1 ; Segment Index
|
||||||
|
push dword 0x0000 ; Start Offset
|
||||||
|
push dword 0xfffff ; Page Count
|
||||||
|
push dword 0 ; Required privilege level
|
||||||
|
call make_code_segment_in_gdt
|
||||||
|
mov esp, ebp
|
||||||
|
pop ebp
|
||||||
|
|
||||||
|
mov bx, 0
|
||||||
|
mov ds, bx
|
||||||
|
lgdt [.gdtr]
|
||||||
|
|
||||||
|
mov bx, (2 << 3)
|
||||||
|
mov ds, bx
|
||||||
|
mov es, bx
|
||||||
|
mov fs, bx
|
||||||
|
mov gs, bx
|
||||||
|
; mov bx, (3 << 3)
|
||||||
|
mov ss, bx
|
||||||
|
|
||||||
|
mov ebx, cr0
|
||||||
|
or ebx, 1
|
||||||
|
mov cr0, ebx
|
||||||
|
|
||||||
|
jmp dword 0x08:.epilog
|
||||||
|
|
||||||
|
bits 32
|
||||||
|
.epilog:
|
||||||
|
mov edi, [esi + (64 - 20)]
|
||||||
|
mov edx, [esi + (64 - 16)]
|
||||||
|
mov ecx, [esi + (64 - 12)]
|
||||||
|
mov ebx, [esi + (64 - 8)]
|
||||||
|
mov eax, [esi + (64 - 4)]
|
||||||
|
|
||||||
|
add esp, 64
|
||||||
|
pop esi
|
||||||
|
jmp stage2_true_entry
|
||||||
|
; jmp after_gdt_loaded
|
||||||
|
|
||||||
|
align 16
|
||||||
|
.gdtr:
|
||||||
|
.gdtr.length:
|
||||||
|
dw 23
|
||||||
|
.gdtr.pointer:
|
||||||
|
dd GDT_MEMORY_AREA
|
||||||
|
|
||||||
|
align 1
|
Loading…
Reference in New Issue