Compare commits
3 Commits
0d16e3e35a
...
65db388f00
Author | SHA1 | Date |
---|---|---|
Eric-Paul Ickhorn | 65db388f00 | |
Eric-Paul Ickhorn | 5ba30e5f8b | |
Eric-Paul Ickhorn | fd8b5bd57e |
|
@ -1,95 +1,48 @@
|
||||||
|
|
||||||
|
; A20 Wraparound check as gotten from osdev.org
|
||||||
check_a20_wraparound:
|
check_a20_wraparound:
|
||||||
.prolog:
|
pushf
|
||||||
push dword esi
|
push ds
|
||||||
sub esp, 64
|
push es
|
||||||
mov esi, esp
|
push di
|
||||||
|
push si
|
||||||
|
|
||||||
; EAX is used for the return value,
|
xor ax, ax ; ax = 0
|
||||||
; so it doesn't have to be preserved.
|
mov es, ax
|
||||||
mov [esi + (64 - 8)], ebx
|
|
||||||
mov [esi + (64 - 12)], edi
|
|
||||||
|
|
||||||
.test_a20:
|
not ax ; ax = 0xFFFF
|
||||||
; Save the values which are going to be overwritten
|
mov ds, ax
|
||||||
mov edi, 0x0800
|
|
||||||
mov eax, [edi]
|
|
||||||
mov edi, 0x00100800
|
|
||||||
mov ebx, [edi]
|
|
||||||
|
|
||||||
; Write to two locations which, if A20 wraps around,
|
mov di, 0x0500
|
||||||
; will both be written to by the second statement.
|
mov si, 0x0510
|
||||||
; Write 0 to 0x08000 to avoid the unlikely case that
|
|
||||||
; those bytes are there coincidentally and A20 is on.
|
|
||||||
mov edi, 0x0800
|
|
||||||
mov [edi], dword 0x00000000
|
|
||||||
mov edi, 0x00100800
|
|
||||||
mov [edi], dword 0xffaa00dd
|
|
||||||
|
|
||||||
; Check the lower address (which should NOT contain)
|
mov al, byte [es:di]
|
||||||
; this value for the value. If it does contain it, the
|
push ax
|
||||||
; memory space wraps around to 0 every 2^19 bytes.
|
|
||||||
cmp [0x0800], dword 0xffaa00dd
|
|
||||||
je .return_a20_not_enabled ; If the value at 0x0800
|
|
||||||
; was written to instead
|
|
||||||
; (or at the same time) of
|
|
||||||
; writing to 0x100800,
|
|
||||||
; the A20 wasn't enabled.
|
|
||||||
; Reset the values at the addresses to which the test
|
|
||||||
; values were written znd return that A20 is enabled.
|
|
||||||
mov edi, 0x0800
|
|
||||||
mov [edi], eax
|
|
||||||
mov edi, 0x00100800
|
|
||||||
mov [edi], ebx
|
|
||||||
|
|
||||||
.return_a20_enabled:
|
mov al, byte [ds:si]
|
||||||
|
push ax
|
||||||
|
|
||||||
mov eax, 1
|
mov byte [es:di], 0x00
|
||||||
|
mov byte [ds:si], 0xFF
|
||||||
|
|
||||||
; Restore the one used register which
|
cmp byte [es:di], 0xFF
|
||||||
; doesn't contain the return value.
|
|
||||||
mov ebx, [esi + (64 - 8)]
|
pop ax
|
||||||
|
mov byte [ds:si], al
|
||||||
|
|
||||||
|
pop ax
|
||||||
|
mov byte [es:di], al
|
||||||
|
|
||||||
|
mov ax, 0
|
||||||
|
je .exit
|
||||||
|
|
||||||
|
mov ax, 1
|
||||||
|
|
||||||
|
.exit:
|
||||||
|
pop si
|
||||||
|
pop di
|
||||||
|
pop es
|
||||||
|
pop ds
|
||||||
|
popf
|
||||||
|
|
||||||
add esp, 64
|
|
||||||
pop dword esi
|
|
||||||
ret
|
|
||||||
|
|
||||||
.return_a20_not_enabled:
|
|
||||||
; It's only necessary to write to one of the addresses
|
|
||||||
; as both of them are equal either way.
|
|
||||||
mov edi, 0x0800
|
|
||||||
mov [edi], eax
|
|
||||||
|
|
||||||
mov eax, 0
|
|
||||||
|
|
||||||
; Restore the one used register which
|
|
||||||
; doesn't contain the return value.
|
|
||||||
mov ebx, [esi + (64 - 12)]
|
|
||||||
mov edi, [esi + (64 - 8)]
|
|
||||||
|
|
||||||
add esp, 64
|
|
||||||
pop dword esi
|
|
||||||
ret
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
enable_a20_through_keyboard_controller:
|
|
||||||
.prolog:
|
|
||||||
push dword esi
|
|
||||||
sub esp, 64
|
|
||||||
mov esi, esp
|
|
||||||
|
|
||||||
mov [esi + (64 - 8)], ebx
|
|
||||||
mov [esi + (64 - 12)], ecx
|
|
||||||
mov [esi + (64 - 16)], edx
|
|
||||||
mov [esi + (64 - 20)], edi
|
|
||||||
|
|
||||||
.epilog:
|
|
||||||
mov ebx, [esi + (64 - 8)]
|
|
||||||
mov ecx, [esi + (64 - 12)]
|
|
||||||
mov edx, [esi + (64 - 16)]
|
|
||||||
mov edi, [esi + (64 - 20)]
|
|
||||||
|
|
||||||
add esp, 64
|
|
||||||
pop dword esi
|
|
||||||
ret
|
ret
|
||||||
|
|
|
@ -2,6 +2,8 @@
|
||||||
GDT_MEMORY_AREA equ 0x7e00
|
GDT_MEMORY_AREA equ 0x7e00
|
||||||
GDT_ENTRY_COUNT equ 3
|
GDT_ENTRY_COUNT equ 3
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; Arguments (note: all arguments are 4-byte padded):
|
; Arguments (note: all arguments are 4-byte padded):
|
||||||
; [Furthest from EBP]
|
; [Furthest from EBP]
|
||||||
;
|
;
|
||||||
|
@ -109,114 +111,6 @@ make_regular_data_segment_in_gdt:
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; 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):
|
; Arguments (note: all arguments are 4-byte padded):
|
||||||
; [Furthest from EBP]
|
; [Furthest from EBP]
|
||||||
;
|
;
|
||||||
|
@ -323,6 +217,7 @@ make_code_segment_in_gdt:
|
||||||
hlt
|
hlt
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
; [Furthest to EBP]
|
; [Furthest to EBP]
|
||||||
; 1) Return Address
|
; 1) Return Address
|
||||||
; [Nearest to EBP]
|
; [Nearest to EBP]
|
||||||
|
@ -346,28 +241,17 @@ load_flat_gdt:
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
push dword 2 ; Segment Index
|
push dword 2 ; Segment Index
|
||||||
push dword 0 ; Start Offset
|
push dword 0 ; Start Offset
|
||||||
push dword 0xfffff ; Page Count
|
push dword 0x000fffff ; Page Count
|
||||||
push dword 0 ; Required privilege level
|
push dword 0 ; Required privilege level
|
||||||
call make_regular_data_segment_in_gdt
|
call make_regular_data_segment_in_gdt
|
||||||
mov esp, ebp
|
mov esp, ebp
|
||||||
pop 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
|
push ebp
|
||||||
mov ebp, esp
|
mov ebp, esp
|
||||||
push dword 1 ; Segment Index
|
push dword 1 ; Segment Index
|
||||||
push dword 0x0000 ; Start Offset
|
push dword 0x0000 ; Start Offset
|
||||||
push dword 0xfffff ; Page Count
|
push dword 0x000fffff ; Page Count
|
||||||
push dword 0 ; Required privilege level
|
push dword 0 ; Required privilege level
|
||||||
call make_code_segment_in_gdt
|
call make_code_segment_in_gdt
|
||||||
mov esp, ebp
|
mov esp, ebp
|
||||||
|
@ -375,42 +259,39 @@ load_flat_gdt:
|
||||||
|
|
||||||
mov bx, 0
|
mov bx, 0
|
||||||
mov ds, bx
|
mov ds, bx
|
||||||
lgdt [.gdtr]
|
|
||||||
|
|
||||||
mov bx, (2 << 3)
|
|
||||||
mov ds, bx
|
|
||||||
mov es, bx
|
mov es, bx
|
||||||
mov fs, bx
|
mov fs, bx
|
||||||
mov gs, bx
|
mov gs, bx
|
||||||
; mov bx, (3 << 3)
|
|
||||||
mov ss, bx
|
mov ss, bx
|
||||||
|
lgdt [.gdtr]
|
||||||
|
|
||||||
mov ebx, cr0
|
mov ebx, cr0
|
||||||
or ebx, 1
|
or ebx, 1
|
||||||
mov cr0, ebx
|
mov cr0, ebx
|
||||||
|
|
||||||
xor bx, bx
|
jmp dword (1 << 3):.epilog
|
||||||
mov ds, bx
|
|
||||||
|
|
||||||
jmp dword 0x08:.epilog
|
|
||||||
|
|
||||||
bits 32
|
bits 32
|
||||||
.epilog:
|
.epilog:
|
||||||
|
mov bx, (2 << 3)
|
||||||
|
mov ds, bx
|
||||||
|
mov es, bx
|
||||||
|
mov fs, bx
|
||||||
|
mov gs, bx
|
||||||
|
mov ss, bx
|
||||||
|
|
||||||
mov edi, [esi + (64 - 20)]
|
mov edi, [esi + (64 - 20)]
|
||||||
mov edx, [esi + (64 - 16)]
|
mov edx, [esi + (64 - 16)]
|
||||||
mov ecx, [esi + (64 - 12)]
|
mov ecx, [esi + (64 - 12)]
|
||||||
mov ebx, [esi + (64 - 8)]
|
mov ebx, [esi + (64 - 8)]
|
||||||
mov eax, [esi + (64 - 4)]
|
mov eax, [esi + (64 - 4)]
|
||||||
|
|
||||||
add esp, 64
|
jmp dword stage2_true_entry
|
||||||
pop esi
|
|
||||||
jmp stage2_true_entry
|
|
||||||
; jmp after_gdt_loaded
|
|
||||||
|
|
||||||
align 16
|
align 16
|
||||||
.gdtr:
|
.gdtr:
|
||||||
.gdtr.length:
|
.gdtr.length:
|
||||||
dw 15
|
dw 23
|
||||||
.gdtr.pointer:
|
.gdtr.pointer:
|
||||||
dd GDT_MEMORY_AREA
|
dd GDT_MEMORY_AREA
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue