Moved most global data out of the LPDOSTASK structure.
Allocate DPMI real-mode segments globally at startup.
Try to allocate DOS memory at address 0.
diff --git a/loader/dos/dosvm.c b/loader/dos/dosvm.c
index 790b5d3..241f669 100644
--- a/loader/dos/dosvm.c
+++ b/loader/dos/dosvm.c
@@ -58,6 +58,21 @@
#undef TRY_PICRETURN
+typedef struct _DOSEVENT {
+ int irq,priority;
+ void (*relay)(CONTEXT86*,void*);
+ void *data;
+ struct _DOSEVENT *next;
+} DOSEVENT, *LPDOSEVENT;
+
+static struct _DOSEVENT *pending_event, *current_event;
+static int sig_sent, entered;
+
+/* from module.c */
+extern int read_pipe, write_pipe;
+extern HANDLE hReadPipe;
+extern pid_t dosmod_pid;
+
static void do_exception( int signal, CONTEXT86 *context )
{
EXCEPTION_RECORD rec;
@@ -77,10 +92,8 @@
EXC_RtlRaiseException( &rec, context );
}
-static void DOSVM_Dump( LPDOSTASK lpDosTask, int fn, int sig,
- struct vm86plus_struct*VM86 )
+static void DOSVM_Dump( int fn, int sig, struct vm86plus_struct*VM86 )
{
- unsigned iofs;
BYTE*inst;
int x;
@@ -106,20 +119,17 @@
fprintf(stderr,"CS=%04X DS=%04X ES=%04X SS=%04X\n",REGS.cs,REGS.ds,REGS.es,REGS.ss);
fprintf(stderr,"IP=%04lX EFLAGS=%08lX\n",REGS.eip,REGS.eflags);
- iofs=((DWORD)REGS.cs<<4)+REGS.eip;
+ inst = PTR_REAL_TO_LIN( REGS.cs, REGS.eip );
#undef REGS
- inst=(BYTE*)lpDosTask->img+iofs;
printf("Opcodes:");
for (x=0; x<8; x++) printf(" %02x",inst[x]);
printf("\n");
}
-static int DOSVM_Int( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask )
+static int DOSVM_Int( int vect, CONTEXT86 *context )
{
- extern UINT16 DPMI_wrap_seg;
-
if (vect==0x31) {
- if (CS_reg(context)==DPMI_wrap_seg) {
+ if (CS_reg(context)==DOSMEM_wrap_seg) {
/* exit from real-mode wrapper */
return -1;
}
@@ -129,7 +139,7 @@
return 0;
}
-static void DOSVM_SimulateInt( int vect, CONTEXT86 *context, LPDOSTASK lpDosTask )
+static void DOSVM_SimulateInt( int vect, CONTEXT86 *context )
{
FARPROC16 handler=INT_GetRMHandler(vect);
@@ -137,7 +147,7 @@
/* if internal interrupt, call it directly */
INT_RealModeInterrupt(vect,context);
} else {
- WORD*stack=(WORD*)(V86BASE(context)+(((DWORD)SS_reg(context))<<4)+LOWORD(ESP_reg(context)));
+ WORD*stack= PTR_REAL_TO_LIN( context->SegSs, context->Esp );
WORD flag=LOWORD(EFL_reg(context));
if (IF_ENABLED(context)) flag|=IF_MASK;
@@ -154,51 +164,50 @@
}
#define SHOULD_PEND(x) \
- (x && ((!lpDosTask->current) || (x->priority < lpDosTask->current->priority)))
+ (x && ((!current_event) || (x->priority < current_event->priority)))
-static void DOSVM_SendQueuedEvent(CONTEXT86 *context, LPDOSTASK lpDosTask)
+static void DOSVM_SendQueuedEvent(CONTEXT86 *context)
{
- LPDOSEVENT event = lpDosTask->pending;
+ LPDOSEVENT event = pending_event;
if (SHOULD_PEND(event)) {
/* remove from "pending" list */
- lpDosTask->pending = event->next;
+ pending_event = event->next;
/* process event */
if (event->irq>=0) {
/* it's an IRQ, move it to "current" list */
- event->next = lpDosTask->current;
- lpDosTask->current = event;
+ event->next = current_event;
+ current_event = event;
TRACE_(int)("dispatching IRQ %d\n",event->irq);
/* note that if DOSVM_SimulateInt calls an internal interrupt directly,
- * lpDosTask->current might be cleared (and event freed) in this very call! */
- DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context,lpDosTask);
+ * current_event might be cleared (and event freed) in this very call! */
+ DOSVM_SimulateInt((event->irq<8)?(event->irq+8):(event->irq-8+0x70),context);
} else {
/* callback event */
TRACE_(int)("dispatching callback event\n");
- (*event->relay)(lpDosTask,context,event->data);
+ (*event->relay)(context,event->data);
free(event);
}
}
- if (!SHOULD_PEND(lpDosTask->pending)) {
+ if (!SHOULD_PEND(pending_event)) {
TRACE_(int)("clearing Pending flag\n");
CLR_PEND(context);
}
}
-static void DOSVM_SendQueuedEvents(CONTEXT86 *context, LPDOSTASK lpDosTask)
+static void DOSVM_SendQueuedEvents(CONTEXT86 *context)
{
/* we will send all queued events as long as interrupts are enabled,
* but IRQ events will disable interrupts again */
while (IS_PEND(context) && IF_ENABLED(context))
- DOSVM_SendQueuedEvent(context,lpDosTask);
+ DOSVM_SendQueuedEvent(context);
}
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data)
+void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
{
- LPDOSTASK lpDosTask = MZ_Current();
LPDOSEVENT event, cur, prev;
- if (lpDosTask && lpDosTask->entered) {
+ if (entered) {
event = malloc(sizeof(DOSEVENT));
if (!event) {
ERR_(int)("out of memory allocating event entry\n");
@@ -209,20 +218,20 @@
/* insert event into linked list, in order *after*
* all earlier events of higher or equal priority */
- cur = lpDosTask->pending; prev = NULL;
+ cur = pending_event; prev = NULL;
while (cur && cur->priority<=priority) {
prev = cur;
cur = cur->next;
}
event->next = cur;
if (prev) prev->next = event;
- else lpDosTask->pending = event;
+ else pending_event = event;
/* get dosmod's attention to the new event, if necessary */
- if (!lpDosTask->sig_sent) {
+ if (!sig_sent) {
TRACE_(int)("new event queued, signalling dosmod\n");
- kill(lpDosTask->task,SIGUSR2);
- lpDosTask->sig_sent++;
+ kill(dosmod_pid,SIGUSR2);
+ sig_sent++;
} else {
TRACE_(int)("new event queued\n");
}
@@ -234,7 +243,7 @@
/* callback event, perform it with dummy context */
CONTEXT86 context;
memset(&context,0,sizeof(context));
- (*relay)(lpDosTask,&context,data);
+ (*relay)(&context,data);
} else {
ERR_(int)("IRQ without DOS task: should not happen");
}
@@ -247,8 +256,7 @@
CP(ss,SS); CP(fs,FS); CP(gs,GS); \
CP(eip,EIP); CP(eflags,EFL)
-static int DOSVM_Process( LPDOSTASK lpDosTask, int fn, int sig,
- struct vm86plus_struct*VM86 )
+static int DOSVM_Process( int fn, int sig, struct vm86plus_struct*VM86 )
{
CONTEXT86 context;
int ret=0;
@@ -270,7 +278,7 @@
}
#else
/* linux doesn't preserve pending flag on return */
- if (SHOULD_PEND(lpDosTask->pending)) {
+ if (SHOULD_PEND(pending_event)) {
SET_PEND(&context);
}
#endif
@@ -280,48 +288,48 @@
TRACE_(int)("DOS module caught signal %d\n",sig);
if ((sig==SIGALRM) || (sig==SIGUSR2)) {
if (sig==SIGALRM) {
- lpDosTask->sig_sent++;
+ sig_sent++;
DOSVM_QueueEvent(0,DOS_PRIORITY_REALTIME,NULL,NULL);
}
- if (lpDosTask->pending) {
+ if (pending_event) {
TRACE_(int)("setting Pending flag, interrupts are currently %s\n",
IF_ENABLED(&context) ? "enabled" : "disabled");
SET_PEND(&context);
- DOSVM_SendQueuedEvents(&context,lpDosTask);
+ DOSVM_SendQueuedEvents(&context);
} else {
TRACE_(int)("no events are pending, clearing Pending flag\n");
CLR_PEND(&context);
}
- lpDosTask->sig_sent--;
+ sig_sent--;
}
else if ((sig==SIGHUP) || (sig==SIGILL) || (sig==SIGSEGV)) {
do_exception( sig, &context );
} else {
- DOSVM_Dump(lpDosTask,fn,sig,VM86);
+ DOSVM_Dump(fn,sig,VM86);
ret=-1;
}
break;
case VM86_UNKNOWN: /* unhandled GPF */
- DOSVM_Dump(lpDosTask,fn,sig,VM86);
+ DOSVM_Dump(fn,sig,VM86);
do_exception( SIGSEGV, &context );
break;
case VM86_INTx:
if (TRACE_ON(relay))
DPRINTF("Call DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip);
- ret=DOSVM_Int(VM86_ARG(fn),&context,lpDosTask);
+ ret=DOSVM_Int(VM86_ARG(fn),&context);
if (TRACE_ON(relay))
DPRINTF("Ret DOS int 0x%02x (EAX=%08lx) ret=%04lx:%04lx\n",VM86_ARG(fn),context.Eax,context.SegCs,context.Eip);
break;
case VM86_STI:
case VM86_PICRETURN:
TRACE_(int)("DOS task enabled interrupts with events pending, sending events\n");
- DOSVM_SendQueuedEvents(&context,lpDosTask);
+ DOSVM_SendQueuedEvents(&context);
break;
case VM86_TRAP:
do_exception( SIGTRAP, &context );
break;
default:
- DOSVM_Dump(lpDosTask,fn,sig,VM86);
+ DOSVM_Dump(fn,sig,VM86);
ret=-1;
}
@@ -335,7 +343,7 @@
return ret;
}
-static void DOSVM_ProcessConsole(LPDOSTASK lpDosTask)
+static void DOSVM_ProcessConsole(void)
{
INPUT_RECORD msg;
DWORD res;
@@ -360,7 +368,7 @@
}
}
-static void DOSVM_ProcessMessage(LPDOSTASK lpDosTask,MSG *msg)
+static void DOSVM_ProcessMessage(MSG *msg)
{
BYTE scan = 0;
@@ -391,21 +399,20 @@
void DOSVM_Wait( int read_pipe, HANDLE hObject )
{
- LPDOSTASK lpDosTask = MZ_Current();
MSG msg;
DWORD waitret;
HANDLE objs[2];
int objc;
BOOL got_msg = FALSE;
- objs[0]=lpDosTask->hConInput;
+ objs[0]=GetStdHandle(STD_INPUT_HANDLE);
objs[1]=hObject;
objc=hObject?2:1;
do {
/* check for messages (waste time before the response check below) */
while (Callout.PeekMessageA(&msg,0,0,0,PM_REMOVE|PM_NOYIELD)) {
/* got a message */
- DOSVM_ProcessMessage(lpDosTask,&msg);
+ DOSVM_ProcessMessage(&msg);
/* we don't need a TranslateMessage here */
Callout.DispatchMessageA(&msg);
got_msg = TRUE;
@@ -415,7 +422,7 @@
INPUT_RECORD msg;
DWORD num;
if (PeekConsoleInputA(objs[0],&msg,1,&num) && num) {
- DOSVM_ProcessConsole(lpDosTask);
+ DOSVM_ProcessConsole();
got_msg = TRUE;
}
}
@@ -439,63 +446,42 @@
if (waitret==(WAIT_OBJECT_0+1)) break;
}
if (waitret==WAIT_OBJECT_0) {
- DOSVM_ProcessConsole(lpDosTask);
+ DOSVM_ProcessConsole();
}
} while (TRUE);
}
int DOSVM_Enter( CONTEXT86 *context )
{
- LPDOSTASK lpDosTask = MZ_Current();
struct vm86plus_struct VM86;
int stat,len,sig;
- if (!lpDosTask) {
- /* MZ_CreateProcess or MZ_AllocDPMITask should have been called first */
- ERR_(module)("dosmod has not been initialized!");
- return -1;
- }
-
- if (context) {
#define CP(x,y) VM86.regs.x = y##_reg(context)
CV;
#undef CP
if (VM86.regs.eflags & IF_MASK)
VM86.regs.eflags |= VIF_MASK;
- } else {
-/* initial setup */
- /* registers */
- memset(&VM86,0,sizeof(VM86));
- VM86.regs.cs=lpDosTask->init_cs;
- VM86.regs.eip=lpDosTask->init_ip;
- VM86.regs.ss=lpDosTask->init_ss;
- VM86.regs.esp=lpDosTask->init_sp;
- VM86.regs.ds=lpDosTask->psp_seg;
- VM86.regs.es=lpDosTask->psp_seg;
- VM86.regs.eflags=VIF_MASK;
- /* hmm, what else do we need? */
- }
/* main exchange loop */
- lpDosTask->entered++;
+ entered++;
do {
TRACE_(module)("thread is: %lx\n",GetCurrentThreadId());
stat = VM86_ENTER;
errno = 0;
/* transmit VM86 structure to dosmod task */
- if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
- ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,lpDosTask->write_pipe,getpid());
+ if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+ ERR_(module)("dosmod sync lost, errno=%d, fd=%d, pid=%d\n",errno,write_pipe,getpid());
return -1;
}
- if (write(lpDosTask->write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) {
+ if (write(write_pipe,&VM86,sizeof(VM86))!=sizeof(VM86)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return -1;
}
/* wait for response, doing other things in the meantime */
- DOSVM_Wait(lpDosTask->read_pipe, lpDosTask->hReadPipe);
+ DOSVM_Wait(read_pipe, hReadPipe);
/* read response */
while (1) {
- if ((len=read(lpDosTask->read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break;
+ if ((len=read(read_pipe,&stat,sizeof(stat)))==sizeof(stat)) break;
if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
WARN_(module)("rereading dosmod return code due to errno=%d, result=%d\n",errno,len);
continue;
@@ -505,11 +491,10 @@
}
TRACE_(module)("dosmod return code=%d\n",stat);
if (stat==DOSMOD_LEFTIDLE) {
- lpDosTask->idling--;
continue;
}
while (1) {
- if ((len=read(lpDosTask->read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
+ if ((len=read(read_pipe,&VM86,sizeof(VM86)))==sizeof(VM86)) break;
if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
WARN_(module)("rereading dosmod VM86 structure due to errno=%d, result=%d\n",errno,len);
continue;
@@ -519,7 +504,7 @@
}
if ((stat&0xff)==DOSMOD_SIGNAL) {
while (1) {
- if ((len=read(lpDosTask->read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break;
+ if ((len=read(read_pipe,&sig,sizeof(sig)))==sizeof(sig)) break;
if (((errno==EINTR)||(errno==EAGAIN))&&(len<=0)) {
WARN_(module)("rereading dosmod signal due to errno=%d, result=%d\n",errno,len);
continue;
@@ -529,8 +514,8 @@
} while (0);
} else sig=0;
/* got response */
- } while (DOSVM_Process(lpDosTask,stat,sig,&VM86)>=0);
- lpDosTask->entered--;
+ } while (DOSVM_Process(stat,sig,&VM86)>=0);
+ entered--;
if (context) {
#define CP(x,y) y##_reg(context) = VM86.regs.x
@@ -542,27 +527,25 @@
void DOSVM_PIC_ioport_out( WORD port, BYTE val)
{
- LPDOSTASK lpDosTask = MZ_Current();
- LPDOSEVENT event;
+ LPDOSEVENT event;
- if (lpDosTask) {
if ((port==0x20) && (val==0x20)) {
- if (lpDosTask->current) {
+ if (current_event) {
/* EOI (End Of Interrupt) */
TRACE_(int)("received EOI for current IRQ, clearing\n");
- event = lpDosTask->current;
- lpDosTask->current = event->next;
+ event = current_event;
+ current_event = event->next;
if (event->relay)
- (*event->relay)(lpDosTask,NULL,event->data);
+ (*event->relay)(NULL,event->data);
free(event);
- if (lpDosTask->pending &&
- !lpDosTask->sig_sent) {
+ if (pending_event &&
+ !sig_sent) {
/* another event is pending, which we should probably
* be able to process now, so tell dosmod about it */
TRACE_(int)("another event pending, signalling dosmod\n");
- kill(lpDosTask->task,SIGUSR2);
- lpDosTask->sig_sent++;
+ kill(dosmod_pid,SIGUSR2);
+ sig_sent++;
}
} else {
WARN_(int)("EOI without active IRQ\n");
@@ -570,27 +553,25 @@
} else {
FIXME_(int)("unrecognized PIC command %02x\n",val);
}
- }
}
void DOSVM_SetTimer( unsigned ticks )
{
- LPDOSTASK lpDosTask = MZ_Current();
int stat=DOSMOD_SET_TIMER;
struct timeval tim;
- if (lpDosTask) {
+ if (MZ_Current()) {
/* the PC clocks ticks at 1193180 Hz */
tim.tv_sec=0;
tim.tv_usec=((unsigned long long)ticks*1000000)/1193180;
/* sanity check */
if (!tim.tv_usec) tim.tv_usec=1;
- if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+ if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return;
}
- if (write(lpDosTask->write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
+ if (write(write_pipe,&tim,sizeof(tim))!=sizeof(tim)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return;
}
@@ -600,18 +581,17 @@
unsigned DOSVM_GetTimer( void )
{
- LPDOSTASK lpDosTask = MZ_Current();
int stat=DOSMOD_GET_TIMER;
struct timeval tim;
- if (lpDosTask) {
- if (write(lpDosTask->write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
+ if (MZ_Current()) {
+ if (write(write_pipe,&stat,sizeof(stat))!=sizeof(stat)) {
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return 0;
}
/* read response */
while (1) {
- if (read(lpDosTask->read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
+ if (read(read_pipe,&tim,sizeof(tim))==sizeof(tim)) break;
if ((errno==EINTR)||(errno==EAGAIN)) continue;
ERR_(module)("dosmod sync lost, errno=%d\n",errno);
return 0;
@@ -621,47 +601,6 @@
return 0;
}
-void DOSVM_SetSystemData( int id, void *data )
-{
- LPDOSTASK lpDosTask = MZ_Current();
- DOSSYSTEM *sys, *prev;
-
- if (lpDosTask) {
- sys = lpDosTask->sys;
- prev = NULL;
- while (sys && (sys->id != id)) {
- prev = sys;
- sys = sys->next;
- }
- if (sys) {
- free(sys->data);
- sys->data = data;
- } else {
- sys = malloc(sizeof(DOSSYSTEM));
- sys->id = id;
- sys->data = data;
- sys->next = NULL;
- if (prev) prev->next = sys;
- else lpDosTask->sys = sys;
- }
- } else free(data);
-}
-
-void* DOSVM_GetSystemData( int id )
-{
- LPDOSTASK lpDosTask = MZ_Current();
- DOSSYSTEM *sys;
-
- if (lpDosTask) {
- sys = lpDosTask->sys;
- while (sys && (sys->id != id))
- sys = sys->next;
- if (sys)
- return sys->data;
- }
- return NULL;
-}
-
#else /* !MZ_SUPPORTED */
int DOSVM_Enter( CONTEXT86 *context )
@@ -674,15 +613,13 @@
void DOSVM_PIC_ioport_out( WORD port, BYTE val) {}
void DOSVM_SetTimer( unsigned ticks ) {}
unsigned DOSVM_GetTimer( void ) { return 0; }
-void DOSVM_SetSystemData( int id, void *data ) { free(data); }
-void* DOSVM_GetSystemData( int id ) { return NULL; }
-void DOSVM_QueueEvent( int irq, int priority, void (*relay)(LPDOSTASK,CONTEXT86*,void*), void *data)
+void DOSVM_QueueEvent( int irq, int priority, void (*relay)(CONTEXT86*,void*), void *data)
{
if (irq<0) {
/* callback event, perform it with dummy context */
CONTEXT86 context;
memset(&context,0,sizeof(context));
- (*relay)(NULL,&context,data);
+ (*relay)(&context,data);
} else {
ERR_(int)("IRQ without DOS task: should not happen");
}
diff --git a/loader/dos/module.c b/loader/dos/module.c
index f75d85a..3636cb4 100644
--- a/loader/dos/module.c
+++ b/loader/dos/module.c
@@ -37,6 +37,8 @@
DEFAULT_DEBUG_CHANNEL(module);
+static LPDOSTASK dos_current;
+
#ifdef MZ_SUPPORTED
#ifdef HAVE_SYS_MMAN_H
@@ -48,15 +50,21 @@
#undef MZ_MAPSELF
#define BIOS_DATA_SEGMENT 0x40
-#define START_OFFSET 0
#define PSP_SIZE 0x10
#define SEG16(ptr,seg) ((LPVOID)((BYTE*)ptr+((DWORD)(seg)<<4)))
#define SEGPTR16(ptr,segptr) ((LPVOID)((BYTE*)ptr+((DWORD)SELECTOROF(segptr)<<4)+OFFSETOF(segptr)))
-static LPDOSTASK dos_current;
+static WORD init_cs,init_ip,init_ss,init_sp;
+static char mm_name[128];
+
+int read_pipe, write_pipe;
+HANDLE hReadPipe, hWritePipe;
+pid_t dosmod_pid;
static void MZ_Launch(void);
+static BOOL MZ_InitTask(void);
+static void MZ_KillTask(void);
static void MZ_CreatePSP( LPVOID lpPSP, WORD env )
{
@@ -107,68 +115,18 @@
0xCF /* iret */
};
-static void MZ_InitHandlers( LPDOSTASK lpDosTask )
+static void MZ_InitHandlers(void)
{
WORD seg;
LPBYTE start=DOSMEM_GetBlock(sizeof(int08),&seg);
memcpy(start,int08,sizeof(int08));
/* INT 08: point it at our tick-incrementing handler */
- ((SEGPTR*)(lpDosTask->img))[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0);
+ ((SEGPTR*)0)[0x08]=PTR_SEG_OFF_TO_SEGPTR(seg,0);
/* INT 1C: just point it to IRET, we don't want to handle it ourselves */
- ((SEGPTR*)(lpDosTask->img))[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1);
+ ((SEGPTR*)0)[0x1C]=PTR_SEG_OFF_TO_SEGPTR(seg,sizeof(int08)-1);
}
-static char enter_xms[]={
-/* XMS hookable entry point */
- 0xEB,0x03, /* jmp entry */
- 0x90,0x90,0x90, /* nop;nop;nop */
- /* entry: */
-/* real entry point */
-/* for simplicity, we'll just use the same hook as DPMI below */
- 0xCD,0x31, /* int $0x31 */
- 0xCB /* lret */
-};
-
-static void MZ_InitXMS( LPDOSTASK lpDosTask )
-{
- LPBYTE start=DOSMEM_GetBlock(sizeof(enter_xms),&(lpDosTask->xms_seg));
- memcpy(start,enter_xms,sizeof(enter_xms));
-}
-
-static char enter_pm[]={
- 0x50, /* pushw %ax */
- 0x52, /* pushw %dx */
- 0x55, /* pushw %bp */
- 0x89,0xE5, /* movw %sp,%bp */
-/* get return CS */
- 0x8B,0x56,0x08, /* movw 8(%bp),%dx */
-/* just call int 31 here to get into protected mode... */
-/* it'll check whether it was called from dpmi_seg... */
- 0xCD,0x31, /* int $0x31 */
-/* we are now in the context of a 16-bit relay call */
-/* need to fixup our stack;
- * 16-bit relay return address will be lost, but we won't worry quite yet */
- 0x8E,0xD0, /* movw %ax,%ss */
- 0x66,0x0F,0xB7,0xE5, /* movzwl %bp,%esp */
-/* set return CS */
- 0x89,0x56,0x08, /* movw %dx,8(%bp) */
- 0x5D, /* popw %bp */
- 0x5A, /* popw %dx */
- 0x58, /* popw %ax */
- 0xCB /* lret */
-};
-
-static void MZ_InitDPMI( LPDOSTASK lpDosTask )
-{
- unsigned size=sizeof(enter_pm);
- LPBYTE start=DOSMEM_GetBlock(size,&(lpDosTask->dpmi_seg));
-
- lpDosTask->dpmi_sel = SELECTOR_AllocBlock( start, size, SEGMENT_CODE, FALSE, FALSE );
-
- memcpy(start,enter_pm,sizeof(enter_pm));
-}
-
-static WORD MZ_InitEnvironment( LPDOSTASK lpDosTask, LPCSTR env, LPCSTR name )
+static WORD MZ_InitEnvironment( LPCSTR env, LPCSTR name )
{
unsigned sz=0;
WORD seg;
@@ -191,39 +149,33 @@
return seg;
}
-static BOOL MZ_InitMemory( LPDOSTASK lpDosTask )
+static BOOL MZ_InitMemory(void)
{
- if (lpDosTask->img) return TRUE; /* already allocated */
+ int mm_fd;
+ void *img_base;
- /* allocate 1MB+64K shared memory */
- lpDosTask->img_ofs=START_OFFSET;
-#ifdef MZ_MAPSELF
- lpDosTask->img=VirtualAlloc(NULL,0x110000,MEM_COMMIT,PAGE_READWRITE);
- /* make sure mmap accepts it */
- ((char*)lpDosTask->img)[0x10FFFF]=0;
-#else
- tmpnam(lpDosTask->mm_name);
-/* strcpy(lpDosTask->mm_name,"/tmp/mydosimage"); */
- lpDosTask->mm_fd=open(lpDosTask->mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR);
- if (lpDosTask->mm_fd<0) ERR("file %s could not be opened\n",lpDosTask->mm_name);
- /* expand file to 1MB+64K */
- ftruncate(lpDosTask->mm_fd,0x110000);
- /* map it in */
- lpDosTask->img=mmap(NULL,0x110000-START_OFFSET,PROT_READ|PROT_WRITE,MAP_SHARED,lpDosTask->mm_fd,0);
-#endif
- if (lpDosTask->img==(LPVOID)-1) {
- ERR("could not map shared memory, error=%s\n",strerror(errno));
- return FALSE;
- }
- TRACE("DOS VM86 image mapped at %08lx\n",(DWORD)lpDosTask->img);
+ /* initialize the memory */
+ TRACE("Initializing DOS memory structures\n");
+ DOSMEM_Init(TRUE);
- /* initialize the memory */
- TRACE("Initializing DOS memory structures\n");
- DOSMEM_Init(TRUE);
- MZ_InitHandlers(lpDosTask);
- MZ_InitXMS(lpDosTask);
- MZ_InitDPMI(lpDosTask);
- return TRUE;
+ /* allocate 1MB+64K shared memory */
+ tmpnam(mm_name);
+ /* strcpy(mm_name,"/tmp/mydosimage"); */
+ mm_fd = open(mm_name,O_RDWR|O_CREAT /* |O_TRUNC */,S_IRUSR|S_IWUSR);
+ if (mm_fd < 0) ERR("file %s could not be opened\n",mm_name);
+ /* fill the file with the DOS memory */
+ if (write( mm_fd, NULL, 0x110000 ) != 0x110000) ERR("cannot write DOS mem\n");
+ /* map it in */
+ img_base = mmap(NULL,0x110000,PROT_READ|PROT_WRITE|PROT_EXEC,MAP_SHARED|MAP_FIXED,mm_fd,0);
+ close( mm_fd );
+
+ if (img_base)
+ {
+ ERR("could not map shared memory, error=%s\n",strerror(errno));
+ return FALSE;
+ }
+ MZ_InitHandlers();
+ return TRUE;
}
BOOL MZ_LoadImage( HMODULE module, HANDLE hFile, LPCSTR filename )
@@ -235,7 +187,7 @@
BYTE*psp_start,*load_start;
int x, old_com=0, alloc=0;
SEGPTR reloc;
- WORD env_seg;
+ WORD env_seg, load_seg;
DWORD len;
win_hdr->OptionalHeader.Subsystem = IMAGE_SUBSYSTEM_WINDOWS_CUI;
@@ -244,7 +196,6 @@
if (!lpDosTask) {
alloc=1;
lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
- lpDosTask->mm_fd = -1;
dos_current = lpDosTask;
}
@@ -269,10 +220,10 @@
max_size=image_size+((DWORD)mz_header.e_maxalloc<<4)+(PSP_SIZE<<4);
}
- MZ_InitMemory(lpDosTask);
+ MZ_InitMemory();
/* allocate environment block */
- env_seg=MZ_InitEnvironment(lpDosTask,GetEnvironmentStringsA(),filename);
+ env_seg=MZ_InitEnvironment(GetEnvironmentStringsA(),filename);
/* allocate memory for the executable */
TRACE("Allocating DOS memory (min=%ld, max=%ld)\n",min_size,max_size);
@@ -289,7 +240,7 @@
SetLastError(ERROR_NOT_ENOUGH_MEMORY);
goto load_error;
}
- lpDosTask->load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
+ load_seg=lpDosTask->psp_seg+(old_com?0:PSP_SIZE);
load_start=psp_start+(PSP_SIZE<<4);
MZ_CreatePSP(psp_start, env_seg);
@@ -311,19 +262,19 @@
SetLastError(ERROR_BAD_FORMAT);
goto load_error;
}
- *(WORD*)SEGPTR16(load_start,reloc)+=lpDosTask->load_seg;
+ *(WORD*)SEGPTR16(load_start,reloc)+=load_seg;
}
}
- lpDosTask->init_cs=lpDosTask->load_seg+mz_header.e_cs;
- lpDosTask->init_ip=mz_header.e_ip;
- lpDosTask->init_ss=lpDosTask->load_seg+mz_header.e_ss;
- lpDosTask->init_sp=mz_header.e_sp;
+ init_cs = load_seg+mz_header.e_cs;
+ init_ip = mz_header.e_ip;
+ init_ss = load_seg+mz_header.e_ss;
+ init_sp = mz_header.e_sp;
- TRACE("entry point: %04x:%04x\n",lpDosTask->init_cs,lpDosTask->init_ip);
+ TRACE("entry point: %04x:%04x\n",init_cs,init_ip);
- if (!MZ_InitTask(lpDosTask)) {
- MZ_KillTask(lpDosTask);
+ if (!MZ_InitTask()) {
+ MZ_KillTask();
SetLastError(ERROR_GEN_FAILURE);
return FALSE;
}
@@ -333,12 +284,7 @@
load_error:
if (alloc) {
dos_current = NULL;
- if (lpDosTask->mm_name[0]!=0) {
- if (lpDosTask->img!=NULL) munmap(lpDosTask->img,0x110000-START_OFFSET);
- if (lpDosTask->mm_fd>=0) close(lpDosTask->mm_fd);
- unlink(lpDosTask->mm_name);
- } else
- if (lpDosTask->img!=NULL) VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE);
+ if (mm_name[0]!=0) unlink(mm_name);
}
return FALSE;
@@ -349,14 +295,14 @@
LPDOSTASK lpDosTask = HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sizeof(DOSTASK));
if (lpDosTask) {
- lpDosTask->mm_fd = -1;
dos_current = lpDosTask;
- MZ_InitMemory(lpDosTask);
+ MZ_InitMemory();
+ MZ_InitTask();
}
return lpDosTask;
}
-static void MZ_InitTimer( LPDOSTASK lpDosTask, int ver )
+static void MZ_InitTimer( int ver )
{
if (ver<1) {
/* can't make timer ticks */
@@ -367,55 +313,42 @@
/* start dosmod timer at 55ms (18.2Hz) */
func=DOSMOD_SET_TIMER;
tim.tv_sec=0; tim.tv_usec=54925;
- write(lpDosTask->write_pipe,&func,sizeof(func));
- write(lpDosTask->write_pipe,&tim,sizeof(tim));
+ write(write_pipe,&func,sizeof(func));
+ write(write_pipe,&tim,sizeof(tim));
}
}
-BOOL MZ_InitTask( LPDOSTASK lpDosTask )
+static BOOL MZ_InitTask(void)
{
int write_fd[2],x_fd;
pid_t child;
- char *fname,*farg,arg[16],fproc[64],path[256],*fpath;
+ char path[256],*fpath;
- if (!lpDosTask) return FALSE;
/* create pipes */
- if (!CreatePipe(&(lpDosTask->hReadPipe),&(lpDosTask->hXPipe),NULL,0)) return FALSE;
+ if (!CreatePipe(&hReadPipe,&hWritePipe,NULL,0)) return FALSE;
if (pipe(write_fd)<0) {
- CloseHandle(lpDosTask->hReadPipe);
- CloseHandle(lpDosTask->hXPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
return FALSE;
}
- lpDosTask->read_pipe = FILE_GetUnixHandle( lpDosTask->hReadPipe, GENERIC_READ );
- x_fd = FILE_GetUnixHandle( lpDosTask->hXPipe, GENERIC_WRITE );
+ read_pipe = FILE_GetUnixHandle( hReadPipe, GENERIC_READ );
+ x_fd = FILE_GetUnixHandle( hWritePipe, GENERIC_WRITE );
TRACE("win32 pipe: read=%d, write=%d, unix pipe: read=%d, write=%d\n",
- lpDosTask->hReadPipe,lpDosTask->hXPipe,lpDosTask->read_pipe,x_fd);
+ hReadPipe,hWritePipe,read_pipe,x_fd);
TRACE("outbound unix pipe: read=%d, write=%d, pid=%d\n",write_fd[0],write_fd[1],getpid());
- lpDosTask->write_pipe=write_fd[1];
-
- lpDosTask->hConInput=GetStdHandle(STD_INPUT_HANDLE);
- lpDosTask->hConOutput=GetStdHandle(STD_OUTPUT_HANDLE);
-
- /* if we have a mapping file, use it */
- fname=lpDosTask->mm_name; farg=NULL;
- if (!fname[0]) {
- /* otherwise, map our own memory image */
- sprintf(fproc,"/proc/%d/mem",getpid());
- sprintf(arg,"%ld",(unsigned long)lpDosTask->img);
- fname=fproc; farg=arg;
- }
+ write_pipe=write_fd[1];
TRACE("Loading DOS VM support module\n");
if ((child=fork())<0) {
close(write_fd[0]);
- close(lpDosTask->read_pipe);
- close(lpDosTask->write_pipe);
+ close(read_pipe);
+ close(write_pipe);
close(x_fd);
- CloseHandle(lpDosTask->hReadPipe);
- CloseHandle(lpDosTask->hXPipe);
+ CloseHandle(hReadPipe);
+ CloseHandle(hWritePipe);
return FALSE;
}
if (child!=0) {
@@ -424,21 +357,21 @@
close(write_fd[0]);
close(x_fd);
- lpDosTask->task=child;
+ dosmod_pid = child;
/* wait for child process to signal readiness */
while (1) {
- if (read(lpDosTask->read_pipe,&ret,sizeof(ret))==sizeof(ret)) break;
+ if (read(read_pipe,&ret,sizeof(ret))==sizeof(ret)) break;
if ((errno==EINTR)||(errno==EAGAIN)) continue;
/* failure */
ERR("dosmod has failed to initialize\n");
- if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name);
+ if (mm_name[0]!=0) unlink(mm_name);
return FALSE;
}
/* the child has now mmaped the temp file, it's now safe to unlink.
* do it here to avoid leaving a mess in /tmp if/when Wine crashes... */
- if (lpDosTask->mm_name[0]!=0) unlink(lpDosTask->mm_name);
+ if (mm_name[0]!=0) unlink(mm_name);
/* start simulated system timer */
- MZ_InitTimer(lpDosTask,ret);
+ MZ_InitTimer(ret);
if (ret<2) {
ERR("dosmod version too old! Please install newer dosmod properly\n");
ERR("If you don't, the new dosmod event handling system will not work\n");
@@ -446,8 +379,8 @@
/* all systems are now go */
} else {
/* child process */
- close(lpDosTask->read_pipe);
- close(lpDosTask->write_pipe);
+ close(read_pipe);
+ close(write_pipe);
/* put our pipes somewhere dosmod can find them */
dup2(write_fd[0],0); /* stdin */
dup2(x_fd,1); /* stdout */
@@ -457,16 +390,16 @@
fpath=strrchr(strcpy(path,full_argv0),'/');
if (fpath) {
strcpy(fpath,"/dosmod");
- execl(path,fname,farg,NULL);
+ execl(path,mm_name,NULL);
strcpy(fpath,"/loader/dos/dosmod");
- execl(path,fname,farg,NULL);
+ execl(path,mm_name,NULL);
}
/* okay, it wasn't there, try in the path */
- execlp("dosmod",fname,farg,NULL);
+ execlp("dosmod",mm_name,NULL);
/* last desperate attempts: current directory */
- execl("dosmod",fname,farg,NULL);
+ execl("dosmod",mm_name,NULL);
/* and, just for completeness... */
- execl("loader/dos/dosmod",fname,farg,NULL);
+ execl("loader/dos/dosmod",mm_name,NULL);
/* if failure, exit */
ERR("Failed to spawn dosmod, error=%s\n",strerror(errno));
exit(1);
@@ -477,53 +410,29 @@
static void MZ_Launch(void)
{
LPDOSTASK lpDosTask = MZ_Current();
- BYTE *psp_start = (BYTE*)lpDosTask->img + ((DWORD)lpDosTask->psp_seg << 4);
+ CONTEXT context;
+ TDB *pTask = (TDB *)GlobalLock16( GetCurrentTask() );
+ BYTE *psp_start = PTR_REAL_TO_LIN( lpDosTask->psp_seg, 0 );
MZ_FillPSP(psp_start, GetCommandLineA());
+ pTask->flags |= TDBF_WINOLDAP;
- DOSVM_Enter(NULL);
+ memset( &context, 0, sizeof(context) );
+ context.SegCs = init_cs;
+ context.Eip = init_ip;
+ context.SegSs = init_ss;
+ context.Esp = init_sp;
+ context.SegDs = lpDosTask->psp_seg;
+ context.SegEs = lpDosTask->psp_seg;
+ context.EFlags = 0x00080000; /* virtual interrupt flag */
+ DOSVM_Enter( &context );
}
-void MZ_KillTask( LPDOSTASK lpDosTask )
+static void MZ_KillTask(void)
{
- DOSEVENT *event,*p_event;
- DOSSYSTEM *sys,*p_sys;
-
TRACE("killing DOS task\n");
VGA_Clean();
- if (lpDosTask->mm_name[0]!=0) {
- munmap(lpDosTask->img,0x110000-START_OFFSET);
- close(lpDosTask->mm_fd);
- } else VirtualFree(lpDosTask->img,0x110000,MEM_RELEASE);
- close(lpDosTask->read_pipe);
- close(lpDosTask->write_pipe);
- CloseHandle(lpDosTask->hReadPipe);
- CloseHandle(lpDosTask->hXPipe);
- kill(lpDosTask->task,SIGTERM);
-/* free memory allocated for events and systems */
-#define DFREE(var,pvar,svar) \
- var = lpDosTask->svar; \
- while (var) { \
- if (var->data) free(var->data); \
- pvar = var->next; free(var); var = pvar; \
- }
-
- DFREE(event,p_event,pending)
- DFREE(event,p_event,current)
- DFREE(sys,p_sys,sys)
-
-#undef DFREE
-
-#if 0
- /* FIXME: this seems to crash */
- if (lpDosTask->dpmi_sel)
- SELECTOR_FreeBlock(lpDosTask->dpmi_sel, 1);
-#endif
-}
-
-LPDOSTASK MZ_Current( void )
-{
- return dos_current;
+ kill(dosmod_pid,SIGTERM);
}
#else /* !MZ_SUPPORTED */
@@ -535,9 +444,15 @@
return FALSE;
}
-LPDOSTASK MZ_Current( void )
+LPDOSTASK MZ_AllocDPMITask( void )
{
- return NULL;
+ ERR("Actual real-mode calls not supported on this architecture!\n");
+ return NULL;
}
-#endif
+#endif /* !MZ_SUPPORTED */
+
+LPDOSTASK MZ_Current( void )
+{
+ return dos_current;
+}
diff --git a/loader/task.c b/loader/task.c
index adcee6a..6b29425 100644
--- a/loader/task.c
+++ b/loader/task.c
@@ -29,13 +29,13 @@
#include "winsock.h"
#include "syslevel.h"
#include "debugtools.h"
-#include "dosexe.h"
#include "services.h"
#include "server.h"
-DEFAULT_DEBUG_CHANNEL(task)
-DECLARE_DEBUG_CHANNEL(relay)
-DECLARE_DEBUG_CHANNEL(toolhelp)
+
+DEFAULT_DEBUG_CHANNEL(task);
+DECLARE_DEBUG_CHANNEL(relay);
+DECLARE_DEBUG_CHANNEL(toolhelp);
/* Min. number of thunks allocated when creating a new segment */
#define MIN_THUNKS 32
@@ -243,7 +243,6 @@
/* NOTE: for 16-bit tasks, the instance handles are updated later on
in NE_InitProcess */
}
- if (MZ_Current() && MZ_Current()->load_seg) pTask->flags |= TDBF_WINOLDAP;
pTask->version = pModule->expected_version;
pTask->hModule = pModule->self;