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
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
.
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...
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With