Using Linux+dosemu to install Windows

Patrick J. LoPresti
2002-07-26T03:50:40Z

I am sorry this is so long. Executive summary: I would like some
guidance to produce a patch to improve dosemu. Skip to the end for my
actual question.

As you may (or may not) know, Windows NT/2000/XP installation CDs
include a 16-bit DOS application i386\winnt.exe which starts the
installation of the operating system. All this application does is
copy a bunch of stuff to the hard drive and reboot the machine.

I want to perform unattendend installations of Windows over the
network. But instead of mucking about with DOS network drivers, I
thought it might be fun to try using a bootable Linux CD and dosemu to
run the winnt.exe installer.

But I hit a snag. Running winnt.exe causes dosemu 1.1.3 to abort like
this:

ERROR: general protection at 0xbbca: 67
ERROR: SIGSEGV, protected insn...exiting!

This error comes from the vm86_GP_fault() function in
src/i386-emu/do_vm86.c. By instrumenting the code a bit, I learned
that winnt.exe is attempting to invoke the pushfd and popfd
instructions (opcodes 0x9c and 0x9d, respectively), which dosemu does
not support.

All winnt.exe is really doing is trying to determine whether the
processor is a 486 or higher. It does this by using pushfd and popfd
to attempt to alter the next-to-highest bit of the EFLAGS register.
On the 386 and earlier, this attempt fails, because the bit was
reserved back then and was always zero.

I figured this out after I wrote stub handlers for opcodes 0x9c and
0x9d, which allowed dosemu to run winnt.exe until the latter explained
that "Windows 2000 requires a 486 or higher; setup will exit now".

I have tried to figure out how to modify EFLAGS from within
vm86_GP_fault(), but so far I am finding this difficult. Assigning to
REG(eflags) does not appear to work. I have hacked my stub handlers
to simply return what winnt.exe expects, and this actually allowed
winnt.exe to proceed to the end and "reboot" the dosemu box (i.e., it
worked). But I would like to do this right and get it into the stock
dosemu distribution.

So, my question boils down to this: How can I modify the EFLAGS
register from within vm86_GP_fault()? If someone will tell me this, I
will submit a patch to add support for emulating the pushf/pushfd and
popf/popfd opcodes.

Thanks!

- Pat