home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Internet MPEG Audio Archive
/
IMAA.mdf
/
util
/
dos
/
l3v100n
/
rsx
/
source
/
loadprg.c
< prev
next >
Wrap
C/C++ Source or Header
|
1994-01-19
|
11KB
|
365 lines
/* This file is LOADPRG.C
** contains :
**
** - loader for a.out programs (emx-format)
**
** Copyright (c) Rainer Schnitker 92,93
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <io.h>
#include <fcntl.h>
#include <sys/types.h>
#include <sys/stat.h>
#ifdef __TURBOC__
#define SH_DENYWR O_DENYWRITE /* for Borland compiler */
#else
#include <share.h>
#endif
#include "DPMI.H"
#include "DPMI10.H"
#include "DPMIDOS.H"
#include "PROCESS.H"
#include "GNUAOUT.H"
#include "LOADPRG.H"
#include "COPY32.H"
#include "START32.H"
#include "CDOSX32.H"
#include "RSX.H"
#include "DOSERRNO.H"
int skip_exe_hdr(int filehandle, DWORD * headoff)
{
struct exe_hdr exehdr;
struct emx_hdr emxhdr;
read(filehandle, &exehdr, sizeof(struct exe_hdr));
if (exehdr.signatur == 0x5a4d) { /* falls exe-kopf */
*headoff = ((DWORD) exehdr.hdr_para) * 16;
if (lseek(filehandle, *headoff, SEEK_SET) == -1)
goto fail;
read(filehandle, &emxhdr, sizeof(struct emx_hdr));
if (memcmp(emxhdr.sig, "emx", 3) == 0)
*headoff = emxhdr.next_hdr;
else {
*headoff = (DWORD) exehdr.high * 512L;
if (exehdr.low)
*headoff += (DWORD) exehdr.low - 512L;
}
}
if (lseek(filehandle, *headoff, SEEK_SET) == -1)
goto fail;
return 0;
fail:
*headoff = 0;
lseek(filehandle, 0, SEEK_SET);
return -1;
}
/*
** arguments and environment at process start
**
** environment and argument strings
** argv[]
** envp[]
** pointer to env[0]
** pointer to argv[0]
** int argc
** <- ESP
*/
int argvenv(int argc, char **argv, int envc, char **env, NEWPROCESS * proc)
{
int i;
DWORD len, stkp;
DWORD *vectors;
WORD count = 3; /* 0=argc 1=argv 2=env */
vectors = (DWORD *) iobuf;
stkp = proc->stackp32;
/* store env strings in user stack, built vectors */
for (i = 0; i < envc; i++) {
len = (DWORD) (WORD) strlen(env[i]) + 1;
stkp -= len;
stkp &= ~3L; /* align4 */
cpy16_32(proc->data32sel, stkp, env[i], len);
vectors[count++] = stkp;
}
vectors[count++] = 0; /* last is a NULL pointer */
/* store arg strings in user stack, built vectors */
for (i = 0; i < argc; i++) {
len = (DWORD) (WORD) strlen(argv[i]) + 1;
stkp -= len;
stkp &= ~3L; /* align4 */
cpy16_32(proc->data32sel, stkp, argv[i], len);
vectors[count] = stkp;
count++;
}
vectors[count++] = 0; /* last is a NULL pointer */
len = (DWORD) (count * sizeof(long));
stkp -= len;
vectors[0] = argc;
vectors[1] = stkp + (4L + envc) * sizeof(long); /* & vectors[3+nenvp+1] */
vectors[2] = stkp + 3 * sizeof(long); /* & vectors[3] */
cpy16_32(proc->data32sel, stkp, vectors, len);
if (proc->p_flags & PF_EMX_FILE)
stkp += 3*4;
proc->stackp32 = stkp;
return 0;
}
int readin_file(short r_bx, short r_ds, long r_edx, long r_ecx)
{
long count;
count = r_ecx;
tr.ebx = (DWORD) (WORD) r_bx;
tr.edx = (DWORD) (WORD) iobuf;
while (count > 0) { /* bytes left */
tr.eax = 0x3F00L;
tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
if (realdos())
return -1;
cpy16_32(r_ds, r_edx, iobuf, tr.eax);
count -= tr.eax;
if ((WORD) tr.ecx != (WORD) tr.eax)
break;
r_edx += tr.eax;
}
return 0;
}
/*
**
** RSX program layout:
**
**
** DPMI 0.9 : fixed stack
** never ending heap
**
** emx style
** |--------------------------------------------------------------
** |stack| code | data/bss | stack,if>64KB | heap -> ...
** |--------------------------------------------------------------
** 0 ^64 KB ^(n x 64KB)
**
**
** old djgpp style
** |--------------------------------------------------------------
** | | code | stack | data/bss | heap -> ...
** |--------------------------------------------------------------
** 0 ^4K ^0x400000
**
** djgpp style 1.11
** |--------------------------------------------------------------
** | code | data/bss | stack | heap -> ...
** |--------------------------------------------------------------
** 0 ^ 4 Kb align ^
**
**
**
** DPMI 1.0 : address room = 64 MegaBytes (default value)
** first page read only ( NULL pointers )
**
** |--------------------------------------------...-----------------------
** | R/O | code | data/bss | heap -> <- stack | mappings
** |--------------------------------------------...-----------------------
** 0 ^64 MB
** ( not implemented in this version )
**
*/
#define DEFAULT_STACK (0x10000L-0x1000L) /* 64 KB - one R/O page */
int load_protected_program(char *filename, NEWPROCESS * proc)
{
GNUOUT aout_hdr;
DWORD segment_size, n_txtaddr, _n_hdroff;
DWORD textsegm, datasegm, stacksegm;
DWORD headoff;
WORD stack32sel;
int fhandle;
fhandle = sopen(filename, O_RDONLY | O_BINARY, SH_DENYWR, S_IREAD | S_IWRITE);
if (fhandle == -1)
return doserror_to_errno(_doserrno);
/* skip exe-header, return correct offset in file */
headoff = 0;
skip_exe_hdr(fhandle, &headoff);
/* read gnu aout header */
read(fhandle, &aout_hdr, sizeof(aout_hdr));
/* test header */
if ((WORD) aout_hdr.a_info == 0x14C) {
lseek(fhandle, headoff + 20, 0);
read(fhandle, &aout_hdr, sizeof(aout_hdr));
aout_hdr.a_entry = aout_hdr.a_syms;
}
if ((WORD) aout_hdr.a_info != 0x10b) {
close(fhandle);
return EMX_ENOEXEC;
}
/* dynamic a.out loading for emx or dj files */
if (aout_hdr.a_entry == 0x10000) {
proc->p_flags |= PF_EMX_FILE;
segment_size = 0x10000L;
_n_hdroff = (1024 - sizeof(struct exec));
n_txtaddr = 0x10000L;
} else if (aout_hdr.a_entry == 0x1020) {
proc->p_flags |= PF_DJGPP_FILE;
segment_size = 0x400000L;
_n_hdroff = 0;
n_txtaddr = 0x1020L;
} else if (aout_hdr.a_entry == 0x10A8) {
proc->p_flags |= PF_DJGPP_FILE;
segment_size = 0x1000L;
_n_hdroff = 16 + 3 * 40;/* add FILEHDR and SCNHDR */
n_txtaddr = 0x10A8L;
} else {
close(fhandle);
return EMX_ENOEXEC;
}
/* compute size of text,data&stack segment for AllocMem() */
textsegm = (aout_hdr.a_entry + aout_hdr.a_text + SEGMENT_SIZE - 1L)
& ~(SEGMENT_SIZE - 1L);
datasegm = (aout_hdr.a_data + aout_hdr.a_bss + 4095L) & ~4095L;
if (opt_stackval)
stacksegm = (DWORD) opt_stackval *1024;
else
stacksegm = DEFAULT_STACK;
if (proc == &RSX_PROCESS)
stacksegm = DEFAULT_STACK;
/* define start-, endaddresses */
proc->text_start = N_TXTADDR(aout_hdr);
proc->text_end = (N_TXTADDR(aout_hdr) + aout_hdr.a_text + 4095L) & ~4095L;
proc->data_start = N_DATADDR(aout_hdr);
proc->data_end = N_DATADDR(aout_hdr) + datasegm;
proc->entry = aout_hdr.a_entry;
/* look for empty space for stack */
if (aout_hdr.a_entry == 0x10000L && stacksegm <= DEFAULT_STACK) {
stacksegm = 0;
/* place stack in the first 64KB segment */
proc->stack_top = proc->text_start;
proc->stack_down = 0x1000L;
} else if (aout_hdr.a_entry == 0x1020L
&& stacksegm <= (proc->data_start - proc->text_end)) {
stacksegm = 0;
/* place stack between code and data */
proc->stack_top = proc->data_start;
proc->stack_down = proc->text_end + 0x1000;
} else {
/* put stack after data/bss */
proc->stack_top = proc->data_end + stacksegm;
proc->stack_down = proc->data_end;
/* sorry, work around window bug */
if ((proc->p_flags & PF_DJGPP_FILE) && proc->stack_down <= 0x11000L) {
DWORD add_stack = 0x11000L - proc->stack_down;
proc->stack_top += add_stack;
proc->stack_down += add_stack;
stacksegm += add_stack;
}
}
proc->stacksize = proc->stack_top - proc->stack_down;
proc->stackp32 = proc->stack_top - 4L;
proc->init_brk = proc->data_end + stacksegm;
proc->brk_value = proc->init_brk;
proc->pagefree = 0;
/* enable first two emx sbrk calls, if heap after bss */
if (proc->init_brk == proc->data_end &&
(proc->data_start + aout_hdr.a_data + aout_hdr.a_bss + 8)
<= proc->data_end) {
proc->init_brk -= 8;
proc->brk_value -= 8;
proc->pagefree = 8;
}
/* MEMORY per DPMI besorgen */
proc->membytes = datasegm + textsegm + stacksegm;
/* since dosmem isn't used by DPMI we put rsx387 in dos memory */
if (proc == &RSX_PROCESS && rsx387_in_dosmem) {
WORD segment, selectors;
if (AllocDosMem((WORD) (proc->membytes >> 4), &segment, &selectors))
return EMX_ENOMEM;
proc->memaddress = (DWORD) segment << 4;
proc->memhandle = (DWORD) selectors;
} else if (AllocMem(proc->membytes, &(proc->memhandle), &(proc->memaddress)))
return EMX_ENOMEM;
/* alloc 32bit cs,ds ldt selector */
if (AllocLDT(3, &(proc->code32sel)))
return EMX_EIO;
proc->data32sel = proc->code32sel + sel_incr;
stack32sel = proc->data32sel + sel_incr;
/* fill descriptors */
SetBaseAddress(proc->code32sel, proc->memaddress);
SetBaseAddress(proc->data32sel, proc->memaddress);
SetBaseAddress(stack32sel, proc->memaddress);
SetAccess(proc->code32sel, APP_CODE_SEL, DEFAULT_BIT);
SetAccess(proc->data32sel, APP_DATA_SEL, BIG_BIT);
SetAccess(stack32sel, APP_DATA_SEL | EXPAND_BIT, BIG_BIT | GRANULAR_BIT);
/* allow execute data & stack (DJGPP / GDB? need this) */
SetLimit(proc->code32sel, proc->membytes - 1L);
/* allow mem access (sorry, this destroy protection) */
if (opt_memaccess)
SetLimit(proc->data32sel, 0xFFFFFFFF);
else
SetLimit(proc->data32sel, proc->membytes - 1L);
/* set stack expand down segment to first stack address */
SetLimit(stack32sel, proc->stack_down - 1L);
/* read in code */
lseek(fhandle, headoff + N_TXTOFF(aout_hdr), SEEK_SET);
readin_file(fhandle, proc->data32sel, N_TXTADDR(aout_hdr), aout_hdr.a_text);
/* read in data,bss */
lseek(fhandle, headoff + N_DATOFF(aout_hdr), SEEK_SET);
readin_file(fhandle, proc->data32sel, N_DATADDR(aout_hdr),
aout_hdr.a_data + aout_hdr.a_bss);
close(fhandle);
/* zero bss segment */
if (aout_hdr.a_bss)
bzero32(proc->data32sel, N_BSSADDR(aout_hdr), aout_hdr.a_bss);
/* if dpmi 1.0, set first page read-only */
if (dpmi10) {
WORD page0;
GetPageAttibutes(proc->memhandle, 0L, 1, &page0);
page0 &= ~8; /* mask out read/write */
ModifyPageAttibutes(proc->memhandle, 0L, 1, &page0);
}
return 0;
}