275 lines
3.9 KiB
NASM
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 |