Page 1 of 1

How to load kernel to address 0x10,1000 in 16 bit real mode

Posted: Mon Feb 09, 2015 6:32 pm
by markq
Hello,

I have successfully load my kernel to address 0x1000 and 0x10,000. But when I try to load into address 0x10,1000, The incorrect value gets loaded. Below code demonstrates what I am doing. It first loads from a CD by using the 0x42 function to read the cd descriptor address packet which wants the bios function to load sector 17 at offset 0x2000 and segment 0xff00 (since 0xff00:0x2000 = 0x10,1000). This should load to address 0x10,1000 but I dont get the correct value. i was able to correctly load to addresses like 0xff:0x2000, 0xff0:0x2000 but not 0xff00:0x2000. Is there something wrong with what I am doing? Could it be that BIOS can't reach that deep into memory because it's still in 16 bit real mode?

Code: Select all

BootCatalogSectorOffset equ 0x47
BootLoaderOffset equ 0x28    

mydisk_load:
    pusha

    ; Load CD descriptor at sector 17
    mov si, DescriptorAddressPacket
    mov ah,0x42			
    int 0x13
    jc disk_error

    ; Get boot catalog sector offset
    ;; since the descriptor was loaded to 0xff00:0x2047
    ;; that means I need to add it to get the physical location of boot catalog offset
    mov bx, 0xff00
    mov es, bx

    mov bx, [es:0x2047]

    push dx
    mov dx, bx
    call print_hex        ;should print 0x0040 but it prints 0x0000
    pop dx
    
    popa
    ret

disk_error:
    mov bx, DISK_ERROR_MSG
    call print_string
    jmp $

success:
    pusha
    mov bx, DISK_SUCCESS_MSG
    call print_string
    popa
    ret

DescriptorAddressPacket:        
DescriptorSize:		db 0x10		;size of packet
DescriptorZero:	        db 0			;always 0
DescriptorTransfers:	dw 1		;number of sectors to read
DescriptorOffset:   	dw 0x2000	;offset
DescriptorSegment:     dw 0xff00        ;segment
DescriptorSector:   	dd 17		;starting LBA #
DescriptorUpper:    	dd 0   		;used for upper part of 48 bit LBAs

Re: How to load kernel to address 0x10,1000 in 16 bit real m

Posted: Mon Feb 09, 2015 8:46 pm
by CelestialMechanic
Have you enabled A20?

Re: How to load kernel to address 0x10,1000 in 16 bit real m

Posted: Mon Feb 09, 2015 8:54 pm
by markq
CelestialMechanic wrote:Have you enabled A20?
I have not enabled A20. I thought enabling A20 is during 32-bit mode? (edit: I have check with the code found at http://wiki.osdev.org/A20_Line that A20 seems to be enabled by default)

Re: How to load kernel to address 0x10,1000 in 16 bit real m

Posted: Mon Feb 09, 2015 11:08 pm
by Octocontrabass
markq wrote:Is there something wrong with what I am doing?
The BIOS can only access the first 640kB of RAM using segment:offset notation (minus the EBDA, which you should never modify). You also need to make sure A20 is enabled before using anything above 0xFFFFF.

Typical bootloaders will load data within the first 640kB and then switch to protected mode (or use unreal mode) to copy data above 1MB, switching back and forth as necessary.

As a possible alternative, some BIOSes support an extension to the Disk Address Packet that specifies a 64-bit linear address instead of a segment:offset address. If you're not worried about backwards-compatibility, this is probably the easiest option.