; number of sectors to be read for the kernel itself ; (note: the first sector gets loaded by the BIOS, the ; next 3 sectors are read by the simple stage 1 loader, ; so subtract 3 here!) NOF_LOAD_SECTORS equ 36 ; data sections used for reading the kernel from disk SECTORS_PER_CYLINDER: db 0x3F ; detect parameters enters the correct value here (sectors + 1) ; if detection fails, force int13 to read ahead NOF_HEADS: db 0x02 ; number of heads + 1 SECTORS_TO_LOAD: db NOF_LOAD_SECTORS ; load NOF_LOAD_SECTORS sectors in total CURRENT_SECTOR: db 5 ; first sector after stage 2 CURRENT_CYLINDER: db 0 CURRENT_HEAD: db 0 ; detect disk geometry ; IN dl: drive detect_disk_geometry: mov dx, 0 mov es, dx mov ah, 0x08 int 0x13 jc .error jmp .ok .error: mov si, DISK_ERROR call print_string mov dh, 0 mov dl, ah call print_hex ret .ok: add dh, 1 mov [NOF_HEADS], BYTE dh call print_hex mov dx, cx call print_hex and cl, 0x3F add cl, 1 mov [SECTORS_PER_CYLINDER], BYTE cl ret ; read the whole stage2 and kernel from the disk ; IN dl: drive to read from read_from_disk: mov bx, 0 ; where to store the data mov es, bx mov bx, 0x8400 ; 2'048 bytes after first sector .read_next_sector: call read_one_sector_from_disk sub [SECTORS_TO_LOAD], BYTE 1 ; one less to load cmp [SECTORS_TO_LOAD], BYTE 0 ; finished? je .finished add bx, 0x200 ; advance write buffer position add [CURRENT_SECTOR], BYTE 1 ; next sector mov ch, [SECTORS_PER_CYLINDER] cmp [CURRENT_SECTOR], ch ; after the end of the current track? je .next_head jmp .read_next_sector .next_head: mov [CURRENT_SECTOR], BYTE 1 ; start from first sector again add [CURRENT_HEAD], BYTE 1 ; advance head mov ch, [NOF_HEADS] cmp [CURRENT_HEAD], ch ; after the number of heads? je .next_track jmp .read_next_sector .next_track: mov [CURRENT_HEAD], BYTE 0 ; start from head 0 again add [CURRENT_CYLINDER], BYTE 1 ; advance track jmp .read_next_sector .finished: ret ; Read one sector after the other, if we get illegal parameter ; errors we assume we have gone over the limit of number of ; sectors per cylinder. This avoids to probe for this number with ; shacky BIOS functions or with probing (as LILO does). It's not ; very efficient though.. ; IN dl: drive to read from read_one_sector_from_disk: mov ah, 0x02 ; read sectors from drive mov al, 1 ; read 1 sector mov ch, BYTE [CURRENT_CYLINDER] mov dh, BYTE [CURRENT_HEAD] mov cl, BYTE [CURRENT_SECTOR] int 0x13 jc .read_error cmp al, 1 ; 1 sector read? jne .short_read ; if not, short read mov al, '.' call print_char ret .read_error: mov si, DISK_ERROR call print_string mov dh, 0 mov dl, ah call print_hex jmp $ .short_read: mov si, SHORT_READ call print_string jmp $ kill_motor: mov dx, 0x3F2 mov al, 0x00 out dx, al ret