2

I'm writing a bootloader for educational use and it goes quit well. But when I tried to boot on a real machine my disk read code fails to load some sectors. No error code is given nor is the CF set. It also returns 1 in al which means that 1 sector has been read (which should be correct). But when I try to jump to the loaded sector it just hangs and does nothing.. The first stage prints an A which the second stage overwrites with an F. Only the A is shown when you boot with real hardware. So the sector is not in memory where it should be..

This is my MBR:

LOADOFF equ 0x7C00
BUFFER equ 0x600

[bits 16]
[org 0x7c00]

jmp _start
nop 
    bootdisk db 0

_start: ; entry point
    jmp 0x0:.flush
.flush:
    xor ax, ax
    mov ds, ax
    mov es, ax
    cli
    mov ss, ax
    mov sp, LOADOFF     ; stack setup
    sti

    mov [bootdisk], dl ; boot drive number given by the bios in dl

    mov si, migrate ; move the code below to the buffer
    mov di, BUFFER
    mov cx, 256
    cld
    rep
    movsw

    jmp 0x0:BUFFER ;get my ass in the buffer
migrate:

.reset:
    xor ax, ax      ; reset the disk
    mov dl, [bootdisk]
    int 0x13
    jc .reset

.read:
    mov ah, 0x2
    mov al, 1 ; read 1 sector
    xor cx, cx ; cylinder 0
    mov cl, 2 ; sector 2
    mov dl, [bootdisk]
    xor dh, dh ; head 0


    ; setup buffer
    xor bx, bx
    mov es, bx
    mov bx, 0x7c00 ; chain load it
    int 0x13
    jc .read

    test ah, ah
    jnz .reset

    cmp al, 0x1 ; is there one and only one sector loaded?
    jne .reset

    mov ax, 0xb800
    mov es, ax
    xor di, di
    mov al, 65 ; capital A
    mov ah, 0xc 
    stosw

;   mov ax, 0x7c0
;   mov es, ax
;   xor di, di
;   
;   mov [es:di], byte 191          ; this code proves that my far jump does its work
;   mov [es:di+1], byte 160       ; if you would like to test, comment it out.
;   mov [es:di+2], byte 128
;   mov [es:di+3], byte 184
;   mov [es:di+4], byte 0
;   mov [es:di+5], byte 176
;   mov [es:di+6], byte  142
;   mov [es:di+7], byte 192
;   mov [es:di+8], byte 184
;   mov [es:di+9], byte 88
;   mov [es:di+10], byte 14
;   mov [es:di+11], byte 171

    jmp 0x0:0x7c00      ; execute the loaded sector

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

ORG 0x7C00
[BITS 16]

Stage 2:

    stage2:
    mov ax, 0xb800
    mov es, ax
    xor di, di
    mov al, 70
    mov ah, 0xc
    stosw
    jmp $

times 512 - ($ - $$) db 0

It works perfectly in kvm, but NOT on real hardware with a real bios. I use an USB flash drive to test boot on real hardware.

Could the problem be the BPB which I do not define at the first bytes of my mbr? I don't think so because I just read raw sectors.. correct me if I'm wrong.

Anyone any clue what it could be?

Thanks

Bietje
  • 51
  • 5
  • 2
    I think that, depending on your BIOS, your USB key might not be treated as a floppy drive... Try to search how to boot from a USB device. The process might be different. – Macmade May 12 '11 at 19:04
  • Nope the bios emulates it as an harddisk. I also found out that int 0x13 loads a sector to the correct address, but somehow when I jump to it, it wont execute. – Bietje May 12 '11 at 23:11
  • Although this question is old, I would be curious to know what program was used to place the code on the USB flash drive? Was this done on Windows by any chance? – Michael Petch Dec 01 '15 at 15:51

1 Answers1

2

Your code tries to load from disk 0 which ist "first floppy drive". Modern HDD (and USB flash disks) ususally are accessed as disk 0x80. So just try

bootdisk db 0x80

in your code.

Turbo J
  • 7,563
  • 1
  • 23
  • 43
  • While it wouldn't hurt to hard code the bootdisk variable to 0x80 to make sure the BIOS is sane, it does look like @Bietje is doing the correct thing by moving bl (which should contain the device number of the currently booted device) in to the variable first. – Rose Lynn Embry Jun 13 '11 at 20:11
  • 1
    Or better, use the value passed to the bootloader by the BIOS itself in the DL register. It is supposed to be the number of the drive the bootsector has been loaded from by the BIOS. It just leaves that number there after loading the bootsector using its own interrupt 13h. After that the value just remains in DL and the bootloader can use it to know which drive it has been boot from. – SasQ Feb 05 '15 at 05:03
  • 1
    Also, if you want your bootloader to be independent of the device it is booted from, use that value from DL in a call to int 13h function 08h to get the geometry of the drive. It could be different from the standard 80:2:18 CHS geometry of the floppy disk if you boot from HDD or a pendrive, for example. – SasQ Feb 05 '15 at 05:07