Rebooting from user-space

2004-03-13

On the mailing list, we had a discussion about "safe" rebooting of a PC through the BIOS.

First:

True that once long time ago it was discussed that the rebooting method of jumping to certain BIOS point wasn't "safe" in the sense that wasn't portable across BIOSes, but it was soooo long time ago that I may be wrong. Thanks.

The reply.

Well, it _always_ was sefe and documented to jump to ffff:0, but at the time people were finding "better" ways of doing it.

Matthias Paul adds this useful explanation:

Actually, as long as we take only DOS into account, it is still almost safe today.

However, a few extra precautions are necessary since the introduction of the PC/AT. Unfortunately, most books do not mention this explicitly, that's why you find many sources in the net, which still do it wrong, that is, explain only the original PC/XT method.

Before you may jump to FFFFh:0000h on any AT class machine (or on an XT which implements INT 15h/AH=4Fh) you *must* manually set the CTRL+ALT flags in the keyboard flags in the BIOS data segment 0040h, and then issue an INT 15h/AH=4Fh with the DEL scancode as argument. This Real Mode broadcast will be intercepted by a multitude of software and allows them to prepare for the reboot, for example, disk caches may write out dirty cache data (that's why any disk cache providing defered writes must hook INT 15h/AH=4Fh), a network server may shut down, memory management software may hook this function in order to bring the machine back into Real Mode (from V86 mode) or prepare EMS hardware for a reboot, and DOS will restore its hooked hardware interrupts to the original vectors found during bootstrap, invalidate the VDISK header at the start of the HMA and issue an INT 19h in order to pass control down to the System BIOS.

NB. An INT 19h must not be issued before the hardware interrupts are restored, otherwise the system will hang instead of rebooting - that's why most books are plainly wrong when suggesting that INT 19h would be some easy and portable means to reboot - it /is/, but only under /some/ circumstances, and these circumstances are almost never met once DOS has booted, so INT 19h is reserved for use by DOS and boot sectors only. And since (only) DOS itself can do the necessary clean-ups first, INT 19h will actually work then.

NB. Simply jumping to FFFFh:0000h will still work in most cases, but only because a memory manager such as EMM386 traps this and does the necessary cleanups. If you are in plain Real Mode (as common in pre-386 times), not calling INT 15h/AH=4Fh first may cause serious loss of data, as resident software has no chance to intercept and defeat or defer the reboot.

So, if all goes well, issuing the INT 15h/AH=4Fh from within an application will never return. If it still does, the application should - depending on the return code and purpose of the reboot - either retry, execute "CLI, JMPF FFFFh:0000h" by itself, go into a tight "loop: CLI, HLT, JMP loop" waiting for the user to press the reset button, or simply give up the attempt to reboot. It is possible to further improve this basic plot by issuing a few disk reset and cache flush calls itself, but I left them out of the description above in order not to complicate things. MS-DOS/PC DOS KEYB BTW does basically the same thing when you actually press CTRL+ALT+DEL. It sets the BIOS flags and then issues the INT 15h/AH=4Fh with the DEL scancode. If this returns, it jumps to FFFFh:0000h itself. Newer issues of KEYB (and FREEKEYB) attempt to flush disk caches first either by directly calling their cache flush API functions, or by ignoring the final DEL key press until after the queried cache API indicates that the cache no longer has any dirty elements.

Actually, that's how it should be done since about 1984 - any other method tried from user space should be considered less portable and potentially dangerous. Unfortunately, in some cases, issuing INT 15h/AH=4Fh will hang instead of rebooting, but in these cases, if you track down the problem you will find, that one of the drivers hooking INT 15h/AH=4Fh is buggy and does not handle it correctly, so it should be fixed or removed. This does not compromise the general picture.

Matthias