Improved the packet server a bit. The loopback now has an extra flag for handling detected default gateway routing.
Now the receiver checks for normal IP addresses first, and if that fails it resolves to the default gateway IP, if not from the host network (pcap).
Connected clients can now actually perform as a default gateway (using IP and subnet mask unconfigured with IPCP, thus both being 0.0.0.0).
The default gateway will route any packets it sends to that client if it detects one using those settings (although only one client is allowed with such a setting).
And the configured default gateway on the host network (if not loopback isn't enforced) will of course override it.
But the default gateway can only be for one client at a time.
So if you want a specific default gateway with a specific IP address, you need to connect with one dial-up connection for the normal IP connection (the direct connection for TCP/IP requests) and connect using a second modem with the default gateway to handle that. It will then receive/send normal packets over the first connection. The second connection sends the same, but receives all packets for the default gateway only.
Of course, combining the two will provide a full router: one IP address (or range) with it's directed packets or broadcasts, one adapter that just receives the packets for the default gateway.
So for example, on Dosbox this can be done by using two serial modem dial-up connections at the same time, one requesting automatic IP address (with subnet mask setup for the network), the other connection handling the default gateway for receiving only (and sending just as the default gateway incoming data).
Of course, UniPCemu's server only will allow one such a default gateway being connected, others are simply denied their IP/subnet combination (and giving the client a non-zero IP address).
Also, if UniPCemu's server has a default gateway client connected but a default gateway on a host machine is configured to use (the default gateway MAC field), that default gateway gets prioritized (routing there instead).
The default gateway only gets handled of course for outgoing packets from unmatching IP addresses from it's clients (it doesn't handle the actual host's defaults gateway for such a default gateway client).
Basically, it's only used when the default gateway isn't configured, the rules for the clients not matching any clients and one client has a default gateway IP/subnet combination (being 0.0.0.0/0 actually).
OK. Windows XP home still crashes.
Looking at the address of the first parameter, I find:
44 00 46 00 80 38 12 E1
Then that's followed by the following string(using C syntax here): "\\ArcName\\%s" (zero terminated).
So it's trying to load some data from disk with a sprintf input? So is some sprintf function failing somehow (it almost looks like that's the case)?
So some kind of string parsing error?
The STOP error is still the same (7B,0xFC90E63C,0xC000...,0x0...,0x0...)
Perhaps I should look into that string pointed to (address E1123880)? That should be the unicode string (length 44h out of 46h bytes? Perhaps a buffer overflow?). So it's length is 68 out of 70 bytes available.
So I can specify some load options to load the kernel of the setup phase?
To be specific: OsLoadOptions , which might support debugging the kernel? https://techshelps.github.io/MSDN/DNWINNT/HTML/D1E/S833A.HTM
So that'd be: "/fastdetect /noguiboot /nodebug /debug /debugport=COM2 /BAUDRATE=57600".
Then run the OS with that and a debugger on a serial loopback connected to UniPCemu (just like I did earlier with putty+COM0COM debugging NT4's kernel).
Next, configure UniPCemu for nullmodem mode 4 (simple nullmodem with dial out without handshake), to make it connect using phonebook entry #0 to the packet server build (like dialling out on a modem, but when it gets DTR set/cleared(hangup) instead).
The packet server build then is performing an IPv4 TCP port to serial passthrough (using COM0COM).
COM0COM then loops back into another virtual serial port.
Putty then connects to said virtual serial port and receives/sends data to the OS listening to the serial port inside UniPCemu.
The exact same setup I used when debugging NT4. Only this time with a newer Windows NT version (XP home).
If Windows actually uses the serial port (and raises DTR), I should see something happening on the connected Putty terminal 🤣.
Just modified the UART receiver buffer to no more being able to get stuck if receiving data, allowing incoming data from hardware to be received.
Although this allows the connected hardware interface to keep sending data and overflow the buffer (if enough time passes for the data to be received), but it will prevent some external protocols from getting stuck (like the Dosbox-compatible serial line handshakes when routed over the TCP connection).
Fixed some dialing out issue when the TCP connection was being set up. The TCP asynchronous dialling was being started to make a connection, but after the time it detected the raising of the DTR line on the client it wouldn't update the dialling process anymore.
Now the main connection handling (which is timed like normal data bytes) performs said check too, calling the linde update function to make it continue the dialling process to connect correctly.
Edit: Fixed some more issues relating to hanging up too.
OK. Observing communication, I see Windows XP home's detecting hardware (before blue screen when loading drivers) sending 3 bytes saying "DSs" over the serial line a few times.
It's receiving "iiii\x06" followed by 11 zeroes. Or 69h times 4 06h times 1 00h times 11.
It (windbg) keeps sending such a packet over and over while windows is loading.
Interestingly enough, 69h is 0110 1001 when in binary. Perhaps some kind of synchronization.
Then 06 is 0000 0110.
So all in all:
"0110 1001 0110 1001 0110 1001 0110 1001 0000 0110" is the packet being received on the Windows XP home side.
OK. Some bugfixes on the serial connection later, I now get a proper connection between the host (Windows 10 running windbg) and the client (inside UniPCemu, running Windows XP home build 2600).
Output that's running inside WinDBG for Windows 7.1 (the only version compatible with that Windows XP builf afaik):
And of course with all this new functionality, something had to break.
Found an issue in the UART that caused errors to be cleared, but not re-detected when a new error occurs (even if the line status register is read to reset said flags). In this case the line status change wasn't detected, thus any handling of the line status register changes wouldn't properly re-trigger as they should.
Now buffer overflow correctly still sets the two bits (overrun error and data ready) when such a overrun happens. Then, once the line status register is read, it's cleared as usual, but now updating the line status difference data properly to update the triggering of new changes if an error is set again.
Noticed said bug when I was trying to view a memory address from the debugger (the structure containing the unicode path and size/length data for the 7B stop code handling's documentation).
OK. It's probably called IopInitializePlugPlayServices (80968aa8). After that, a TEST EAX,EAX triggers a jge to the call IopInitializeBootDrivers. That function has just ran IopCreateArcNames, doing something with the partition table next I think it said. Unfortunately, when investigating further the above bugs popped up inside UniPCemu's UART, so I need to start again.
Luckily I know where to look this time (although it's still a very slow connection at 57600 baud).
Now if it detects two samples being used, it'll still play the samples on two channels (each with their own samplerate).
But if it detects a mono sample for a note, it'll now optimize the channel to only use the left channel that was reserved to play the mono sample, panned into the stereo field.
The other channel (for the right sample) that was reserved will simply not be active for such a mono sound (as it's identical).
Fixed some CPU/BIU issues causing the emulation to lock up (not progressing) when waitstates are performed during a HALT or related cycle.
Now the BIU proceeds to finish it's active cycles until it's properly ready.
Edit: The AT now POSTs again. Although perhaps giving an error (video output failing a bit) because the CMOS isn't setup.
And fixed the MDA and compatiblity modes to properly setup the video RAM memory mapping to compatible values (the RAM appearing at the correct location for the CPU to access). It was incorrectly setup for RAM location A0000-AFFFF, which is of course incorrect behaviour.
Although I forgot to connect the debugger beforehand, I did open UniPCemu's debugger and looked at the string that it's trying to boot:
The structure at FC90E63C:
44 00 (string length)
46 00 (
e111f5d8
e111d5d8 points to a string:
"\ArcName\multi(0)disk(0)cdrom(159)" in Unicode format (2 bytes/character, every second byte is zeroed, zero-terminated).
The CD-ROM drive is located at the secondary master in the emulation setup, on the i440fx onboard IDE device.
Is 159 correct for CD-ROM booting? what about disk(0)?
Fixed an issue found in the 386+ 0F opcode information tables. The SHLD r/m16,r16,CL instrution (opcode 0FA5) used an invalid special handling parameter on it's modr/m settings.
Although it should have no effect on the emulation, as the value of 1 is ignored by the current implementation of modr/m from what I can see.
Some more progress on the Windows XP home crash:
FC9BB62D: Reached when a byte is received.
Sets FC9BBD79 to FFh when received.
Jmps to FC9BB7A4.
FC9BB876 reached.
FC9BB87A reached for no error.
FC9BB93A function called from some table?
Jmps to FC9BBCF8.
Jumps dynamically to 80197E5C (the ntos kernel module?).
Function selects I/O port 2F8, reads it and returns.
So function 80197E5C is the read function for reading data from the serial port at least (AL=result, EDX=port).
Data received is stored at BP+13 (FC90D98C+13).
FC9BB8C4 reached.
Some ptr into EAX (FC90D9B2), byte received into CL. Store it there.
Jumps to FC9BB8B1.
Returns to caller.
Zero extend AX(FC900000) to EAX to clear.
Return to caller.
@FC9BBE32.
@FC9BBE41: Read the read data from the I/O port into AL.
30h read found: going to FC9BBE51.
FC9BBE29 reached.
Pointer to read data into AL 9 it seems (FC90D9B2, from EBP-02 offset).
Save pointer to stack (32-bit PUSH EAX).
Call function FC9BB984 (CALL).
Push 00000001h to stack.
Push the offset to the data received onto the stack.
Push FC9BBD20 to the stack.
Call function FC9BB810 (opcode E8h).
Basic stack setup (BP,SP).
Push ESI(1).
FC9BBD20 into ESI.
Check if it's cleared. It's not, so jump to FC9BB82D.
Push EBX, then clear it.
Set it to 1.
Check if FC9BBD08 is zero.
Push EDI (0).
Not zero, so jump to FC9BB855.
Load some value from memory.
Negate (=>FFh).
SBB EAX,EAX.
EAX becomes all ones.
And to become 31FFFh.
Incrase to 32000h.
To EDI.
Not zero, so FC9BB866.
Function call near: FC9BB5BD.
Stack setup, 64 bytes of local function area.
Push ESI at FC90D930.
Load ESI to get the data storage of the received data.
Load into EAX. @FC9BB5C7.
Its port 2F8h.
Select port 2FDh.
Read the port (@80197E62).
Check it for FFh.
Save it at FC90D970+0B (EBP+0B).
Zero, so FC9BB604.
FC9BB63D reached.
Some kernel hander at 80195F00h reached. Does nothing.
Load status, compare, FC9BB712 reached.
Check bit 6 of EBP+F (FC90D970).
AL 1 if it's zeroed (SETZ).
Increase it to 2.
Or it into FC9BBD84 (02h or'ed).
Did that value become 03h?
Nope, conditional jump to FC9BB762h.
Push 03h.
EDX=FC9BBD80h.
ESI=FC9BBD0C.
ECX=EBP-18=FC90D958h.
POP EDI(=03h).
Load AL from FC9BBD80 (=00h).
Is cleared, so jump to FC9BB782.
20202020h into ECX offset @ FC9BB782 (to FC90D958).
Some very slow data transfers occur.
Now, the WinDBG debugger has dumped:
1Microsoft (R) Windows Kernel Debugger Version 3.0.0020.0 2Copyright (c) Microsoft Corporation. All rights reserved. 3 4Waiting to reconnect... 5Connected to Windows XP 2600 x86 compatible target, ptr64 FALSE 6Kernel Debugger connection established. 7Loaded dbghelp extension DLL 8Loaded ext extension DLL 9Loaded exts extension DLL 10Loaded kext extension DLL 11Loaded kdexts extension DLL 12Symbol search path is: srv*DownstreamStore*https://msdl.microsoft.com/download/symbols 13Executable search path is: 14PsLoadedModuleList not initialized yet. Delay kernel load. 15Windows XP Kernel Version 2600 MP (1 procs) Free x86 compatible 16Built by: 2600.xpclient.010817-1148 17Kernel base = 0x807c2000 PsLoadedModuleList = 0x8083ce28 18System Uptime: not available 19 20*** Fatal System Error: 0x0000007b 21 (0xFC90E63C,0xC0000034,0x00000000,0x00000000) 22 23Break instruction exception - code 80000003 (first chance) 24 25A fatal system error has occurred. 26Debugger entered on first try; Bugcheck callbacks have not been invoked. 27 28A fatal system error has occurred. 29 30Will request initial breakpoint at next boot. 31Will breakin on first symbol load at next boot. 32Verbose mode ON. 33Engine is busy, try again 34ntkrnlmp.exe 35WARNING: Stack unwind information not available. Following frames may be wrong. 36WARNING: Stack unwind information not available. Following frames may be wrong. 37******************************************************************************* 38* * 39* Bugcheck Analysis * 40* * 41******************************************************************************* 42 43Use !analyzebugcheck -v to get more information. 44 45BugCheck 7B, {fc90e63c, c0000034, 0, 0} 46*** Bugcheck Analysis may not be correct, please followup with the following. 47Followup : MachineOwner 48 49ntkrnlmp+2784c: 50807e984c cc int 3
Edit: And I got a debugging interface now!
The attachment 20250409_Debugging Windows XP home again.png is no longer available
Last edited by superfury on 2025-04-09, 00:01. Edited 1 time in total.
Other than the symbol paths, the interface seems to be properly connected now 😁
Anyone knows how to get the symbol paths installed on the connected WinDBG program's machine (that's connected to the Windows XP Home installation that's being debugged over the serial loopback connection) hard drive into the debugger to make it recognise it?
1Break instruction exception - code 80000003 (first chance) 2******************************************************************************* 3* * 4* You are seeing this message because you pressed either * 5* CTRL+C (if you run kd.exe) or, * 6* CTRL+BREAK (if you run WinDBG), * 7* on your debugger machine's keyboard. * 8* * 9* THIS IS NOT A BUG OR A SYSTEM CRASH * 10* * 11* If you did not intend to break into the debugger, press the "g" key, then * 12* press the "Enter" key now. This message might immediately reappear. If it * 13* does, press "g" and "Enter" again. * 14* * 15******************************************************************************* 16ntkrnlmp!RtlpBreakWithStatusInstruction: 17807e984c cc int 3 18kd> !devnode 0 1 19Dumping IopRootDeviceNode (= 00000000) 2000000000: Could not read device node
Edit: OK, this should help:
1kd> bp pciidex!DriverEntry 2kd> bl 3 0 eu 0001 (0001) (pcipciidex!DriverEntry) 4 1 e fc73f04a 0001 (0001) PCIIDEX!DriverEntry 5
Edit: A slight revision later:
1kd> bp pcipciidex!DriverEntry 2Bp expression 'pcipciidex!DriverEntry' could not be resolved, adding deferred bp 3kd> bp pciidex!DriverEntry 4kd> bl 5 0 eu 0001 (0001) (pcipciidex!DriverEntry) 6 1 e fc73f04a 0001 (0001) PCIIDEX!DriverEntry 7 8kd> bc pcipciidex!DriverEntry 9 ^ Syntax error in 'bc pcipciidex!DriverEntry' 10kd> bc 0 11kd> bl 12 1 e fc73f04a 0001 (0001) PCIIDEX!DriverEntry
OK. Somehow, it reached the bugcheck (7B) again, never hitting the PCIIDEX!DriverEntry breakpoint.
So could it be an issue in the PCI driver then? Or perhaps the ESCD isn't properly setup somehow (it seems to somehow get corrupted or something like that, seeing as the BIOS corrupts itself from what I can see)?