%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