diff --git a/stage_1/start.asm b/stage_1/start.asm index 08c814c..4b988f6 100644 --- a/stage_1/start.asm +++ b/stage_1/start.asm @@ -3,8 +3,6 @@ section .text org 0x7c00 start: - push dx - mov ax, 0 mov ds, ax mov es, ax @@ -17,62 +15,196 @@ start: mov sp, 256 mov bp, 256 + mov si, dx ; save the origin disk number + mov ax, 0x7c00 add ax, 446 ; ax now points to the start of the partition table - mov di, 0 - + xor di, di + call initialize_video_mode .search_partition: - mov bx, ax - add bx, 4 + mov bx, ax ; get the offset of the current entry + add bx, 4 ; go to the offset of the partition type mov cl, [bx] cmp cl, 0x9d - je .found_partition + je .load_partition inc di + + ; leave and print debug message if the last partition entry + ; did not provide the wanted bootloader - partition cmp di, 4 je .no_boot_partition + add ax, 16 + jmp .search_partition -.found_partition: +.load_partition: + ; ax is the start of the bootloader's partition entry in the mbr + + ; read the chs-entry and push it onto the stack + + ; head + xor dx, dx + mov bx, ax + add bx, 1 + mov dl, [bx] + push dx + + ; cylinder + xor dx, dx + mov bx, ax + add bx, 3 + mov dh, [bx] + mov bx, ax + add bx, 2 + mov dl, [bx] + shr dx, 6 + push dx + + ; sector + xor dx, dx + mov bx, ax + add bx, 2 + mov dl, [bx] + and dl, 0b00111111 + push dx + + + + ; push the partition's length + + mov bx, ax + add bx, 12 + mov dx, [bx] + push dx ; lower part mov bx, ax add bx, 14 - mov cx, [bx] ; more than 65536 sectors will NOT be - ; supported for the bootloader's partition! - - mov bx, 0x8000 - mov es, bx - mov di, 0x0000 - - mov bx, ax - inc bx - ; bx now points to the CHS-address of the first sector - ; of the bootloader's partition. - mov dx, [bx] - mov ah, dh ; head - mov bl, dl ; sector + push dx ; higher part + + + + ; load it all and read from disk + + mov bx, sp + add bx, 4 + + mov al, [bx] ; sector-count add bx, 2 - ; bx now points to the CHS-cylinder of the first sector - ; of the bootloader's partition. + mov cl, [bx] ; start-sector - mov al, [bx] ; cylinder + add bx, 2 + mov ch, [bx] ; start-cylinder - call load_sectors + mov dx, si ; drive + mov bx, 0x0800 + mov es, bx ; output segment + + mov bx, sp + add bx, 8 + mov dh, [bx] ; start-head + call .write_hex + + + + mov cl, 2 + mov ah, 0x02 + mov al, 1 + mov bx, 0x0000 ; output address in es - segment + int 13h + + + + mov cx, 8 + mov si, 0x8000 + mov dh, 12 + mov dl, 32 + call print_string + jmp .keepalive + .no_boot_partition: - hlt + mov cx, LEN_TEXT_NO_BOOT_PARTITION + mov si, error_texts.no_boot_partition + mov dh, 12 + mov dl, 32 + call print_string + +.keepalive: + jmp .keepalive + +.write_hex: + push bx + push cx + + mov bx, error_texts.hextab + and cx, 0x0f + add bx, cx + mov cl, [bx] + mov bx, error_texts.hexbuf + inc bx + mov [bx], cl + + mov bx, error_texts.hextab + and cx, 0xf0 + shr cx, 4 + add bx, cx + mov cl, [bx] + mov bx, error_texts.hexbuf + mov [bx], cl + + mov cx, 2 + mov si, error_texts.hexbuf + mov dh, 12 + mov dl, 32 + call print_string + + pop cx + pop bx + + ret +; %include "exfat.asm" %include "gdt.asm" %include "utility.asm" + +LEN_TEXT_NO_BOOT_PARTITION equ 17 + +error_texts: + +.no_boot_partition: + ;db "NO_BOOT_PARTITION" + +.hextab: + db "0123456789abcdef" + +.hexbuf: + resb 4 + + +times 446 - ($-$$) db 0 +db 0x80 +db 0, 2, 0 +db 0x9d +db 0, 3, 0 +dd 1 +dd 1 + +times 510 - ($-$$) db 0 + +db 0x55 +db 0xAA + +db "################" diff --git a/stage_1/utility.asm b/stage_1/utility.asm index e04262e..3d91f6c 100644 --- a/stage_1/utility.asm +++ b/stage_1/utility.asm @@ -198,14 +198,28 @@ mem_equals: -; ax: start_sector (lower) -; bl: start_sector (upper) -; cx: sector_count +; ax: start_sector (upper) +; bl: start_sector (lower) +; cx: wanted_sector_count ; dh: drive -; es: buffer_address (upper) +; si: buffer_address (upper) ; di: buffer_address (lower) load_sectors: + ; INNER WORKING: + ; + ; This function first checks if it needs to load sectors going over + ; a cylinder boundary and loads to that cylinder boundary first continuing + ; in 63-sector - parts after that until the last, < 63-sectors part is read. + ; + ; This is done because some systems don't like reading over the boundaries + ; between the cylinders. + ; + ; The actual part loading the data is in .read_from_disk, it's no different + ; from the first read to the other reads. It just gets different arguments + ; from 1).load_first_sectors, and 2) .load_further_sectors + ; + .prolog: push ax push bx @@ -214,101 +228,43 @@ load_sectors: push si xor si, si ; current sector index - - - ; calculate the distance (in sectors) to the next cylinder boundary - - ; get the index of the current cylinder - and ax, 0b00111111 ; extract only the sector index - mov bx, 64 ; get the maximum number of sectors + 1 - sub bx, ax ; invert the result; 1 becomes 63; 63 becomes 1 - cmp ax, 63 - jne .is_not_on_full_cylinder_boundary - - ; if it's indeed on a full cylinder boundary, the first_read-part is unimportant - mov ax, 0 - set_load_args - -.is_not_on_full_cylinder_boundary: +.load_first_sectors: - ; cx still contains the entry-point's wanted sector_count - ; ax now contains the distance to the next cylinder boundary - cmp cx, ax - jbe .load_data - ; it gets here if there are more sectors needed after the - ; next cylinder boundary - ; if the number of sectors - ; which are wanted (sector_count) is above the - ; distance to the next cylinder boundary +; ah: EMPTY +; al: num_sectors_to_read +; bx: EMPTY +; ch: cylinder +; cl: sector +; dh: head +; dl: drive +.read_from_disk: - ; if not that many sectors are needed, just read as - ; many sectors as are needed in total - mov cx, bx + ; set es:bx to the address in bytes to which the output should be written. - jmp .load_data + mov bx, si + shr bx, 9 -; sets the arguments for a run of '.load_data' after the -; first one; aligned on a CHS - cylinder boundary -.set_load_args: - - mov bx, sp - add bx, 4 - mov cx, [bx] - sub cx, si ; cx = num_missing_sectors - - cmp cx, 63 - jbe .add_num_missing_sectors_to_sector_index - - ; if this goes here, there are more than 63 sectors - ; still missing to be loaded - ; -> clamp them to 63 so they can be loaded. - mov cl, 63 - jmp .load_data - -.add_num_missing_sectors_to_sector_index: - - add si, cx - -; loads at most 64 sectors from the disk into the main memory -; ax: scratchpad -; bx: start_sector (high part) -; ch: start_sector (low part) -; cl: num_sectors -.load_data: mov ah, 0x02 - mov al, cl - mov dl, [bx] ; drive - mov dh, bh ; head - mov cl, ch ; sector - mov ch, bl ; cylinder - mov bx, di ; buffer address (lower) int 0x13 -.continue_if_needed: - ; check if there still are sectors missing to load - mov bx, sp - add bx, 4 - mov cx, [bx] ; sector_count - cmp si, cx - jb .set_load_args +.load_further_sectors: + + + + + +.epilog: -.epilog: - pop si - pop dx - pop cx - pop bx - pop ax - ret