wip refactor
This commit is contained in:
1 parent
ae2720c826
commit
2b1a9f9412
15 files changed
+906
-20
No files matched your search
Binary file not shown.
+112
@@ -0,0 +1,112 @@
|
||||
%include "fn.s"
|
||||
%include "ps2.s"
|
||||
|
||||
|
||||
%macro mov_out 3
|
||||
mov %1, %3
|
||||
out %2, %1
|
||||
%endmacro
|
||||
|
||||
|
||||
; Check whether the A20 line is enabled. Writes to the boot sector identifier.
|
||||
; Arguments: none
|
||||
; Return:
|
||||
; - ax: 0 if A20 disabled, nonzero if A20 enabled
|
||||
; Clobber: none
|
||||
test_a20:
|
||||
push bp
|
||||
mov bp, sp
|
||||
push gs
|
||||
|
||||
; Restore the boot sector identifier in case it was overwritten by anything.
|
||||
mov word [0x7dfe], 0xaa55
|
||||
|
||||
mov ax, 0xffff
|
||||
mov gs, ax
|
||||
xor ax, ax
|
||||
|
||||
; If the word at 0x107dfe (1 MiB after the boot sector identifier) is different to the boot
|
||||
; sector identifier, than A20 must be enabled.
|
||||
cmp word gs:[0x7e0e], 0xaa55
|
||||
setne al
|
||||
jne .return
|
||||
|
||||
; Even if A20 was enabled, the two words may have been equal by chance, so we temporarily swap
|
||||
; the boot sector identifier bytes and test again.
|
||||
ror word [0x7dfe], 8
|
||||
cmp word gs:[0x7e0e], 0x55aa
|
||||
setne al
|
||||
ror word [0x7dfe], 8
|
||||
jmp .return
|
||||
|
||||
.return:
|
||||
pop gs
|
||||
pop bp
|
||||
ret
|
||||
|
||||
global test_a20
|
||||
|
||||
|
||||
; Try to enable A20 using the Intel 8042 PS/2 keyboard controller.
|
||||
; Arguments: none
|
||||
; Return: none
|
||||
; Clobber: ax, cx, dx
|
||||
enable_a20_intel_8042:
|
||||
; Temporarily disable the keyboard.
|
||||
call intel_8042_wait_write
|
||||
mov_out al, INTEL_8042_OUT_CMD, INTEL_8042_CMD_PS2_1_DISABLE
|
||||
|
||||
; Read the controller output port.
|
||||
call intel_8042_wait_write
|
||||
mov_out al, INTEL_8042_OUT_CMD, INTEL_8042_CMD_CONTROLLER_OUT_PORT_READ
|
||||
call intel_8042_wait_read
|
||||
in al, INTEL_8042_IO_DATA
|
||||
|
||||
; The second bit is "A20 enabled", so set it.
|
||||
mov cl, al
|
||||
or cl, 2
|
||||
|
||||
; Write the modified byte back to the controller output port.
|
||||
call intel_8042_wait_write
|
||||
mov_out al, INTEL_8042_OUT_CMD, INTEL_8042_CMD_CONTROLLER_OUT_PORT_WRITE
|
||||
call intel_8042_wait_write
|
||||
mov_out al, INTEL_8042_IO_DATA, cl
|
||||
|
||||
; Re-enable the keyboard.
|
||||
call intel_8042_wait_write
|
||||
mov_out al, INTEL_8042_OUT_CMD, INTEL_8042_CMD_PS2_1_ENABLE
|
||||
|
||||
; Wait for writes to finish.
|
||||
call intel_8042_wait_write
|
||||
|
||||
ret
|
||||
|
||||
global enable_a20_intel_8042
|
||||
|
||||
|
||||
; Wait for the Intel 8042 input buffer to become empty, so we can write.
|
||||
; Arguments: none
|
||||
; Return: none
|
||||
; Clobber: al
|
||||
intel_8042_wait_write:
|
||||
.loop:
|
||||
; Read the 8042 status register.
|
||||
in al, INTEL_8042_IN_STATUS
|
||||
; Input buffer status flag set means the input buffer is full, so loop in this case.
|
||||
test al, INTEL_8042_STATUS_MASK_IBUF
|
||||
jnz .loop
|
||||
ret
|
||||
|
||||
|
||||
; Wait for the Intel 8042 output buffer to become filled, so we can read.
|
||||
; Arguments: none
|
||||
; Return: none
|
||||
; Clobber: al
|
||||
intel_8042_wait_read:
|
||||
.loop:
|
||||
; Read the 8042 status register.
|
||||
in al, INTEL_8042_IN_STATUS
|
||||
; Output buffer status flag unset means output buffer is empty, so loop in this case.
|
||||
test al, INTEL_8042_STATUS_MASK_OBUF
|
||||
jz .loop
|
||||
ret
|
||||
Binary file not shown.
+180
@@ -0,0 +1,180 @@
|
||||
[bits 16]
|
||||
|
||||
%include "fn.s"
|
||||
%include "layout.s"
|
||||
%include "s2_fns.s"
|
||||
|
||||
extern test_a20
|
||||
extern enable_a20_intel_8042
|
||||
|
||||
section .s3_text
|
||||
|
||||
s3_main:
|
||||
call test_a20
|
||||
test al, al
|
||||
jnz .a20_enabled
|
||||
|
||||
; Try to enable A20 using the Intel 8042 PS/2 keyboard controller.
|
||||
call enable_a20_intel_8042
|
||||
call test_a20
|
||||
test al, al
|
||||
jnz .a20_enabled
|
||||
|
||||
; TODO: try other methods first before we panic:
|
||||
; - [ ] BIOS interrupt
|
||||
; - [ ] Fast A20 enable
|
||||
jmp panic_simple
|
||||
|
||||
.a20_enabled:
|
||||
mov ax, 0x0003
|
||||
int 0x10
|
||||
|
||||
; Disable cursor
|
||||
mov ax, 0x0100
|
||||
mov cx, 0x3f00
|
||||
int 0x10
|
||||
|
||||
; Ensure interrupts are definitely disabled.
|
||||
cli
|
||||
|
||||
; Load our flat-address-space GDT.
|
||||
lgdt [gdt_flat_slice]
|
||||
|
||||
; Set the protected-mode bit in cr0.
|
||||
mov eax, cr0
|
||||
or al, 0x01
|
||||
mov cr0, eax
|
||||
|
||||
; Long jump to set the code segment to gdt_flat.segment_code, and to clear the instruction
|
||||
; pipeline.
|
||||
jmp GDT_FLAT_IDX_CODE_32:.protected_mode_32
|
||||
|
||||
[bits 32]
|
||||
.protected_mode_32:
|
||||
|
||||
; Set the data segments to gdt_flat.segment_data.
|
||||
mov eax, GDT_FLAT_IDX_DATA
|
||||
mov ds, eax
|
||||
mov es, eax
|
||||
mov fs, eax
|
||||
mov gs, eax
|
||||
mov ss, eax
|
||||
|
||||
; Reset the stack.
|
||||
; TODO: put the 32-bit stack somewhere else.
|
||||
mov ebp, REAL_STACK_BASE
|
||||
mov esp, ebp
|
||||
|
||||
; TODO
|
||||
; jmp _start
|
||||
|
||||
.halt:
|
||||
hlt
|
||||
jmp .halt
|
||||
|
||||
; panic_simple_32:
|
||||
; mov word [0xb8000], 0x4f21
|
||||
; .halt:
|
||||
; hlt
|
||||
; jmp .halt
|
||||
|
||||
global s3_main
|
||||
|
||||
|
||||
section .s3_data
|
||||
|
||||
gdt_flat_slice:
|
||||
dw GDT_FLAT_LEN
|
||||
dd gdt_flat
|
||||
|
||||
global gdt_flat_slice
|
||||
|
||||
; Segment descriptor layout
|
||||
; | Range (bits) | Field |
|
||||
; |--------------|---------------|
|
||||
; | 0-16 | limit |
|
||||
; | 16-32 | base |
|
||||
; | 32-40 | base cont. |
|
||||
; | 40-48 | access |
|
||||
; | 48-52 | limit cont. |
|
||||
; | 52-56 | flags |
|
||||
; | 56-64 | base cont. |
|
||||
;
|
||||
; Flags
|
||||
; - 0: reserved
|
||||
; - 1: long-mode code segment
|
||||
; - 2: size
|
||||
; - unset: 16-bit
|
||||
; - set: 32-bit
|
||||
; - 3: granularity
|
||||
; - unset: limit is measured in bytes
|
||||
; - set: limit is measured in 4KiB pages
|
||||
;
|
||||
; Access
|
||||
; - 0: accessed
|
||||
; - unset: CPU will set it when the segment is accessed
|
||||
; - 1: readable / writable
|
||||
; - data segments: is segment writable (data segments are always readable)
|
||||
; - code segments: is segment readable (code segments are never writable)
|
||||
; - 2: direction / conforming
|
||||
; - data segments: whether segment grows down
|
||||
; - code segments: whether this can be executed from a lower-privilege ring
|
||||
; - 3: executable
|
||||
; - unset: this is a data segment
|
||||
; - set: this is a code segment
|
||||
; - 4: descriptor type
|
||||
; - unset: this is a task state segment
|
||||
; - set: this is a data or code segment
|
||||
; - 5-6: privilege level (ring number)
|
||||
; - 7: present (must be set)
|
||||
;
|
||||
|
||||
; FIXME: copy this to a fixed memory location
|
||||
align 8
|
||||
gdt_flat:
|
||||
; First GDT entry must be 0.
|
||||
dq 0
|
||||
|
||||
; 32-bit code segment.
|
||||
; Bytes 0x0000 - 0xffff.
|
||||
.segment_code_32:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10011011b, \
|
||||
01000000b, \
|
||||
0x00
|
||||
|
||||
; 16-bit code segment, to use if we want to switch back to real mode.
|
||||
; Bytes 0x0000 - 0xffff.
|
||||
.segment_code_16:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10011011b, \
|
||||
00000000b, \
|
||||
0x00
|
||||
|
||||
; Data segment.
|
||||
; Pages 0x000000 - 0x0fffff, which covers the entire 32-bit address space (start of 0xfffff-th page
|
||||
; is 0xfffff * 4096 = 0xfffff000, end of page exclusive is 0xfffff000 + 4096 = 0x100000000).
|
||||
.segment_data:
|
||||
db 0xff, 0xff, \
|
||||
0x00, 0x00, \
|
||||
0x00, \
|
||||
10010011b, \
|
||||
11001111b, \
|
||||
0x00
|
||||
|
||||
global gdt_flat
|
||||
|
||||
GDT_FLAT_LEN equ ($ - gdt_flat)
|
||||
|
||||
GDT_FLAT_IDX_CODE_32 equ (gdt_flat.segment_code_32 - gdt_flat)
|
||||
global GDT_FLAT_IDX_CODE_32
|
||||
|
||||
GDT_FLAT_IDX_CODE_16 equ (gdt_flat.segment_code_16 - gdt_flat)
|
||||
global GDT_FLAT_IDX_CODE_16
|
||||
|
||||
GDT_FLAT_IDX_DATA equ (gdt_flat.segment_data - gdt_flat)
|
||||
global GDT_FLAT_IDX_DATA
|
||||
Reference in new issue
Block a user