x86_fat12bs/src/stage2.asm

275 lines
3.9 KiB
NASM

%include "addr.inc"
org STAGE2_OFFSET
jmp start16
%macro print_msg 1
mov ax, %1
push ax
push ds
call print_str
add sp, 4
%endmacro
%macro print_rtn 0
mov ax, 0xA
call print_char
%endmacro
%macro print_addr 2
push %1
call print_u16
add sp, 2
mov ax, 0x3A ; colon
call print_char
push %2
call print_u16
add sp, 2
%endmacro
[section .data]
[bits 16]
fn_kernel: db 'KERNEL BIN',0
fn_stage3: db 'STAGE3 BIN',0
msg_ok: db 'OK ', 0
msg_err: db 'ERR ', 0
msg_stage2_hello: db 'Stage2 loader loaded at ', 0
msg_det_mem: db 'Detecting memory... ', 0
msg_det_mem_title: db "Memory Information: ", 0
msg_det_mem_tbl_hdr: db 'Base Length Type ',0 ; each field is of length 20
msg_det_mem_tbl_pad: db ' ',0 ; 4 x spaces
msg_ld_stage3: db 'Loading stage3.bin... ', 0
msg_ld_krnl: db 'Loading kernel.bin... ', 0
msg_init_pm: db 'Initializing protected mode and jumping to stage3 loader... ', 0
%include "fat12_hdr.inc"
[section .text]
[bits 16]
%include "print16.lib"
%include "fat12_drv.lib"
start16:
mov ax,cs
mov ds,ax
mov ss,ax
mov es,ax
; initialize video mode
xor ax, ax
mov al, 0x03
int 0x10
print_msg msg_stage2_hello
print_addr STAGE2_BASE, STAGE2_OFFSET
print_rtn
print_msg msg_det_mem
call detect_mem
cmp ax, 1
je .err
print_msg msg_ok
print_rtn
print_msg msg_det_mem_title
print_rtn
call print_mem_layout
print_rtn
print_msg msg_ld_stage3
push word fn_stage3
push word STAGE3_OFFSET
push word STAGE3_BASE
call fat12_read_file
add esp, 6
cmp ax, 1
je .err
print_msg msg_ok
print_addr STAGE3_BASE, STAGE3_OFFSET
print_rtn
print_msg msg_ld_krnl
push word fn_kernel
push word KERNEL_OFFSET
push word KERNEL_BASE
call fat12_read_file
add esp, 6
cmp ax, 1
je .err
print_msg msg_ok
print_addr KERNEL_BASE, KERNEL_OFFSET
print_rtn
print_msg msg_init_pm
;load gdt
lgdt [gdtr32]
;open A20
in al,92h
or al,00000010b
out 92h,al
;prepare to switch to the protected mode
mov eax,cr0
or eax,1
mov cr0,eax
; pass the frame buffer
xor ebx, ebx
mov bx, word [vb_pos]
jmp dword gdt32.sel_code:(STAGE2_FLAT + start32)
start16.err:
print_msg msg_err
jmp $
;;;;;;;;;;;;;;;;;;
; detects system memory
; memory maps stored in detect_mem_buf
; # of maps stored in detect_mem_num
; returns:
; ax = 0 success / 1 fail
;;;;;;;;;;;;;;;;;;
detect_mem_buf: times 1024 db 0
detect_mem_num: dw 0
detect_mem:
push ebx
push ecx
push edx
push esi
push edi
xor ebx,ebx
mov di, detect_mem_buf ;es:di = ASRD
.loop:
; configure int 0x15 magic values
mov eax,0xE820
mov ecx,20
mov edx,0534D4150h
int 0x15
jc .fail
inc word [detect_mem_num]
add di,20
; ebx = 0 means finished
test ebx, ebx
jne .loop
jmp .end
.fail:
mov ax, 1
.end:
pop edi
pop esi
pop edx
pop ecx
pop ebx
ret
;;;;;;;;;;;;;;;;;;
;
; prints system memory layout
;
;;;;;;;;;;;;;;;;;;
print_mem_layout:
push eax
push si
push cx
push ds
print_msg msg_det_mem_tbl_hdr
print_rtn
; si is the pointer into the array
mov si, detect_mem_buf
; cx = total number of memory descriptors
mov cx, word [ds:detect_mem_num]
.cont:
; print base addr
push si
push ds
call print_u64
add sp, 4
print_msg msg_det_mem_tbl_pad
; print length
add si, 8
push si
push ds
call print_u64
add sp, 4
print_msg msg_det_mem_tbl_pad
; print type
add si, 8
mov eax, dword [ds:si]
push eax
call print_u32
add sp, 4
print_rtn
add si, 4
loop .cont
pop ds
pop cx
pop si
pop eax
ret
[section .text]
[bits 32]
start32:
; ebx holds -> vram_buffer
mov ax,gdt32.sel_data
mov ss,ax
mov ds,ax
mov es,ax
mov gs,ax
; adjust
;Jump to stage 3
mov eax, STAGE3_FLAT
jmp eax
[section .data]
[bits 32]
gdt32:
dd 0
dd 0
.sel_code: equ $ - gdt32
dw 0xFFFF ; LIMIT = 0xFFFF
dw 0 ; BASE LOW = 0
db 0 ; BASE MID = 0
db 10011010b; PRESENT | RW | EXE
db 11001111b; Granularity = 4k | 32 bits
db 0 ; BASE_HIGH = 0
.sel_data: equ $ - gdt32
dw 0xFFFF ; LIMIT = 0xFFFF
dw 0 ; BASE LOW = 0
db 0 ; BASE MID = 0
db 10010010b; PRESENT | RW | EXE
db 11001111b; Granularity = 4k | 32 bits
db 0 ; BASE_HIGH = 0
.size: equ $ - gdt32
gdtr32: dw gdt32.size - 1
dd STAGE2_FLAT + gdt32