USE16 stage1: ; dl comes with disk ; initialize segment registers xor ax, ax mov ds, ax mov es, ax mov ss, ax ; initialize stack mov sp, 0x7C00 ; initialize CS push ax push word .set_cs retf .set_cs: ; save disk number mov [disk], dl mov si, stage_msg call print mov al, '1' call print_char call print_line ; read CHS gemotry ; CL (bits 0-5) = maximum sector number ; CL (bits 6-7) = high bits of max cylinder number ; CH = low bits of maximum cylinder number ; DH = maximum head number mov ah, 0x08 mov dl, [disk] xor di, di int 0x13 jc error ; carry flag set on error mov bl, ch mov bh, cl shr bh, 6 mov [chs.c], bx shr dx, 8 inc dx ; returns heads - 1 mov [chs.h], dx and cl, 0x3f mov [chs.s], cl ; PARAM stage1 0x7C00 ; PARAM stage2 0xC000 ; PARAM stage3.end 0x4b600 ; disk address of stage 2 ; (start sector) mov eax, STAGE2_SECTOR ; where to load stage 2 mov bx, stage2 ; length of stage2 + stage3 ; (on disk, in sectors) mov cx, (stage3.end - stage2) / 512 mov dx, 0 call load mov si, stage_msg call print mov al, '2' call print_char call print_line jmp stage2.entry ; load some sectors from disk to a buffer in memory ; buffer has to be below 1MiB ; IN ; ax: start sector ; bx: offset of buffer ; cx: number of sectors (512 Bytes each) ; dx: segment of buffer ; CLOBBER ; ax, bx, cx, dx, si ; TODO rewrite to (eventually) move larger parts at once ; if that is done increase buffer_size_sectors in startup-common to that (max 0x80000 - startup_end) load: cmp cx, 127 jbe .good_size pusha mov cx, 127 call load popa add eax, 127 add dx, 127 * 512 / 16 sub cx, 127 jmp load .good_size: mov [DAPACK.addr], eax mov [DAPACK.buf], bx mov [DAPACK.count], cx mov [DAPACK.seg], dx ; This should be a subroutine, ; but we don't call/ret to save a few bytes. ; (we only use this once) ; ;call print_dapack ;print_dapack: mov bx, [DAPACK.addr + 2] call print_hex mov bx, [DAPACK.addr] call print_hex mov al, '#' call print_char mov bx, [DAPACK.count] call print_hex mov al, ' ' call print_char mov bx, [DAPACK.seg] call print_hex mov al, ':' call print_char mov bx, [DAPACK.buf] call print_hex call print_line ;ret ; End of print_dapack cmp byte [chs.s], 0 jne .chs ;INT 0x13 extended read does not work on CDROM! mov dl, [disk] mov si, DAPACK mov ah, 0x42 int 0x13 jc error ; carry flag set on error ret .chs: ; calculate CHS xor edx, edx mov eax, [DAPACK.addr] div dword [chs.s] ; divide by sectors mov ecx, edx ; move sector remainder to ecx xor edx, edx div dword [chs.h] ; divide by heads ; eax has cylinders, edx has heads, ecx has sectors ; Sector cannot be greater than 63 inc ecx ; Sector is base 1 cmp ecx, 63 ja error_chs ; Head cannot be greater than 255 cmp edx, 255 ja error_chs ; Cylinder cannot be greater than 1023 cmp eax, 1023 ja error_chs ; Move CHS values to parameters mov ch, al shl ah, 6 and cl, 0x3f or cl, ah shl dx, 8 ; read from disk using CHS mov al, [DAPACK.count] mov ah, 0x02 ; disk read (CHS) mov bx, [DAPACK.buf] mov dl, [disk] push es ; save ES mov es, [DAPACK.seg] int 0x13 pop es ; restore EC jc error ; carry flag set on error ret error_chs: mov ah, 0 error: call print_line mov bh, 0 mov bl, ah call print_hex mov si, stage1_error_msg call print call print_line .halt: cli hlt jmp .halt %include "print.asm" stage_msg: db "Stage ",0 stage1_error_msg: db " ERROR",0 disk: db 0 chs: .c: dd 0 .h: dd 0 .s: dd 0 DAPACK: db 0x10 db 0 .count: dw 0 ; int 13 resets this to # of blocks actually read/written .buf: dw 0 ; memory buffer destination address (0:7c00) .seg: dw 0 ; in memory page zero .addr: dq 0 ; put the lba to read in this spot db 0xff