You cannot select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
177 lines
3.8 KiB
ArmAsm
177 lines
3.8 KiB
ArmAsm
[bits 16]
|
|
|
|
%include "fn.s"
|
|
%include "layout.s"
|
|
%include "s2_fns.s"
|
|
|
|
extern test_a20
|
|
extern enable_a20_intel_8042
|
|
extern load_s3
|
|
|
|
s2_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:
|
|
call load_s3
|
|
jc panic_simple
|
|
|
|
mov ax, 0x0003
|
|
int 0x10
|
|
|
|
; Disable cursor
|
|
mov ax, 0x0100
|
|
mov cx, 0x3f00
|
|
int 0x10
|
|
|
|
; Copy the GDT
|
|
mov cx, GDT_FLAT_LEN
|
|
mov si, gdt_flat
|
|
mov di, GDT_FLAT_ADDR
|
|
rep movsb
|
|
|
|
; 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
|
|
|
|
jmp S3_LOAD_ADDR
|
|
|
|
.halt:
|
|
hlt
|
|
jmp .halt
|
|
|
|
global s2_main
|
|
|
|
|
|
section .s3_data
|
|
|
|
gdt_flat_slice:
|
|
dw GDT_FLAT_LEN
|
|
dd GDT_FLAT_ADDR
|
|
|
|
; 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)
|
|
;
|
|
|
|
align 8
|
|
gdt_flat:
|
|
; First GDT entry must be 0.
|
|
dq 0
|
|
|
|
; 32-bit code segment.
|
|
; Pages 0x0000 - 0xffff. Needs to contain 0x10000, where the stage 3 text is loaded.
|
|
.segment_code_32:
|
|
db 0xff, 0xff, \
|
|
0x00, 0x00, \
|
|
0x00, \
|
|
10011011b, \
|
|
11001111b, \
|
|
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
|
|
|
|
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
|