1

Edit: PLEASE. FOR THE LOVE OF GOD. REMEMBER TO ADD [BITS 16] IF YOU ARE EXECUTING IN REAL MODE. IT WILL SAVE YOU.

I'm trying to get the BIOS to read in a little section from the disk and execute it. So far I have

; Boot sector if you didn't know. The entire purpose of this is to jump to protected mode setup (PMS)
%define BIOS_ERROR_FREQUENCY 440
%define ERR_LBA_NOT_FOUND    1
%define ERR_BIOS_WRITE       2

extern BIOS_BLOCK_SIZE
extern boot_sector_e
extern pms_s
extern pms_e
extern pms_number_of_blocks

section .boot
    ; Check if the BIOS supports LBA
    mov ah, 0x41
    mov bx, 0x55AA
    ; dl has already been set to the boot drive
    int 0x13
    ; Error handle
    mov al, ERR_LBA_NOT_FOUND
    jc boot_error

    ; If it does support LBA, we read in PMS to memory and start executing it
    mov ah, 0x42
    ; dl already set
    mov si, bios_lba_packet_s
    int 0x13
    mov al, ERR_BIOS_WRITE
    jc boot_error
    jmp pms_s
    ; Please note that this will overwrite and read extra from the disk. We don't know what this is however, we can just ignore it :)

    ; Misc
    bios_lba_packet_s:
    db bios_lba_packet_e - bios_lba_packet_s ; Size
    db 0 ; Reserved
    dw pms_number_of_blocks
    dw boot_sector_e ; Offset of transfer buffer location
    dw 0x0 ; Section
    dq 0 ; Starting block. We have the ability to hardcode this because it's at the set position of one sector off (boot sector is 0)
    bios_lba_packet_e:

    boot_error: ; Will just print out a upon error
        mov ah, 0x0E
        mov al, "a"
        int 0x10
        jmp $

section .boot-header
    dw 0xAA55 ; 55AA tells the BIOS that this is bootable (reversed because of endians)

and

section .pms
    mov ah, 0x0E
    mov al, "w"
    int 0x10

which is what I want to load in and will simply just print out "w" upon working

and I link that together with

SECTIONS {
    .boot ORG : {
        boot_sector_s = .;
        *( .boot );
    }
    . += BIOS_BLOCK_SIZE - boot_header_size - boot_size;
    .boot-header : {
        *( .boot-header );
        boot_sector_e = .;
    }
    
    .pms : {
        pms_s = .;
        *( .pms );
        pms_e = .;
    }
}
/* Constants */
BIOS_BLOCK_SIZE = 512;
ORG = 0x7C00;

boot_size = SIZEOF( .boot );
boot_header_size = SIZEOF( .boot-header ); /* This has be defined after the .boot-header section has been defined (it's weird, I know) */
pms_number_of_blocks = ((pms_e - pms_s) + BIOS_BLOCK_SIZE) / BIOS_BLOCK_SIZE;

I've dumped out the memory and the loaded in section has not been found. I also checked the carry flags and they were not set. Could it have something to do with my final binary not having padding in order to make the section I want to load in be a full 512 bytes?

JustFast
  • 67
  • 7
  • 2
    Are you sure DS is what you think it is? [Rumor has it](https://stackoverflow.com/questions/43359327/default-registers-and-segments-value-on-booting-x86-machine#comment73781273_43359327) that you shouldn't make assumptions about what's in the registers at bootloader time (other than DL). – David Wohlferd Nov 07 '21 at 04:11
  • dl is 0x80 which is the default HDA & ds is 0x0. – JustFast Nov 07 '21 at 04:13
  • 1
    `dq 0` means you will load the first sector. – ecm Nov 07 '21 at 08:14
  • yeah i tried it with ```dq 0``` and ```dq 1``` and to no avail – JustFast Nov 07 '21 at 17:36

1 Answers1

2

The fact that the InstallationCheck function 41h reported CF=0 does not mean everything.
You still need to verify that BX=AA55h to see if the IBM/MS INT 13 Extensions are indeed installed.
And check the SubsetSupportBitmap in CX. If bit 0 of CX is set then the ExtendedRead function 42h is supported.

pms_number_of_blocks = ((pms_e - pms_s) + BIOS_BLOCK_SIZE) / BIOS_BLOCK_SIZE;

This will set your pms_number_of_blocks to just 1. You need to set the StartingAbsoluteBlockNumber to 1 instead of 0. (0 would be re-reading the boot sector.)

bios_lba_packet_s:
db 16
db 0
dw pms_number_of_blocks
dd 0:pms_s
dq 1

Could it have something to do with my final binary not having padding in order to make the section I want to load in be a full 512 bytes?

Go ahead and pad it! You should always do that anyway.


  • Strange to see "ERR_BIOS_WRITE" reported on a function that reads.

  • The BIOS.Teletype function 0Eh uses the BH DisplayPage parameter. Set it to 0.

      section .pms
          mov  bh, 0
          mov  ax, 0x0E * 256 + "w"
          int  0x10
          times (512 - 7) db 0
    
  • BIOS only passes you the bootdrive in the DL register. Nothing else! Don't trust any particular setting of the segment registers. Set DS=0 expressly.

  • Always setup a stack in a safe place. Here set it up beneath the bootsector:

      xor  ax, ax
      mov  ds, ax
      mov  ss, ax
      mov  sp, 0x7C00
    
Sep Roland
  • 33,889
  • 7
  • 43
  • 76