First post, by superfury
I'm trying to create a little program for use with my emulator to execute:
- A cold reboot (flush caches, set 40:72 to 0, try and execute hard reset using 8042 chip, try reset by calling interrupt 19h. Error out on fail.). Parameter is /hard.
- A MS-DOS reboot (flush caches, load boot sector into address 7C00, jump to boot sector, error out on fail.). Parameter = /soft.
- A default reboot handler (flush caches, set 40:72 to 0, jump to F000:0).
Although my emulator doesn't handle floppy disk writes correctly atm for some reason (worked perfectly earlier), I already made a program that does that. Cold reboots and default reboot works. Soft reboot fails for some reason? Anyone knows why this happens? It flushes cache by using the assembler method specified in:
https://support.microsoft.com/en-us/kb/67929
It only executes the jump to the BIOS using an inline statement (it jumps to the loaded boot sector data with the /soft flag instead using "inline($EA,$00,$7C,$00,$00);" after having read the sector using interrupt 13h, function 02h. This should work, but instead it's hanging? ).
My source code:
Program reboot;
uses dos;
var
regs: registers;
currentdisk: byte;
disklist: array[0..3] of byte;
currentdisk2: byte;
oldmem: word;
procedure preparereboot;
begin
asm
mov ah,$0D
int $21
mov ax,$40
mov ds,ax
or byte ptr ds:[$17],$0C
mov ax,$4F53
int $15
mov word ptr ds:[$72],$1234
end;
end;
Begin
oldmem := memw[$40:$72];
disklist[0]:=$80;
disklist[1]:=$81;
disklist[2]:=$0;
disklist[3]:=$1;
if (ParamStr(1)='/?') then
begin
writeln;
writeln('Reboot: performs a reboot.');
writeln('Usage: reboot [/hard]');
writeln('/hard: tries to perform a hard reboot, default is soft boot');
writeln('/soft: tries to perform a soft reboot from floppy, then hdd');
exit;
end;
if (ParamStr(1)='/hard') then
begin
fillchar(regs,sizeof(regs),0);
preparereboot;
memw[$40:$72] := 0; (* Hard reboot *)
port[$64] := $FE; (* Try hard reset *)
intr($19,regs); (* Second option: BIOS *)
memw[$40:$72] := oldmem; (* Hard reset instead *)
writeln('Hard reboot failed.');
exit;
end;
if (ParamStr(1)='/soft') then
begin
for currentdisk := 0 to sizeof(disklist)-1 do
begin
fillchar(regs,sizeof(regs),0);
currentdisk2 := disklist[currentdisk]; (* The disk to boot *)
regs.ah := 0;
regs.dl := currentdisk2;
intr($13,regs);
if ((regs.flags and FCarry)=0) then (* Reset? *)
begin
regs.ah := 2;
regs.al := 1;
regs.ch := 0;
regs.cl := 1;
regs.dh := 0;
regs.dl := currentdisk2;
regs.es := 0;
regs.bx := $7C00;
intr($13,regs);
if ((regs.flags and FCarry)=0) then (* Read sector? *)
if ((memw[0:$7dfe]=$aa55) or (disklist[currentdisk]<$80)) then (* Valid to boot? *)
begin
preparereboot;
asm
mov dl,currentdisk2
db $EA
dw $7C00
dw 0
end;
end;
end;
end;
memw[$40:$72] := oldmem; (* Hard reset instead *)
writeln('Soft reboot failed: no bootable disks have been found.');
exit;
end;
preparereboot;
memw[$40:$72] := 0; (* Hard reset instead *)
inline($EA/$00/$00/$FF/$FF); (* Perform hard reset manually. *)
memw[$40:$72] := oldmem; (* Hard reset instead *)
writeln('Hard BIOS reset failed.');
End.
- Reboot.exe without parameters reboots using a cold reboot.
- Reboot.exe with /soft hangs executing (simply blinking cursor on the next row after the command line).
- Reboot /hard executes, waits a bit (emulator resetting it's system), then restarts the BIOS (working correctly).
Anyone knows why the /soft parameter makes the system hang? The sector should be correctly loaded at 0000:7C00 and jumped to? The assembly executes until the jump to 0:7C00 then crashes (doesn't seem to do anything anymore). Anyone knows what I'm doing wrong here?
I'm using the latest x86EMU build to test this program.
Edit: After doing some research: do I need to replace "mov dl,currentdisk2" with "mov dl,[currentdisk2]"?
Author of the UniPCemu emulator.
UniPCemu Git repository
UniPCemu for Android, Windows, PSP, Vita and Switch on itch.io