Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Problem reading many sectors #245

Open
GodToRun opened this issue May 21, 2022 · 2 comments
Open

Problem reading many sectors #245

GodToRun opened this issue May 21, 2022 · 2 comments

Comments

@GodToRun
Copy link

Hi, there is a problem with increasing the number of sectors that the kernel needs to read as it grows. If the number of sectors read (dh) is greater than 62, only Loading kernel into memory appears and the kernel is not loaded. I tried to increase the memory, but it didn't work. Here's the code.

bootsect.asm

KERNEL_OFFSET equ 0x1000
mov [BOOT_DRIVE], dl
mov bp, 0x9000
mov sp, bp
    
call load_kernel
call switch
jmp $
%include 'boot/gdt.asm'
%include 'boot/io32.asm'
%include 'boot/io.asm'
%include 'boot/switch32.asm'
%include 'boot/disk.asm'

[bits 16]
load_kernel:
    mov bx, MSG_LOAD_KERNEL
    call print
    call print_nl
    mov bx, KERNEL_OFFSET
    mov dh, 62
    mov dl, [BOOT_DRIVE]
    call disk_load
    ret
[bits 32]
begin:
    mov esi, msg
    call print32
    call KERNEL_OFFSET
    jmp $
msg db 'Now we are actually protected mode!',0
MSG_LOAD_KERNEL db "Loading kernel into memory", 0
MSG_REAL_MODE db "Started in 16-bit Real Mode", 0

BOOT_DRIVE db 0

times 510-($-$$) db 0
dw 0xaa55

disk.asm

[bits 16]
; load 'dh' sectors from drive 'dl' into ES:BX
disk_load:
    pusha
    ; reading from disk requires setting specific values in all registers
    ; so we will overwrite our input parameters from 'dx'. Let's save it
    ; to the stack for later use.
    push dx

    mov ah, 0x02 ; ah <- int 0x13 function. 0x02 = 'read'
    mov al, dh   ; al <- number of sectors to read (0x01 .. 0x80)
    mov cl, 0x02 ; cl <- sector (0x01 .. 0x11)
                 ; 0x01 is our boot sector, 0x02 is the first 'available' sector
    mov ch, 0x00 ; ch <- cylinder (0x0 .. 0x3FF, upper 2 bits in 'cl')
    ; dl <- drive number. Our caller sets it as a parameter and gets it from BIOS
    ; (0 = floppy, 1 = floppy2, 0x80 = hdd, 0x81 = hdd2)
    mov dh, 0x00 ; dh <- head number (0x0 .. 0xF)

    ; [es:bx] <- pointer to buffer where the data will be stored
    ; caller sets it up for us, and it is actually the standard location for int 13h
    int 0x13      ; BIOS interrupt
    ;jc disk_error ; if error (stored in the carry bit)

    pop dx
    cmp al, dh    ; BIOS also sets 'al' to the # of sectors read. Compare it.
    jne sectors_error
    popa
    ret


disk_error:
    mov bx, DISK_ERROR
    call print
    call print_nl
    jmp disk_loop

sectors_error:
    mov bx, SECTORS_ERROR
    call print

disk_loop:
    jmp $

DISK_ERROR: db "Disk read error", 0
SECTORS_ERROR: db "Incorrect number of sectors read", 0
@nocturn9x
Copy link

AFAIK You can't read more than 62 sectors because that's the hard limit of what you can do in real mode

@epic-coder-64
Copy link

epic-coder-64 commented Jun 10, 2023

You can read more sectors, the hard limit in a single interrupt is 127* sectors. However, qemu believes your disk is 512 bytes long because that is how long your boot sector is (or more if you have a kernel). You can use a quick hack to counteract this:

$ touch zero.asm
$ cat "times 65536 db 0x00" > zero.asm
$ nasm -f bin zero.asm -o zero.bin
$ rm zero.asm

You can then modify your Makefile so it runs cat bootsect.bin kernel.bin zero.bin > os-image.bin instead of just bootsect.bin and kernel.bin.

*Technically, it is 128, but I assume you don't want to reload your boot sector again

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

3 participants