Baron-von-Riedesel / HX

Home of the HX DOS Extender and its included DPMI-host HDPMI.
197 stars 14 forks source link

Build error on HDPMI, update JWlink needed. #27

Closed crazii closed 1 year ago

crazii commented 1 year ago

Hi,

I was trying to build HDPMI and HDPMI only, but I encounter a problem: The JWlink (1.9beta 13, downloaded from: https://www.japheth.de/ ) is outdated, I check the makefile and it says 1.9beta15 with NODOSSEG option needed.

Here's the output of my make:

E:\HDPMI\HX\Src\HDPMI>wmake -f MAKEFILE Open Watcom Make Version 2.0 beta Dec 2 2022 01:05:59 (64-bit) Copyright (c) 2002-2022 The Open Watcom Contributors. All Rights Reserved. Portions Copyright (c) 1988-2002 Sybase, Inc. All Rights Reserved. Source code is available under the Sybase Open Watcom Public License. See http://www.openwatcom.org/ for details. Error! E3033: directive error near 'nodosseg' Error(E42): Last command making (STD16\HDPMI16.TMP) returned a bad status Error(E02): Make execution terminated Error! E3033: directive error near 'nodosseg' Error(E42): Last command making (STD32\HDPMI32.TMP) returned a bad status Error(E02): Make execution terminated Error! E3033: directive error near 'nodosseg' Error(E42): Last command making (HDPMIST\HDPMIST.TMP) returned a bad status Error(E02): Make execution terminated Error(F38): (ALL) does not exist and cannot be made from existing files Error(E02): Make execution terminated

BTW, The extra tool needed to build HDPMI is already built: SetMZHdr.exe & ExtrMZ.exe.

Would you provide the latest JWlink binary, please?

crazii commented 1 year ago

Okay, I found the latest JWlink on GitHub, nevermind. https://github.com/Baron-von-Riedesel/jwlink/releases

Baron-von-Riedesel commented 1 year ago

The site https://www.japheth.com is a clone of my old site, freezed in the state it was in 2013. I have no access to it.

crazii commented 1 year ago

The site https://www.japheth.com is a clone of my old site, freezed in the state it was in 2013. I have no access to it.

Where to get the latest HXDEV package? Currently I'm using the latest package from https://www.japheth.com/, I can build STD HDPMI and it tested working. But other editions using SetMZHdr will fail to build, saying "setmzhdr: write error". I've check the asm code of SetMZHdr, it's weird that fopen & fread succeeded but fwrite failed. Any advices?

Baron-von-Riedesel commented 1 year ago

Where to get the latest HXDEV package?

Well, it's on github: https://github.com/Baron-von-Riedesel/HX

The latest release is v2.19, it should be named hxdev219.zip

crazii commented 1 year ago

Where to get the latest HXDEV package?

Well, it's on github: https://github.com/Baron-von-Riedesel/HX

The latest release is v2.19, it should be named hxdev219.zip

Thanks, problem solved! New HXDEV package used and no errors.

crazii commented 1 year ago

Hey I've filled the blank in I2FHDPMI.ASM, now I'm trying to write the exception handler code. I've read this comment:

;--- exception handler entered with error code: ;--- bit 0: 0=in, 1=out ;--- bit 1: 0=port in dx, 1= port in bits 8-15 ;--- bit 2-3: access 00=byte, 01=word, 10=dword, 11=string ;--- bit 4-7: size of instruction

I've read the intel developer's manuals the IN/OUT raise #GP without error code, so I wonder this error code is planned to generated by HDPMI?

Baron-von-Riedesel commented 1 year ago

so I wonder this error code is planned to generated by HDPMI?

Yes. Since the host has to scan the instruction in any case, why not tell the handler the result.

Although, thinking about it, "string" should probably be an independent flag, not just an additional value

crazii commented 1 year ago

so I wonder this error code is planned to generated by HDPMI?

Yes. Since the host has to scan the instruction in any case, why not tell the handler the result.

Although, thinking about it, "string" should probably be an independent flag, not just an additional value

Okay, I just scanned the opcode in the handler, not using the error codes, and skipping strings first. besides, its hard to tell the operand size (AX/EAX) which may need read the CS sel's descriptor and also need check the 66h prefix, so I just ignore it for now. Does HDPMI32 always have a 32bit client absolutely without any 16bit segment? if that is true, I may just use the 32BIT macro and check the prefix.

Baron-von-Riedesel commented 1 year ago

Does HDPMI32 always have a 32bit client absolutely without any 16bit segment?

No, there's no guarantee. But the prefix issue is really simple to account for - there was code in hdpmi.asm to simulate all in/out; it's now - with the existing IO permission bitmap - no logner needed.and has been removed.

crazii commented 1 year ago

Does HDPMI32 always have a 32bit client absolutely without any 16bit segment?

No, there's no guarantee. But the prefix issue is really simple to account for - there was code in hdpmi.asm to simulate all in/out; it's now - with the existing IO permission bitmap - no logner needed.and has been removed.

Cool. I'll probably check the commit history later. I've added the prefix checking and LDT descriptor type checking untested. the problem is I haven't been writing asm for too many years and when I read you code I'm pretty sure that I cannot write good quality codes like yours. For now I'm gonna make it work first, and then try to improve it.

About the real mode handler, it might be possible to manually create 2 16bit sel (data & code) to access the memory like EMM386 does. That will be put in low priority, I'm not thinking about it quite much now.

crazii commented 1 year ago

Hey sorry to bother, I have another question, I'm debugging the code now. it could calls to a ring3 handler from ring0, with a simulated IRET stack frame with IOPL3 temporarily. but I'm unable to return the handler to the exact return point in ring 0.

I can think of a ring3 wrapper code to do the privilege elevation call after saving ring0 return addr onto ring3 stack. or just use an extra ring0 sel for the handler code.

Any ideas?

crazii commented 1 year ago

I saw a _TEXT32R3 segment and it didn't appear in readme.txt. I was planning to add another seg desc in the GDT but seems no need anymore.

Baron-von-Riedesel commented 1 year ago

Any ideas?

I don't really know what you are doing, but I suggest not to do much - if anything at all - in ring 0 code. The idea of the port trapping support in hdpmi is to make it possible that the emulation code runs in ring 3 ( quite similar as it is done in the NTVDM API ). The major benefit is that at that layer you are not restricted to assembly language.

The only thing that's really required in ring 0 is to set the port bits in the IO permission bitmap. Everything else would be just "nice to have".

crazii commented 1 year ago

Any ideas?

I don't really know what you are doing, but I suggest not to do much - if anything at all - in ring 0 code. The idea of the port trapping support in hdpmi is to make it possible that the emulation code runs in ring 3 ( quite similar as it is done in the NTVDM API ). The major benefit is that at that layer you are not restricted to assembly language.

The only thing that's really required in ring 0 is to set the port bits in the IO permission bitmap. Everything else would be just "nice to have".

Any ideas?

I don't really know what you are doing, but I suggest not to do much - if anything at all - in ring 0 code. The idea of the port trapping support in hdpmi is to make it possible that the emulation code runs in ring 3 ( quite similar as it is done in the NTVDM API ). The major benefit is that at that layer you are not restricted to assembly language.

The only thing that's really required in ring 0 is to set the port bits in the IO permission bitmap. Everything else would be just "nice to have".

Here's what I am doing: In the in/out exception handler (ring 0), call the ring 3 port trap handler (with IOPL3) that was registered and RETURN TO RING0 where the port trap handler was called, via RETF. and finally set IOPL to 0 and exit the exception handler. I'm now struggling with the return to ring0 part.

Not sure I'm doing this correctly though. Any help will be appreciated.

Baron-von-Riedesel commented 1 year ago

Any help will be appreciated.

I don't know your skills, so please apologize if I may sound patronizing...

The first thing is, you cannot "call" ring 3 code from ring 0 - the x86 architecture assumes that you "return" from ring 0 to ring 3. Also, handling exceptions is done by a very special routine which I really don't want to modify without very good reasons. It handles everything that's needed, including a switch to the "locked protected-mode stack".

IMO, in a first step, you don't need a special "in/out exception handler" - just tell hdpmi what ports you want to trap ( using the "vendor" API ) and then install a "standard" dpmi exception 0Dh handler. This handler will be called if any trapped port is accessed and you can then examine the code and check if the instruction that caused the exception is indeed one of the I/O instructions you're interested in. If no, just route the exception to the previous handler. If yes, do whatever you have to emulate, find out the size of the instruction and skip it.

Once the "io exception handling" is properly implemented in hdpmi, you can deactivate those parts of your code that have to determine if the current exception is indeed the one you're "waiting" for...

What device exactly do you want to emulate?

crazii commented 1 year ago

It sounds a little but fine. and to clarify, I'm writing the "in/out exception handler" function in the 0Dh handler, by "calling ring 3 from ring 0" I'm doing it using a simulated IRET frame and that seems OK. about return ring3 to ring0, I was modifying the client's stack so that its trap handler will return to a host ring3 segment then I'll do the ring0 call, still trying to make it work.

I'm completing the API that allow HDPMI's client (most probably a TSR) to register a IO trap handler to the host/server, and the host route the trapped port read/write to the TSRed ring3 code and then return to the exception handler (ring0) and continue.

What device exactly do you want to emulate?

I'm trying to make my RetroWave OPL3 driver working for PM games. trapping ports 388h~38Bh.

BTW, I've cloned the code and you can find it here: https://github.com/crazii/HX

crazii commented 1 year ago

I've finished the feature. tested with one game using HDPMI32i and my TSR, and its working, probably need more test. Would you like a PR?