6

For a project I would like to invoke the MBR on the first harddisk directly from DOS. I've written a small assembler program that loads the MBR in memory at 0:7c00h an does a far jump to it. I've put my util on a (DOS) bootable floppy. The disk (HD0, 0x80) i'm trying to boot has a TrueCrypt boot loader on it. When I run the tool in this setup, it shows up the TrueCrypt screen, but after entering the password it crashes the system. When I run my little utlility (w00t.com) on a normal WinXP machine it seems to crash immediately.

Apparently I'm forgetting some crucial stuff the BIOS normally does, my guess is it's something trivial. Can someone with better bare-metal DOS and BIOS experience help me out?

Heres my code:

.MODEL tiny
.386
_TEXT SEGMENT USE16

INCLUDE BootDefs.i

ORG 100h

start:
    ; http://vxheavens.com/lib/vbw05.html
    ; Before DOS has booted the BIOS stores the amount of usable lower memory 
    ; in a word located at 0:413h in memory. We going to erase this value because
    ; we have booted dos before loading the bootsector, and dos is fat (and ugly).

    ; fake free memory  
    ;push ds
    ;push   0
    ;pop        ds
    ;mov        ax, TC_BOOT_LOADER_SEGMENT / 1024 * 16 + TC_BOOT_MEMORY_REQUIRED
    ;mov    word ptr ds:[413h], ax  ;ax = memory in K
    ;pop ds
    ;lea si, memory_patched_msg
    ;call print

    ;mov ax, cs
    mov ax, 0
    mov es, ax

    ; read first sector to es:7c00h (== cs:7c00)
    mov  dl, 80h
    mov  cl, 1
    mov  al, 1
    mov  bx, 7c00h ;load sector to es:bx
    call read_sectors

    lea si, mbr_loaded_msg
    call print

    lea si, jmp_to_mbr_msg
    call print

    ;Set BIOS default values in environment
    cli
    mov dl, 80h ;(drive C)
    xor ax, ax
    mov ds, ax
    mov es, ax
    mov ss, ax
    mov sp, 0ffffh
    sti

    push es
    push 7c00h
    retf            ;Jump to MBR code at 0:7c00h


    ; Print string
print:
    xor bx, bx
    mov ah, 0eh
    cld

@@: lodsb
    test al, al
    jz print_end

    int 10h
    jmp @B

print_end:
    ret

    ; Read sectors of the first cylinder
read_sectors:
    mov ch, 0           ; Cylinder
    mov dh, 0           ; Head
                        ; DL = drive number passed from BIOS
    mov ah, 2
    int 13h
    jnc read_ok

    lea si, disk_error_msg
    call print
read_ok:
    ret

memory_patched_msg      db 'Memory patched', 13, 10, 7, 0
mbr_loaded_msg          db 'MBR loaded', 13, 10, 7, 0
jmp_to_mbr_msg          db 'Jumping to MBR code', 13, 10, 7, 0
disk_error_msg          db 'Disk error', 13, 10, 7, 0

_TEXT ENDS
END start
Rogier
  • 121
  • 9

3 Answers3

2

Edited -- new answer:

OK, seems like I first misunderstood your question. The only further advice I can give is this:

  • Check that you don't load either HIMEM.SYS and/or EMM386.EXE (nor any other memory manager). The CPU must be in Real Mode when the bootloader executes.

  • Have a look at Ralf Brown's interrupt list. If I remember correctly, there's some technical info somewhere in there about the boot process. It might give you a hint.

  • Look at the source code of other loader utilities, e.g. loadlin. (It doesn't do exactly the same thing as your utility, but might give you some insight, nevertheless.)


Previous answer:

Is ORG 100h really the correct thing to do in a boot loader?

I thought this was just relevant for DOS .com executables, because DOS will initialize the first 256 bytes with the Program Segment Prefix (PSP). If you write a boot loader, there is no DOS, and no such thing as a PSP. I'd suppose this has to be ORG 0.

stakx - no longer contributing
  • 83,039
  • 20
  • 168
  • 268
  • It is a COM file indeed, so that's whys it's ORGed at 100h. Just like any other .com file. It loads the MBR to mem and jumps to is. As you can read in my initial question it actually does the job: the TrueCrypt bootloader gets started and shows the right screen. So loading and jumping works. Only after that, the computer freezes. Something must be wrong, perhaps the environment is not set correctly? – Rogier Apr 14 '10 at 22:16
  • No, even loading a bootloader to address 0:7c00 is not possible in Windows(XP) with this utils. You cannot acces the disk directly from windows and you cannot just go pokin' around in the mem. But please read in my question that i'm running the tool from floppy (image), i.e. it's running in DOS, 16bit real mode. Furthermore is actually does the job partly already; the TC Bootloader GETS started and show the "Welcome to TC, please enter passsword" screen. Only after that it craches. Ergo, there must be something wrong in the environmnt the BIOS normally sets up. – Rogier Apr 15 '10 at 07:10
  • For your informatin, interes, or good nights sleep: When you run such executable under WinXP nothin really happens, Windows complaints a bit about you hacking around on the drive directly and stops the application. – Rogier Apr 15 '10 at 07:13
  • Ok.. thanks for the new answer! Anyway, the memory managers might be the cause of all the trouble as I'm running himem.sys from the boot floppy. I'll give it a try without. As a side note: To me, memory management in DOS is kind of black magic to me; I don't know enough about it (because it's " redundant legacy" knowledge) and not much is to be found about it on the net either... (for the same reason). – Rogier Apr 15 '10 at 23:06
  • Tried without himem.sys still same issue. The funny thing is, it DOES load the MBR. In this case it's the TrueCrypt MBR. This TrueCrypt bootloader actually works, it's able to load its second stage. You can enter a password (it's an ecrypted system volume) but it hangs just before it give over control to the OS laoder (winxp in this case). Any ideas? Maybe some grub devver around? :) – Rogier May 05 '10 at 21:15
2

Ok my DOS knowledge is very rusty and I haven't had the time to test/validate my answer, but I guess your problem is as follows:

When booting DOS or any other OS, they will change the interrupt table. DOS will change the interrupt table so - for example - interrupt 20 can be used to send commands to the DOS "kernel". They do this by saving the original interrupt handler, replacing it by their own handler and afterwards, as a default fallback, chaining to the original interrupt handler if they do not know how to handle the interrupt. This way they "add" new functionality to the already existing bios funcitionality, and every program running under DOS can use the system call by just setting some registers and then calling the interrupt.

However, when you boot a new operating system, this new operating system will assume that a) all interrupts are handled by the bios and b) all memory is free/unused unless reported in use by that bios.

So the new os will overwrite the memory currently in use by your old OS and then it will at some point call one of the interrupts, and will execute something in invalid memory, and your computer will crash.

So, reset your interrupt table to the original bios version and you should be fine...

Peter
  • 963
  • 6
  • 10
0

I don't think this is a boot loader, it's .com file that loads the boot sector and tries to execute it. So it runs after DOS has been initialized.

enix
  • 1
  • 2