Bootloader works in emulators but not on real hardware
Asked Answered
B

1

6

I am writing a bootloader in assembly and it seems to work fine on qemu, bochs and virtualbox. However, it is not loading the kernel on real hardware (it seems).

The bootloader starts off by writing a character to the video memory (for debugging), it then reads sector 2 off the drive and far jumps to the kernel. The kernel is then writing some characters to video memory.

On a real machine, I see the character from the bootloader on the screen, and there it hangs (blinking caret).

I have tried to set DS, ES, SI to zero, and I am also setting up a stack segment.

I am reading sector 2 off of the drive using bios int 13 function 2. I kind of suspect that it has something to do with the drive number. I have both tried to use the drive number passed to the bootloader on startup (in dl), and setting it manually to 0x0, 0x80 and 0x81.

One strange thing I noticed is that the labels I use to near jump, magically gets the correct address. Using objdump I see for example: jmp 0x2, while using gdb and qemu, it says: jmp 0x7c02. CS and all the other segment registers are zero. Whether I use -Ttext 0x0 or -Ttext 0x7c00 in the linking, the bootloader works fine on all the emulators. objdump says jmp 0x7c02 when I link with -Ttext 0x7c00.

EDIT, the bootloader looks like this:

.code16
.text
movw $0xb800, %ax
movw %ax, %ds
movw $0x0741, (0x0)

xorw %ax, %ax
movw %ax, %ds
movw %ax, %si
movw %ax, %es

movw  $0x8000, %ax
movw  %ax, %ss
movw  $0, %sp

movb $2, %ah
movb $1, %al
movw $0x02, %cx
movb $0x00, %dh

movw $0x5000, %bx
movw %bx, %es
movw $0x0, %bx
int $0x13

ljmpw $0x5000, $0x0000

Edit, Second stage:

.code16
.text
    movw $0xb800, %ax
    movw %ax, %ds
    movw $0x0742, (0x2)

forever:
    jmp forever
Buckbuckaroo answered 28/1, 2017 at 15:39 Comment(11)
Near jumps will work if relative jumps are used for them.Irrelevant
I am sorry, but we cannot really help you with that little information. Can you perhaps make a second bootloader with just enough code to demonstrate the issue at hand and show this to us?Fuqua
Try to solve it by splitting into smaller parts. If you print a character before load of sector 2, print another one after this loading (and differ it whether read call returned error). Compare your code with available opensource boot loaders; maybe they do some setup you missed. Have you followed Ralf Brown Interrupt List to make proper setup before calls?Tasimeter
You should check for an error code and maybe print another character on error. Also show the start of the second sector loaded. Obviously also make sure said 2nd sector is actually written to your physical device, maybe print a character from it before jumping to it.Unarmed
-Ttext 0x0 and -Ttext 0x7c00will only work the same if there are no near absolute references to labels. If your bootloader code were to have an instruction where there was such a reference it would not work in a bootloader unless -Ttext 0x7c00 is used. If you were to create a string in the bootloader and tried to move the address to the start of it into a register that would be such an example. (ie movw $mystring, %di)Cheltenham
Near JMPs are not absolute, they are relative. So the VMA(origin) will not matter.Cheltenham
So near jumps will not jump relative to CS then?Buckbuckaroo
I'd like to see your second stage code, would appreciate if you would show it to us. Quite possible your code is being loaded in memory and jumped to but that code is a problem.Cheltenham
Near jumps are always in the same segment (CS). Near jumps are encoded as a displacement from the start (offset) of the next instruction not a fixed offset in memory. What base address (offset) the code started at isn't relevant.Cheltenham
movw $0x074b, (0x1) seems wrong. Each cell is 2 bytes. Did you mean movw $0x074b, (0x2)?Cheltenham
A recommendation though. Keep DS so it matches CS so regular memory address operands that default to DS will do what you expect. Instead place 0xb800 in ES and then do memory accesses with a segment override like movw $0x74b, %es:(0x02)Cheltenham
C
5

If your hardware is using floppy disk emulation for the USB drive it may be possible that without a proper BIOS Parameter Block (BPB) in your MBR that it is failing to boot properly. Many BIOSes will attempt to detect a BPB at the start of the bootloader and may even update the values with proper drive geometry after the bootloader is loaded into memory. It is possible your bootloader was not being detected as a proper bootable drive or it was but the BIOS overwrote some of your code with drive geometry information before executing it.

The following adds a BPB that happens to look like a 2.88MB floppy.

.global _start
.code16
.text

_start:
    jmp     main
    .space 3 - (.-_start)

    /* Configuration for a 2.88MB floppy using FAT 12 */
    OEMname:            .ascii      "MYBOOT  "
    bytesPerSector:     .word       512
    sectPerCluster:     .byte       1
    reservedSectors:    .word       1
    numFAT:             .byte       2
    numRootDirEntries:  .word       240
    numSectors:         .word       5760
    mediaType:          .byte       0xf0
    numFATsectors:      .word       9
    sectorsPerTrack:    .word       36
    numHeads:           .word       2
    numHiddenSectors:   .long       0
    numSectorsHuge:     .long       0
    driveNum:           .byte       0
    reserved:           .byte       0x00
    signature:          .byte       0x29
    volumeID:           .long       0x54428E71
    volumeLabel:        .ascii      "NO NAME    "
    fileSysType:        .ascii      "FAT12   "

main:
    movw $0xb800, %ax
    movw %ax, %ds
    movw $0x0741, (0x0)

    xorw %ax, %ax
    movw %ax, %ds
    movw %ax, %si
    movw %ax, %es

    movw  $0x8000, %ax
    movw  %ax, %ss
    movw  $0, %sp

    movb $2, %ah
    movb $1, %al
    movw $0x02, %cx
    movb $0x00, %dh

    movw $0x5000, %bx
    movw %bx, %es
    movw $0x0, %bx
    int $0x13

    ljmpw $0x5000, $0x0000

.space 510-(.-_start)
.word 0xaa55
Cheltenham answered 29/1, 2017 at 10:11 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.