Bunch of work on getting java.exe to start up. Not there yet.

Lots of fixes, improvements, and a few more APIs implemented.
This commit is contained in:
Ryan C. Gordon committed 2016-10-27 03:20:02 -04:00
1 parent 411c204ccb
commit 2481f59a28
8 files changed
+306 -55

No files matched your search

+48 -10
View File
@@ -1470,10 +1470,18 @@ static LxModule *loadLxModule(const char *fname, uint8 *exe, uint32 exelen, int
*(ptr++) = 0x90; // nop
} // if
// !!! FIXME: hack for Java that fails to mark a code page as executable
// !!! FIXME: (on 386 machines, read implies execute, so this error could go unnoticed).
uint32 object_flags = obj->object_flags;
if ((i == 4) && (strcasecmp(modname, "HPI") == 0)) {
fprintf(stderr, "fixed page permissions to workaround bug in Java DLL\n");
object_flags |= 0x4;
} // if
// Now set all the pages of this object to the proper final permissions...
const int prot = ((obj->object_flags & 0x1) ? PROT_READ : 0) |
((obj->object_flags & 0x2) ? PROT_WRITE : 0) |
((obj->object_flags & 0x4) ? PROT_EXEC : 0);
const int prot = ((object_flags & 0x1) ? PROT_READ : 0) |
((object_flags & 0x2) ? PROT_WRITE : 0) |
((object_flags & 0x4) ? PROT_EXEC : 0);
if (mprotect(retval->mmaps[i].mapped, retval->mmaps[i].size, prot) == -1) {
fprintf(stderr, "mprotect(%p, %u, %s%s%s, ANON|PRIVATE|FIXED, -1, 0) failed (%d): %s\n",
@@ -1692,12 +1700,15 @@ static void initPib(LxPIB *pib, const int argc, char **argv, char **envp)
exit(1);
} // if
const char *libpath = NULL;
char *ptr = env;
for (int i = 0; envp[i]; i++) {
const char *str = envp[i];
if (strncmp(str, "PATH=", 5) == 0) {
if (!GLoaderState->subprocess)
str = default_os2path;
} else if (strncmp(str, "LIBPATH=", 8) == 0) {
libpath = str + 8;
} else if (strncmp(str, "IS_2INE=", 8) == 0) {
continue;
} // if
@@ -1707,6 +1718,15 @@ static void initPib(LxPIB *pib, const int argc, char **argv, char **envp)
}
*(ptr++) = '\0';
// we keep a copy of LIBPATH for undocumented API
// DosQueryHandleInfo(..., QHINF_LIBPATH, ...). I guess in case the app
// has changed the environment var after start? Java uses this.
if (libpath == NULL)
libpath = "";
GLoaderState->libpath = strdup(libpath);
GLoaderState->libpathlen = strlen(libpath) + 1;
// put the exe name between the environment and the command line.
strcpy(ptr, argv[0]);
ptr += strlen(argv[0]) + 1;
@@ -1758,6 +1778,23 @@ static LxModule *loadLxModuleByModuleName(const char *modname)
return loadLxModuleByModuleNameInternal(modname, 0);
} // loadLxModuleByModuleName
static LxModule *loadLxModuleByPathOrModuleName(const char *modname)
{
LxModule *retval = NULL;
// !!! FIXME: can a module name be specified as "NAME.DLL" and not be considered a filename?
if (strrchr(modname, '.') == NULL) {
retval = loadLxModuleByModuleName(modname);
} else {
uint32 err = 0;
char *path = makeUnixPath(modname, &err);
if (!path)
return NULL;
retval = loadLxModuleByPath(path);
free(path);
} // else
return retval;
} // loadLxModuleByPathOrModuleName
static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int slot, ucontext_t *uctx)
{
greg_t *gregs = uctx->uc_mcontext.gregs;
@@ -1775,7 +1812,7 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
uint32 *tls = (uint32 *) (ptib2 + 1); // The thread's TLS data is stored right after its TIB2 struct.
tls += slot;
printf("We wanted to access thread %p TLS slot %d (currently holds %u)\n", tls - slot, slot, (uint) *tls);
//printf("We wanted to access thread %p TLS slot %d (currently holds %u)\n", tls - slot, slot, (uint) *tls);
static const int x86RegisterToUContextEnum[] = {
REG_EAX, REG_ECX, REG_EDX, REG_EBX, REG_ESP, REG_EBP, REG_ESI, REG_EDI
@@ -1786,19 +1823,19 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
uint8 *eip = (void *) (size_t) gregs[REG_EIP]; // program counter at point of segfault.
switch (eip[0]) {
case 0xC7: // mov imm16/32 -> r/m
printf("setting TLS slot %d to imm %u.\n", slot, (uint) *((uint32 *) (eip + 2)));
//printf("setting TLS slot %d to imm %u.\n", slot, (uint) *((uint32 *) (eip + 2)));
*tls = *((uint32 *) (eip + 2)); // !!! FIXME: verify it's a imm32, not 16
gregs[REG_EIP] += 6;
break;
case 0x89: // mov r -> r/m
printf("setting TLS slot %d to reg %d (%u).\n", slot, x86RegisterToUContextEnum[eip[1] >> 3], (uint) gregs[x86RegisterToUContextEnum[eip[1] >> 3]]);
//printf("setting TLS slot %d to reg %d (%u).\n", slot, x86RegisterToUContextEnum[eip[1] >> 3], (uint) gregs[x86RegisterToUContextEnum[eip[1] >> 3]]);
*tls = (uint32) gregs[x86RegisterToUContextEnum[eip[1] >> 3]];
gregs[REG_EIP] += 2;
break;
case 0x8B: // mov r/m -> r
printf("setting to reg %d to TLS slot %d (%u).\n", (uint) x86RegisterToUContextEnum[eip[1] >> 3], slot, *tls);
//printf("setting reg %d to TLS slot %d (%u).\n", (uint) x86RegisterToUContextEnum[eip[1] >> 3], slot, *tls);
gregs[x86RegisterToUContextEnum[eip[1] >> 3]] = (greg_t) *tls;
gregs[REG_EIP] += 2;
break;
@@ -1813,7 +1850,7 @@ static __attribute__((noreturn)) void handleThreadLocalStorageAccess(const int s
} else {
// drop out of signal handler to (hopefully) next instruction in the app,
// as if it accessed the TLS slot normally and none of this ever happened.
printf("TLS access handler jumping back into app at %p...\n", (void *) gregs[REG_EIP]); fflush(stdout);
//printf("TLS access handler jumping back into app at %p...\n", (void *) gregs[REG_EIP]); fflush(stdout);
setcontext(uctx);
fprintf(stderr, "panic: setcontext() failed in the TLS access handler! Aborting! (%s)\n", strerror(errno));
} // else
@@ -1841,6 +1878,7 @@ static void segfault_catcher(int sig, siginfo_t *info, void *ctx)
// !!! FIXME: case #1 should be a much more detailed crash dump.
case 1: fprintf(stderr, "SIGSEGV at addr=%p (eip=%p)\n", addr, (void *) ((ucontext_t *) ctx)->uc_mcontext.gregs[REG_EIP]); break;
case 2: write(2, "SIGSEGV, aborting.\n", 19); break;
default: break;
} // switch
abort(); // cash out.
@@ -1855,7 +1893,7 @@ static int installSignalHandlers(void)
action.sa_flags = SA_NODEFER | SA_SIGINFO;
if (sigaction(SIGSEGV, &action, NULL) == -1) {
fprintf(stderr, "Couldn't install signal handler! (%s)\n", strerror(errno));
fprintf(stderr, "Couldn't install SIGSEGV handler! (%s)\n", strerror(errno));
return 0;
} // if
@@ -1890,7 +1928,7 @@ int main(int argc, char **argv, char **envp)
GLoaderState->findSelector = findSelector;
GLoaderState->freeSelector = freeSelector;
GLoaderState->convert1616to32 = convert1616to32;
GLoaderState->loadModule = loadLxModuleByModuleName;
GLoaderState->loadModule = loadLxModuleByPathOrModuleName;
GLoaderState->locatePathCaseInsensitive = locatePathCaseInsensitive;
GLoaderState->makeUnixPath = makeUnixPath;
GLoaderState->makeOS2Path = makeOS2Path;
+2
View File
@@ -215,6 +215,8 @@ typedef struct LxLoaderState
uint16 original_ss;
uint16 original_ds;
uint32 ldt[8192];
char *libpath;
uint32 libpathlen;
uint32 *tlspage;
uint32 tlsmask; // one bit for each TLS slot in use.
uint8 tlsallocs[32]; // number of TLS slots allocated in one block, indexed by starting block (zero if not the starting block).
+164 -16
View File
@@ -14,7 +14,28 @@
#include <sys/resource.h>
#include <sys/stat.h>
static LxLoaderState *GLoaderState = NULL;
// DosQueryHeaderInfo() is an undocumented OS/2 API that is exported from DOSCALLS. Java uses it.
// This isn't mentioned in the docs or the SDK (beyond the ordinal being listed). I got the basic details
// from Odin32, which lists it in their os2newapi.h header.
enum
{
QHINF_EXEINFO = 1,
QHINF_READRSRCTBL,
QHINF_READFILE,
QHINF_LIBPATHLENGTH,
QHINF_LIBPATH,
QHINF_FIXENTRY,
QHINF_STE,
QHINF_MAPSEL
};
APIRET OS2API DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction);
// This is also undocumented (thanks, EDM/2!). Of course, Java uses it.
APIRET OS2API DosQuerySysState(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz);
// This is also undocumented (no idea about this at all, including function params). Of course, Java uses it.
APIRET DosR3ExitAddr(void);
static pthread_mutex_t GMutexDosCalls;
@@ -54,9 +75,10 @@ enum {
typedef struct HFileInfo
{
int fd;
ULONG type;
ULONG attr;
int fd; // unix file descriptor.
ULONG type; // file, pipe, device, etc.
ULONG attr; // for character devices, DAW_*
ULONG flags; // OPEN_FLAGS_*
} HFileInfo;
static HFileInfo *HFiles = NULL;
@@ -95,11 +117,6 @@ typedef struct
static DirFinder GHDir1;
// !!! FIXME:
#undef TRACE_NATIVE
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
LX_NATIVE_MODULE_DEINIT({
ExitListItem *next = GExitList;
GExitList = NULL;
@@ -118,14 +135,10 @@ LX_NATIVE_MODULE_DEINIT({
MaxHFiles = 0;
pthread_mutex_destroy(&GMutexDosCalls);
GLoaderState = NULL;
})
static int initDoscalls(LxLoaderState *lx_state)
static int initDoscalls(void)
{
GLoaderState = lx_state;
if (pthread_mutex_init(&GMutexDosCalls, NULL) == -1) {
fprintf(stderr, "pthread_mutex_init failed!\n");
return 0;
@@ -143,6 +156,7 @@ static int initDoscalls(LxLoaderState *lx_state)
info->fd = -1;
info->type = 0;
info->attr = 0;
info->flags = 0;
} // for
// launching a Hello World program from CMD.EXE seems to inherit several
@@ -164,7 +178,8 @@ static int initDoscalls(LxLoaderState *lx_state)
return 1;
} // initDoscalls
LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
LX_NATIVE_MODULE_INIT({ if (!initDoscalls()) return NULL; })
LX_NATIVE_EXPORT(DosSetMaxFH, 209),
LX_NATIVE_EXPORT(DosSetPathInfo, 219),
LX_NATIVE_EXPORT(DosQueryPathInfo, 223),
LX_NATIVE_EXPORT(DosQueryHType, 224),
@@ -183,6 +198,7 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
LX_NATIVE_EXPORT(DosOpen, 273),
LX_NATIVE_EXPORT(DosQueryCurrentDir, 274),
LX_NATIVE_EXPORT(DosQueryCurrentDisk, 275),
LX_NATIVE_EXPORT(DosQueryFHState, 276),
LX_NATIVE_EXPORT(DosQueryFileInfo, 279),
LX_NATIVE_EXPORT(DosWaitChild, 280),
LX_NATIVE_EXPORT(DosRead, 281),
@@ -214,6 +230,7 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
LX_NATIVE_EXPORT(DosSubFreeMem, 346),
LX_NATIVE_EXPORT(DosQuerySysInfo, 348),
LX_NATIVE_EXPORT(DosSetExceptionHandler, 354),
LX_NATIVE_EXPORT(DosQuerySysState, 368),
LX_NATIVE_EXPORT(DosSetSignalExceptionFocus, 378),
LX_NATIVE_EXPORT(DosEnterMustComplete, 380),
LX_NATIVE_EXPORT(DosExitMustComplete, 381),
@@ -221,6 +238,10 @@ LX_NATIVE_MODULE_INIT({ if (!initDoscalls(lx_state)) return NULL; })
LX_NATIVE_EXPORT(DosFlatToSel, 425),
LX_NATIVE_EXPORT(DosAllocThreadLocalMemory, 454),
LX_NATIVE_EXPORT(DosFreeThreadLocalMemory, 455),
LX_NATIVE_EXPORT(DosR3ExitAddr, 553),
LX_NATIVE_EXPORT(DosQueryHeaderInfo, 582),
LX_NATIVE_EXPORT(DosQueryExtLIBPATH, 874),
LX_NATIVE_EXPORT(DosQueryThreadContext, 877),
LX_NATIVE_EXPORT(DosOpenL, 981)
LX_NATIVE_MODULE_INIT_END()
@@ -364,7 +385,7 @@ APIRET DosQueryModuleName(HMODULE hmod, ULONG buflen, PCHAR buf)
const LxModule *lxmod = (LxModule *) hmod;
// !!! FIXME: error 6 ERROR_INVALID_HANDLE
if (strlen(lxmod->os2path) <= buflen)
if (strlen(lxmod->os2path) >= buflen)
return ERROR_BAD_LENGTH;
strcpy(buf, lxmod->os2path);
return NO_ERROR;
@@ -683,6 +704,7 @@ APIRET DosSetRelMaxFH(PLONG pincr, PULONG pcurrent)
info->fd = -1;
info->type = 0;
info->attr = 0;
info->flags = 0;
} // for
MaxHFiles += incr;
} // if
@@ -955,6 +977,8 @@ static APIRET doDosOpen(PSZ pszFileName, PHFILE pHf, PULONG pulAction, LONGLONG
__builtin_unreachable();
} // if
info->flags = fsOpenFlags;
if (isReplacing)
*pulAction = FILE_TRUNCATED;
else if (existed)
@@ -1244,6 +1268,12 @@ static APIRET queryPathInfo(PSZ unixPath, ULONG ulInfoLevel, PVOID pInfoBuf, ULO
case FIL_STANDARD: return queryPathInfoStandard(unixPath, pInfoBuf, cbInfoBuf);
case FIL_QUERYEASIZE: return queryPathInfoEaSize(unixPath, pInfoBuf, cbInfoBuf);
case FIL_QUERYEASFROMLIST: return queryPathInfoEasFromList(unixPath, pInfoBuf, cbInfoBuf);
// OS/2 has an undocumented info level, 7, that appears to return a case-corrected version
// of the path. (FIL_QUERYFULLNAME doesn't correct the case of what the app queries on
// OS/2). Since we have to case-correct for a Unix filesystem anyhow, we just use the
// usual FIL_QUERYFULLNAME to handle the undocumented level. Java uses this level.
case 7:
case FIL_QUERYFULLNAME: return queryPathInfoFullName(unixPath, pInfoBuf, cbInfoBuf);
default: break;
} // switch
@@ -2707,5 +2737,123 @@ APIRET DosFreeThreadLocalMemory(ULONG *p)
return retval;
} // DosFreeThreadLocalMemory
APIRET DosQueryFHState(HFILE hFile, PULONG pMode)
{
TRACE_NATIVE("DosQueryFHState(%u, %p)", (uint) hFile, pMode);
APIRET retval = NO_ERROR;
ULONG tmp = 0;
if (!pMode)
pMode = &tmp;
grabLock(&GMutexDosCalls);
if ((hFile < MaxHFiles) && (HFiles[hFile].fd != -1))
*pMode = HFiles[hFile].flags;
else
retval = ERROR_INVALID_HANDLE;
ungrabLock(&GMutexDosCalls);
return retval;
} // DosQueryFHState
APIRET DosQueryHeaderInfo(HMODULE hmod, ULONG ulIndex, PVOID pvBuffer, ULONG cbBuffer, ULONG ulSubFunction)
{
TRACE_NATIVE("DosQueryHeaderInfo(%u, %u, %p, %u, %u)", (uint) hmod, (uint) ulIndex, pvBuffer, (uint) cbBuffer, (uint) ulSubFunction);
switch (ulSubFunction) {
//case QHINF_EXEINFO:
//case QHINF_READRSRCTBL:
//case QHINF_READFILE:
case QHINF_LIBPATHLENGTH:
if (cbBuffer < sizeof (ULONG))
return ERROR_BUFFER_OVERFLOW;
*((ULONG *) pvBuffer) = GLoaderState->libpathlen;
return NO_ERROR;
case QHINF_LIBPATH:
if (cbBuffer < GLoaderState->libpathlen)
return ERROR_BUFFER_OVERFLOW;
strcpy((char *) pvBuffer, GLoaderState->libpath);
return NO_ERROR;
//case QHINF_FIXENTRY:
//case QHINF_STE:
//case QHINF_MAPSEL:
default: FIXME("I don't know what this query wants"); break;
} // switch
return ERROR_INVALID_PARAMETER;
} // DosQueryHeaderInfo
APIRET OS2API DosQueryExtLIBPATH(PSZ pszExtLIBPATH, ULONG flags)
{
TRACE_NATIVE("DosQueryExtLIBPATH('%s', %u)", pszExtLIBPATH, (uint) flags);
// !!! FIXME: this is mostly a stub for now.
if ((flags != BEGIN_LIBPATH) && (flags != END_LIBPATH))
return ERROR_INVALID_PARAMETER;
if (pszExtLIBPATH)
*pszExtLIBPATH = '\0';
return NO_ERROR;
} // DosQueryExtLIBPATH
APIRET DosSetMaxFH(ULONG cFH)
{
grabLock(&GMutexDosCalls);
if (cFH < MaxHFiles) {
ungrabLock(&GMutexDosCalls);
return ERROR_INVALID_PARAMETER; // strictly speaking, we could shrink, but I'm not doing it.
} // if
if (cFH == MaxHFiles) {
ungrabLock(&GMutexDosCalls);
return NO_ERROR;
} // if
HFileInfo *info = (HFileInfo *) realloc(HFiles, sizeof (HFileInfo) * (cFH));
if (info != NULL) {
HFiles = info;
info += MaxHFiles;
for (ULONG i = MaxHFiles; i < cFH; i++, info++) {
info->fd = -1;
info->type = 0;
info->attr = 0;
info->flags = 0;
} // for
MaxHFiles = cFH;
} // if
ungrabLock(&GMutexDosCalls);
return NO_ERROR;
} // DosSetMaxFH
APIRET DosQuerySysState(ULONG func, ULONG arg1, ULONG pid, ULONG _res_, PVOID buf, ULONG bufsz)
{
TRACE_NATIVE("DosQuerySysState(%u, %u, %u, %u, %p, %u)", (uint) func, (uint) arg1, (uint) pid, (uint) _res_, buf, (uint) bufsz);
FIXME("implement me");
return ERROR_INVALID_PARAMETER;
} // DosQuerySysState
APIRET DosR3ExitAddr(void)
{
TRACE_NATIVE("DosR3ExitAddr()");
FIXME("I have no idea what this is"); // but...JAVA USES IT.
return ERROR_INVALID_PARAMETER;
} // DosR3ExitAddr
APIRET DosQueryThreadContext(TID tid, ULONG level, PCONTEXTRECORD pcxt)
{
TRACE_NATIVE("DosQueryThreadContext(%u, %u, %p)", (uint) tid, (uint) level, pcxt);
FIXME("Need to be able to suspend threads first");
return ERROR_INVALID_PARAMETER;
} // DosQueryThreadContext
// end of doscalls.c ...
+11
View File
@@ -371,6 +371,13 @@ enum
FAPPTYP_32BIT = 0x4000
};
enum
{
BEGIN_LIBPATH = 1,
END_LIBPATH = 2
};
typedef void *PCONTEXTRECORD; // !!! FIXME
// !!! FIXME: these should probably get sorted alphabetically and/or grouped
// !!! FIXME: into areas of functionality, but for now, I'm just listing them
@@ -434,6 +441,10 @@ APIRET OS2API DosResetBuffer(HFILE hFile);
APIRET OS2API DosQueryAppType(PSZ pszName, PULONG pFlags);
APIRET OS2API DosAllocThreadLocalMemory(ULONG cb, PULONG *p);
APIRET OS2API DosFreeThreadLocalMemory(ULONG *p);
APIRET OS2API DosQueryFHState(HFILE hFile, PULONG pMode);
APIRET OS2API DosQueryExtLIBPATH(PSZ pszExtLIBPATH, ULONG flags);
APIRET OS2API DosSetMaxFH(ULONG cFH);
APIRET OS2API DosQueryThreadContext(TID tid, ULONG level, PCONTEXTRECORD pcxt);
#ifdef __cplusplus
}
+10 -3
View File
@@ -16,8 +16,11 @@
#include "os2errors.h"
#include "../lx_loader.h"
#if 0
#define TRACE_NATIVE(...) do { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } while (0)
// note that this is defined in _every_ module that includes this file!
static LxLoaderState *GLoaderState = NULL;
#if 1
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
#else
#define TRACE_NATIVE(...) do {} while (0)
#endif
@@ -26,10 +29,14 @@ OS2EXPORT const LxExport * lxNativeModuleInit(LxLoaderState *lx_state, uint32 *l
void OS2EXPORT lxNativeModuleDeinit(void);
#define LX_NATIVE_MODULE_DEINIT(deinitcode) \
void lxNativeModuleDeinit(void) { deinitcode; }
void lxNativeModuleDeinit(void) { \
deinitcode; \
GLoaderState = NULL; \
}
#define LX_NATIVE_MODULE_INIT(initcode) \
const LxExport *lxNativeModuleInit(LxLoaderState *lx_state, uint32 *lx_num_exports) { \
GLoaderState = lx_state; \
initcode; \
static const LxExport lx_native_exports[] = {
+4 -10
View File
@@ -6,7 +6,6 @@
// !!! FIXME: _lots_ of macro salsa in here.
#define LX_NATIVE_MODULE_16BIT_SUPPORT() \
static LxLoaderState *GLoaderState = NULL; \
static LxMmaps obj16;
// These are the 16-bit entry points, which are exported to the LX loader
@@ -26,11 +25,8 @@
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
GLoaderState = NULL;
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT() \
GLoaderState = lx_state; \
\
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
@@ -39,7 +35,6 @@
void *mmapaddr = mmap(NULL, vsize, PROT_READ|PROT_WRITE, MAP_PRIVATE|MAP_ANONYMOUS, -1, 0); \
if (mmapaddr == ((void *) MAP_FAILED)) { \
fprintf(stderr, "mmap(NULL, 0x20000, RW-, ANON|PRIVATE, -1, 0) failed (%d): %s\n", errno, strerror(errno)); \
GLoaderState = NULL; \
return 0; \
} \
\
@@ -62,7 +57,6 @@
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
GLoaderState = NULL; \
return 0; \
} \
assert(offset == 0); \
@@ -115,7 +109,7 @@ MOV SP, BX
RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling convention!) with retval in AX.
*/
#define LX_NATIVE_INIT_16BIT_BRIDGE(fn, argbytes) \
#define LX_NATIVE_INIT_16BIT_BRIDGE(fn, argbytes) { \
fn##16 = ptr; \
\
/* instructions are in Intel syntax here, not AT&T. */ \
@@ -192,9 +186,9 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
*(ptr++) = 0xCA; /* retf 0x22... */ \
const uint16 argbytecount = argbytes; \
memcpy(ptr, &argbytecount, 2); ptr += 2; \
}
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() \
#define LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END() { \
assert((((uint32)ptr) - ((uint32)mmapaddr)) < 0x10000); /* don't be more than 64k. */ \
if (mprotect(obj16.mapped, vsize, PROT_READ | PROT_EXEC) == -1) { \
fprintf(stderr, "mprotect() failed for 16-bit bridge code!\n"); \
@@ -203,9 +197,9 @@ RETF 0x22 ; ...and back to the (far) caller, clearing the args (Pascal calling
obj16.mapped = obj16.addr = NULL; \
obj16.size = 0; \
obj16.alias = 0xFFFF; \
GLoaderState = NULL; \
return 0; \
} \
}
#define LX_NATIVE_EXPORT16(fn, ord) { ord, #fn, &fn##16, &obj16 }
+66 -16
View File
@@ -1,23 +1,35 @@
#include "os2native16.h"
#include "viocalls.h"
LX_NATIVE_MODULE_16BIT_SUPPORT()
LX_NATIVE_MODULE_16BIT_API(VioGetMode)
LX_NATIVE_MODULE_16BIT_SUPPORT_END()
// !!! FIXME:
#undef TRACE_NATIVE
#define TRACE_NATIVE(...) do { if (GLoaderState->trace_native) { fprintf(stderr, "2INE TRACE [%lu]: ", (unsigned long) pthread_self()); fprintf(stderr, __VA_ARGS__); fprintf(stderr, ";\n"); } } while (0)
LX_NATIVE_MODULE_DEINIT({
LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
})
APIRET16 VioGetMode(PVIOMODEINFO pvioModeInfo, HVIO hvio)
{
TRACE_NATIVE("VioGetMode(%p, %u)", pvioModeInfo, (uint) hvio);
FIXME("write me");
return ERROR_INVALID_PARAMETER;
if (hvio != 0)
return ERROR_VIO_INVALID_HANDLE; // !!! FIXME: can be non-zero when VioCreatePS() is implemented.
else if (pvioModeInfo == NULL)
return ERROR_VIO_INVALID_PARMS;
else if (pvioModeInfo->cb != sizeof (*pvioModeInfo))
return ERROR_VIO_INVALID_LENGTH;
memset(pvioModeInfo, '\0', sizeof (*pvioModeInfo));
pvioModeInfo->cb = sizeof (*pvioModeInfo);
pvioModeInfo->fbType = VGMT_OTHER;
pvioModeInfo->color = 8; // bits?
pvioModeInfo->col = 80;
pvioModeInfo->row = 25;
FIXME("I don't know what most of these fields do");
//pvioModeInfo->hres = 640;
//pvioModeInfo->vres = 480;
//UCHAR fmt_ID;
//UCHAR attrib;
//ULONG buf_addr;
//ULONG buf_length;
//ULONG full_length;
//ULONG partial_length;
//PCHAR ext_data_addr;
return NO_ERROR;
} // VioGetMode
static APIRET16 bridge16to32_VioGetMode(uint8 *args)
@@ -27,15 +39,53 @@ static APIRET16 bridge16to32_VioGetMode(uint8 *args)
return VioGetMode(pvmi, hvio);
} // bridge16to32_VioGetMode
static int initViocalls(LxLoaderState *lx_state)
APIRET16 VioGetCurPos(PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio)
{
TRACE_NATIVE("VioGetCurPos(%p, %p, %u)", pusRow, pusColumn, (uint) hvio);
if (hvio != 0)
return ERROR_VIO_INVALID_HANDLE; // !!! FIXME: can be non-zero when VioCreatePS() is implemented.
FIXME("write me");
if (pusRow)
*pusRow = 0;
if (pusColumn)
*pusColumn = 0;
return NO_ERROR;
} // VioGetCurPos
static APIRET16 bridge16to32_VioGetCurPos(uint8 *args)
{
const HVIO hvio = *((HVIO *) args); args += 2;
PUSHORT pusRow = GLoaderState->convert1616to32(*((uint32*) args)); args += 4;
PUSHORT pusColumn = GLoaderState->convert1616to32(*((uint32*) args)); args += 4;
return VioGetCurPos(pusRow, pusColumn, hvio);
} // bridge16to32_VioGetCurPos
LX_NATIVE_MODULE_16BIT_SUPPORT()
LX_NATIVE_MODULE_16BIT_API(VioGetCurPos)
LX_NATIVE_MODULE_16BIT_API(VioGetMode)
LX_NATIVE_MODULE_16BIT_SUPPORT_END()
LX_NATIVE_MODULE_DEINIT({
LX_NATIVE_MODULE_DEINIT_16BIT_SUPPORT();
})
static int initViocalls(void)
{
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT()
LX_NATIVE_INIT_16BIT_BRIDGE(VioGetCurPos, 6)
LX_NATIVE_INIT_16BIT_BRIDGE(VioGetMode, 6)
LX_NATIVE_MODULE_INIT_16BIT_SUPPORT_END()
return 1;
} // initViocalls
LX_NATIVE_MODULE_INIT({ if (!initViocalls(lx_state)) return NULL; })
LX_NATIVE_MODULE_INIT({ if (!initViocalls()) return NULL; })
LX_NATIVE_EXPORT16(VioGetCurPos, 9),
LX_NATIVE_EXPORT16(VioGetMode, 21)
LX_NATIVE_MODULE_INIT_END()
+1
View File
@@ -35,6 +35,7 @@ enum
};
APIRET16 OS2API16 VioGetMode(PVIOMODEINFO pvioModeInfo, HVIO hvio);
APIRET16 OS2API16 VioGetCurPos(PUSHORT pusRow, PUSHORT pusColumn, HVIO hvio);
#ifdef __cplusplus
}