0

I’m currently developing an operating system for a class. The OS boots fine on both real hardware and QEMU. However, I need it to boot on either Virtualbox or DOSBox as I’m working on getting Soundblaster 16 support working. I need to use direct mode, but QEMU only supports DMA transfers on the Soundblaster. I’m booting in qemu with:

qemu-system-i386                                 \           
  -cpu "SandyBridge-v2"                          \
  -m 256M                                        \
  -no-reboot                                     \
  -drive format=raw,file=usb.image               \
  -serial stdio                                  \
  -smp 1                                         \
  -usb                                           \
  -vga std                                       \
  -soundhw sb16

DOSBox can handle my img file directly, but Virtualbox needs a VMDK. I’m creating a VMDK file that maps to the raw IMG with:

VBoxManage internalcommands createrawvmdk -filename OS.VMDK -rawimage os.img

In both cases, the boot loader I was given fails in this section of code:

/*
** Read one complete program block into memory.
**
**  ax: number of sectors to read
**  es:bx = starting address for the block
*/
readprog:
    pushw   %ax     /* save sector count */

    movw    $3,%cx      /* initial retry count is 3 */
retry:
    pushw   %cx     /* push the retry count on the stack. */

    movw    sec,%cx     /* get sector number */
    movw    head,%dx    /* get head number */
    movb    drive, %dl

    movw    $0x0201,%ax /* read 1 sector */
    int $0x13
    jnc readcont    /* jmp if it worked ok */

    movw    $err_diskread,%si /* report the error */
    call    dispMsg
    popw    %cx     /* get the retry count back */
    loop    retry       /*   and go try again. */
    movw    $err_diskfail,%si /* can't proceed, */
    call    dispMsg     /* print message and freeze. */
    jmp .

The drive is initialized like this:

/* get drive parameters to determine number of heads and sectors/track */
    xorw    %ax, %ax    /* set ES:DI = 0000:0000 in case of BIOS bugs */
    movw    %ax, %es
    movw    %ax, %di
    movb    $0x08, %ah  /* get drive parameters */
    movb    drive, %dl  /* hard disk or floppy */
    int $0x13

My guess is that the virtual motherboard in both Virtualbox and DOSBox is configured incorrectly, either not responding to interrupt 0x13 properly or has an offset set incorrectly that is causing the bootloader to attempt to pull in wrong or garbage data. In DOSBox and Virtualbox, the bootloader prints out:

Read failed
Read failed
Read failed
Can’t proceed

The OS itself is printing that from the snippet of code I provided, not Virtualbox or DOSBox

Michael Petch
  • 46,082
  • 8
  • 107
  • 198
Alex
  • 724
  • 1
  • 9
  • 24
  • 1
    How is `drive` initialized? – Margaret Bloom Apr 29 '20 at 07:27
  • @MargaretBloom Added to the original question – Alex Apr 29 '20 at 20:49
  • 2
    You don't show the code where `drive` is initialized (set with its initial value) which I assume is done near the beginning of the bootloader. Some people incorrectly save the value in `dl` before setting the segment register(s) like DS, or they rely on the value in CS being 0 and then copy it to DS ((you can't assume any segment is correct). It is also unclear if you set up a stack (SS:SP)so you don't inadvertently load a sector on top of the existing stack (there is a default one set by BIOS). What would help is if you would show a [mcve] showing all the code for the bootloader to reproduce – Michael Petch Apr 29 '20 at 22:49

0 Answers0