diff --git a/boot0.s b/boot0.s index 9349f3b..bd3a8f9 100644 --- a/boot0.s +++ b/boot0.s @@ -22,6 +22,10 @@ ; bp - 0x0c: sector stride when loading GPT entries ; bp - 0x0e: byte stride when loading GPT entries ; bp - 0x10: entries per sector when loding GPT entries +; bp - 0x12: current entry index +; bp - 0x14: current entry index within the current sector +; bp - 0x16: number of sectors loaded +; bp - 0x18: current LBA ; BIOS puts our boot sector at 0000:7c00 org 0x7c00 @@ -42,10 +46,6 @@ bits 16 mov bp, 0x7c00 mov sp, bp - ; Segment for VGA (0xb800 * 16 = 0xb8000) - mov ax, 0xb800 - mov fs, ax - ; Store boot drive number xor dh, dh push dx @@ -71,9 +71,9 @@ bits 16 inc cl xor ah, ah ; Zero-extend temp xor dx, dx ; div by 16-bit register divides dx:ax, so we zero dx - div bx ; ah = mod (head), al = div (cylinder) + div bx ; dx = mod (head), ax = div (cylinder) - mov dh, ah ; Head + mov dh, dl ; Head mov ch, al ; Cylinder ; We already have sector in cl mov ah, 2 ; Read disk @@ -86,11 +86,6 @@ bits 16 ; head = temp % number of heads ; cylinder = temp / number of heads - ; Set VGA mode - ; https://mendelson.org/wpdos/videomodes.txt - mov ax, 0x0003 - int 0x10 - mov cx, 8 mov si, .gpt_magic mov di, 0x7e00 @@ -99,13 +94,10 @@ bits 16 ; Ensure the 8-byte GPT starting LBA fits in 16 bits mov di, 0x7e00 ; The rep increments di so we need to reset it - xor bx, bx - mov ax, [di + 0x4a] - or bx, ax - mov ax, [di + 0x4c] - or bx, ax - mov ax, [di + 0x4e] - or bx, ax + mov eax, [di + 0x4c] + mov bx, [di + 0x4a] + or ax, bx + or eax, eax jnz .panic ; Load and spill the GPT starting LBA mov ax, [di + 0x48] @@ -153,6 +145,8 @@ bits 16 .gpt_sector_stride_loaded: push ax + ; Find the "byte stride", which is the number of bytes we increment by each time we want to load + ; the next entry in the same sector. cmp ebx, 512 jb .gpt_find_entries_per_sector push word 0 ; Arbitrary byte stride since there's only one entry per sector @@ -166,13 +160,75 @@ bits 16 push ax .gpt_found_entries_per_sector: + ; Set up stack variables for our second stage search loop. + xor ax, ax + push ax ; Current entry + push ax ; Current entry within the current sector + push ax ; First LBA loaded? + mov ax, [bp - 0x08] ; Starting LBA + push ax ; Current LBA + + ; Search for the partition storing our second stage. +.loop_find_stage2: + mov dx, [bp - 0x12] + cmp [bp - 0x0a], dx + ; Panic if we've run out of partitions and haven't found the second stage yet. + jbe .panic + + ; If we haven't loaded any sectors yet, load the first one. + cmp word [bp - 0x16], 0 ; Load number of sectors loaded + je .load_first_lba + ; If there's still more entries in the current sector, skip loading a new sector + mov ax, [bp - 0x18] ; Load current entry index within the current sector + cmp [bp - 0x10], ax ; Compare to entries per sector + ja .process_current_entry + + mov ax, [bp - 0x0c] ; Load sector stride + add word [bp - 0x18], ax ; Increment current LBA by sector stride + mov word [bp - 0x14], 0 ; Reset the current entry index within the current sector +.load_first_lba: + mov ax, [bp - 0x18] ; Load current LBA + xor dx, dx + div word [bp - 0x04] ; Divide by sectors per track. dx = mod (sector - 1), ax = div (temp) + mov cx, dx + inc cx ; Put sector into cx (bios will read sector from cl) + xor dx, dx + div word [bp - 0x06] ; Divide by number of heads. dx = mod (head), ax = div (cylinder) + mov dh, dl + mov ch, al + mov dl, byte [bp - 0x02] ; Load drive number + mov ah, 0x02 + mov al, 1 + mov bx, 0x8000 + int 0x13 ; Read sector + jc .panic + inc word [bp - 0x16] ; Increment number of sectors loaded + +.process_current_entry: + jmp .debug + ; TODO + ; TODO: remember to read offset by current entry index within the current sector + + inc word [bp - 0x12] ; Increment current entry index + inc word [bp - 0x14] ; Increment current entry index within the current sector + jmp .loop_find_stage2 + +.debug: + ; Segment for VGA (0xb800 * 16 = 0xb8000) + mov ax, 0xb800 + mov fs, ax + + ; Set VGA mode + ; https://mendelson.org/wpdos/videomodes.txt + mov ax, 0x0003 + int 0x10 + mov al, [0x7e00] mov byte fs:[0x0000], al - mov al, [0x7e01] + + mov al, [0x8000] mov byte fs:[0x0002], al - mov al, [0x7e02] - mov byte fs:[0x0004], al - + ; mov word fs:[0x0000], 0xc048 ; mov word fs:[0x0002], 0xc069 @@ -183,10 +239,7 @@ bits 16 int 0x10 mov ax, 0xb800 mov ds, ax - mov word [0x0000], 0x4f46 - mov word [0x0002], 0x4f41 - mov word [0x0004], 0x4f49 - mov word [0x0006], 0x4f4c + mov word [0x0000], 0x4f21 hlt ; TODO: enable A20 @@ -209,6 +262,10 @@ bits 16 .gpt_magic: db "EFI PART" +.guid_linux: + db 0xaf, 0x3d, 0xc6, 0x0f, 0x83, 0x84, 0x72, 0x47, \ + 0x8e, 0x79, 0x3d, 0x69, 0xd8, 0x47, 0x7d, 0xe4 + ; MBR bootstrap field is 440 bytes long %if ($ - $$) > 440 %error "exceeded mbr bootstrap field size"