home *** CD-ROM | disk | FTP | other *** search
/ Internet MPEG Audio Archive / IMAA.mdf / util / dos / l3v100n / rsx / source / loadprg.c < prev    next >
C/C++ Source or Header  |  1994-01-19  |  11KB  |  365 lines

  1. /* This file is LOADPRG.C
  2. ** contains :
  3. **
  4. **              - loader for a.out programs (emx-format)
  5. **
  6. ** Copyright (c) Rainer Schnitker 92,93
  7. */
  8.  
  9. #include <stdio.h>
  10. #include <stdlib.h>
  11. #include <string.h>
  12. #include <io.h>
  13. #include <fcntl.h>
  14. #include <sys/types.h>
  15. #include <sys/stat.h>
  16. #ifdef __TURBOC__
  17. #define SH_DENYWR O_DENYWRITE            /* for Borland compiler */
  18. #else
  19. #include <share.h>
  20. #endif
  21.  
  22. #include "DPMI.H"
  23. #include "DPMI10.H"
  24. #include "DPMIDOS.H"
  25. #include "PROCESS.H"
  26. #include "GNUAOUT.H"
  27. #include "LOADPRG.H"
  28. #include "COPY32.H"
  29. #include "START32.H"
  30. #include "CDOSX32.H"
  31. #include "RSX.H"
  32. #include "DOSERRNO.H"
  33.  
  34. int skip_exe_hdr(int filehandle, DWORD * headoff)
  35. {
  36.     struct exe_hdr exehdr;
  37.     struct emx_hdr emxhdr;
  38.  
  39.     read(filehandle, &exehdr, sizeof(struct exe_hdr));
  40.  
  41.     if (exehdr.signatur == 0x5a4d) {    /* falls exe-kopf */
  42.     *headoff = ((DWORD) exehdr.hdr_para) * 16;
  43.     if (lseek(filehandle, *headoff, SEEK_SET) == -1)
  44.         goto fail;
  45.     read(filehandle, &emxhdr, sizeof(struct emx_hdr));
  46.     if (memcmp(emxhdr.sig, "emx", 3) == 0)
  47.         *headoff = emxhdr.next_hdr;
  48.     else {
  49.         *headoff = (DWORD) exehdr.high * 512L;
  50.         if (exehdr.low)
  51.         *headoff += (DWORD) exehdr.low - 512L;
  52.     }
  53.     }
  54.     if (lseek(filehandle, *headoff, SEEK_SET) == -1)
  55.     goto fail;
  56.     return 0;
  57.  
  58.   fail:
  59.     *headoff = 0;
  60.     lseek(filehandle, 0, SEEK_SET);
  61.     return -1;
  62. }
  63.  
  64. /*
  65. ** arguments and environment at process start
  66. **
  67. **    environment and argument strings
  68. **    argv[]
  69. **    envp[]
  70. **    pointer to env[0]
  71. **    pointer to argv[0]
  72. **    int argc
  73. **    <- ESP
  74. */
  75. int argvenv(int argc, char **argv, int envc, char **env, NEWPROCESS * proc)
  76. {
  77.     int i;
  78.     DWORD len, stkp;
  79.     DWORD *vectors;
  80.     WORD count = 3;        /* 0=argc 1=argv 2=env */
  81.  
  82.     vectors = (DWORD *) iobuf;
  83.  
  84.     stkp = proc->stackp32;
  85.  
  86.     /* store env strings in user stack, built vectors */
  87.     for (i = 0; i < envc; i++) {
  88.     len = (DWORD) (WORD) strlen(env[i]) + 1;
  89.     stkp -= len;
  90.     stkp &= ~3L;        /* align4 */
  91.     cpy16_32(proc->data32sel, stkp, env[i], len);
  92.     vectors[count++] = stkp;
  93.     }
  94.     vectors[count++] = 0;    /* last is a NULL pointer */
  95.  
  96.     /* store arg strings in user stack, built vectors */
  97.     for (i = 0; i < argc; i++) {
  98.     len = (DWORD) (WORD) strlen(argv[i]) + 1;
  99.     stkp -= len;
  100.     stkp &= ~3L;        /* align4 */
  101.     cpy16_32(proc->data32sel, stkp, argv[i], len);
  102.     vectors[count] = stkp;
  103.     count++;
  104.     }
  105.     vectors[count++] = 0;    /* last is a NULL pointer */
  106.  
  107.     len = (DWORD) (count * sizeof(long));
  108.     stkp -= len;
  109.     vectors[0] = argc;
  110.     vectors[1] = stkp + (4L + envc) * sizeof(long);    /* & vectors[3+nenvp+1] */
  111.     vectors[2] = stkp + 3 * sizeof(long);    /* & vectors[3] */
  112.     cpy16_32(proc->data32sel, stkp, vectors, len);
  113.  
  114.     if (proc->p_flags & PF_EMX_FILE)
  115.     stkp += 3*4;
  116.  
  117.     proc->stackp32 = stkp;
  118.     return 0;
  119. }
  120.  
  121.  
  122. int readin_file(short r_bx, short r_ds, long r_edx, long r_ecx)
  123. {
  124.     long count;
  125.  
  126.     count = r_ecx;
  127.     tr.ebx = (DWORD) (WORD) r_bx;
  128.     tr.edx = (DWORD) (WORD) iobuf;
  129.     while (count > 0) {        /* bytes left */
  130.     tr.eax = 0x3F00L;
  131.     tr.ecx = (count <= IOBUF_SIZE) ? count : (DWORD) IOBUF_SIZE;
  132.  
  133.     if (realdos())
  134.         return -1;
  135.  
  136.     cpy16_32(r_ds, r_edx, iobuf, tr.eax);
  137.     count -= tr.eax;
  138.     if ((WORD) tr.ecx != (WORD) tr.eax)
  139.         break;
  140.     r_edx += tr.eax;
  141.     }
  142.  
  143.     return 0;
  144. }
  145.  
  146. /*
  147. **
  148. ** RSX program layout:
  149. **
  150. **
  151. **  DPMI 0.9 :     fixed stack
  152. **         never ending heap
  153. **
  154. **  emx style
  155. **  |--------------------------------------------------------------
  156. **  |stack|    code    |  data/bss  |  stack,if>64KB |    heap -> ...
  157. **  |--------------------------------------------------------------
  158. **  0      ^64 KB       ^(n x 64KB)
  159. **
  160. **
  161. **  old djgpp style
  162. **  |--------------------------------------------------------------
  163. **  |    |    code     | stack    |  data/bss  | heap -> ...
  164. **  |--------------------------------------------------------------
  165. **  0    ^4K                ^0x400000
  166. **
  167. **  djgpp style 1.11
  168. **  |--------------------------------------------------------------
  169. **  |  code    |  data/bss  | stack  | heap -> ...
  170. **  |--------------------------------------------------------------
  171. **  0        ^ 4 Kb align ^
  172. **
  173. **
  174. **
  175. **  DPMI 1.0 :     address room = 64 MegaBytes (default value)
  176. **         first page read only ( NULL pointers )
  177. **
  178. **  |--------------------------------------------...-----------------------
  179. **  | R/O |    code    |  data/bss  |  heap ->          <- stack    | mappings
  180. **  |--------------------------------------------...-----------------------
  181. **  0                                ^64 MB
  182. **       ( not implemented in this version )
  183. **
  184. */
  185.  
  186. #define DEFAULT_STACK (0x10000L-0x1000L)    /* 64 KB - one R/O page */
  187.  
  188. int load_protected_program(char *filename, NEWPROCESS * proc)
  189. {
  190.     GNUOUT aout_hdr;
  191.     DWORD segment_size, n_txtaddr, _n_hdroff;
  192.     DWORD textsegm, datasegm, stacksegm;
  193.     DWORD headoff;
  194.     WORD stack32sel;
  195.     int fhandle;
  196.  
  197.     fhandle = sopen(filename, O_RDONLY | O_BINARY, SH_DENYWR, S_IREAD | S_IWRITE);
  198.     if (fhandle == -1)
  199.     return doserror_to_errno(_doserrno);
  200.  
  201.     /* skip exe-header, return correct offset in file */
  202.     headoff = 0;
  203.     skip_exe_hdr(fhandle, &headoff);
  204.  
  205.     /* read gnu aout header */
  206.     read(fhandle, &aout_hdr, sizeof(aout_hdr));
  207.  
  208.     /* test header */
  209.     if ((WORD) aout_hdr.a_info == 0x14C) {
  210.     lseek(fhandle, headoff + 20, 0);
  211.     read(fhandle, &aout_hdr, sizeof(aout_hdr));
  212.     aout_hdr.a_entry = aout_hdr.a_syms;
  213.     }
  214.     if ((WORD) aout_hdr.a_info != 0x10b) {
  215.     close(fhandle);
  216.     return EMX_ENOEXEC;
  217.     }
  218.  
  219.     /* dynamic a.out loading for emx or dj files */
  220.     if (aout_hdr.a_entry == 0x10000) {
  221.     proc->p_flags |= PF_EMX_FILE;
  222.     segment_size = 0x10000L;
  223.     _n_hdroff = (1024 - sizeof(struct exec));
  224.     n_txtaddr = 0x10000L;
  225.     } else if (aout_hdr.a_entry == 0x1020) {
  226.     proc->p_flags |= PF_DJGPP_FILE;
  227.     segment_size = 0x400000L;
  228.     _n_hdroff = 0;
  229.     n_txtaddr = 0x1020L;
  230.     } else if (aout_hdr.a_entry == 0x10A8) {
  231.     proc->p_flags |= PF_DJGPP_FILE;
  232.     segment_size = 0x1000L;
  233.     _n_hdroff = 16 + 3 * 40;/* add FILEHDR and SCNHDR */
  234.     n_txtaddr = 0x10A8L;
  235.     } else {
  236.     close(fhandle);
  237.     return EMX_ENOEXEC;
  238.     }
  239.  
  240.     /* compute size of text,data&stack segment for AllocMem() */
  241.     textsegm = (aout_hdr.a_entry + aout_hdr.a_text + SEGMENT_SIZE - 1L)
  242.     & ~(SEGMENT_SIZE - 1L);
  243.     datasegm = (aout_hdr.a_data + aout_hdr.a_bss + 4095L) & ~4095L;
  244.     if (opt_stackval)
  245.     stacksegm = (DWORD) opt_stackval *1024;
  246.     else
  247.     stacksegm = DEFAULT_STACK;
  248.  
  249.     if (proc == &RSX_PROCESS)
  250.     stacksegm = DEFAULT_STACK;
  251.  
  252.     /* define start-, endaddresses */
  253.     proc->text_start = N_TXTADDR(aout_hdr);
  254.     proc->text_end = (N_TXTADDR(aout_hdr) + aout_hdr.a_text + 4095L) & ~4095L;
  255.     proc->data_start = N_DATADDR(aout_hdr);
  256.     proc->data_end = N_DATADDR(aout_hdr) + datasegm;
  257.     proc->entry = aout_hdr.a_entry;
  258.  
  259.     /* look for empty space for stack */
  260.     if (aout_hdr.a_entry == 0x10000L && stacksegm <= DEFAULT_STACK) {
  261.     stacksegm = 0;
  262.     /* place stack in the first 64KB segment */
  263.     proc->stack_top = proc->text_start;
  264.     proc->stack_down = 0x1000L;
  265.     } else if (aout_hdr.a_entry == 0x1020L
  266.            && stacksegm <= (proc->data_start - proc->text_end)) {
  267.     stacksegm = 0;
  268.     /* place stack between code and data */
  269.     proc->stack_top = proc->data_start;
  270.     proc->stack_down = proc->text_end + 0x1000;
  271.     } else {
  272.     /* put stack after data/bss */
  273.     proc->stack_top = proc->data_end + stacksegm;
  274.     proc->stack_down = proc->data_end;
  275.  
  276.     /* sorry, work around window bug */
  277.     if ((proc->p_flags & PF_DJGPP_FILE) && proc->stack_down <= 0x11000L) {
  278.         DWORD add_stack = 0x11000L - proc->stack_down;
  279.         proc->stack_top += add_stack;
  280.         proc->stack_down += add_stack;
  281.         stacksegm += add_stack;
  282.     }
  283.     }
  284.  
  285.     proc->stacksize = proc->stack_top - proc->stack_down;
  286.     proc->stackp32 = proc->stack_top - 4L;
  287.  
  288.     proc->init_brk = proc->data_end + stacksegm;
  289.     proc->brk_value = proc->init_brk;
  290.     proc->pagefree = 0;
  291.  
  292.     /* enable first two emx sbrk calls, if heap after bss */
  293.     if (proc->init_brk == proc->data_end &&
  294.     (proc->data_start + aout_hdr.a_data + aout_hdr.a_bss + 8)
  295.     <= proc->data_end) {
  296.     proc->init_brk -= 8;
  297.     proc->brk_value -= 8;
  298.     proc->pagefree = 8;
  299.     }
  300.     /* MEMORY per DPMI besorgen */
  301.     proc->membytes = datasegm + textsegm + stacksegm;
  302.  
  303.     /* since dosmem isn't used by DPMI we put rsx387 in dos memory */
  304.     if (proc == &RSX_PROCESS && rsx387_in_dosmem) {
  305.     WORD segment, selectors;
  306.     if (AllocDosMem((WORD) (proc->membytes >> 4), &segment, &selectors))
  307.         return EMX_ENOMEM;
  308.     proc->memaddress = (DWORD) segment << 4;
  309.     proc->memhandle = (DWORD) selectors;
  310.     } else if (AllocMem(proc->membytes, &(proc->memhandle), &(proc->memaddress)))
  311.     return EMX_ENOMEM;
  312.  
  313.     /* alloc 32bit cs,ds ldt selector */
  314.     if (AllocLDT(3, &(proc->code32sel)))
  315.     return EMX_EIO;
  316.     proc->data32sel = proc->code32sel + sel_incr;
  317.     stack32sel = proc->data32sel + sel_incr;
  318.  
  319.     /* fill descriptors */
  320.     SetBaseAddress(proc->code32sel, proc->memaddress);
  321.     SetBaseAddress(proc->data32sel, proc->memaddress);
  322.     SetBaseAddress(stack32sel, proc->memaddress);
  323.     SetAccess(proc->code32sel, APP_CODE_SEL, DEFAULT_BIT);
  324.     SetAccess(proc->data32sel, APP_DATA_SEL, BIG_BIT);
  325.     SetAccess(stack32sel, APP_DATA_SEL | EXPAND_BIT, BIG_BIT | GRANULAR_BIT);
  326.  
  327.     /* allow execute data & stack  (DJGPP / GDB? need this) */
  328.     SetLimit(proc->code32sel, proc->membytes - 1L);
  329.  
  330.     /* allow mem access (sorry, this destroy protection) */
  331.     if (opt_memaccess)
  332.     SetLimit(proc->data32sel, 0xFFFFFFFF);
  333.     else
  334.     SetLimit(proc->data32sel, proc->membytes - 1L);
  335.  
  336.     /* set stack expand down segment to first stack address */
  337.     SetLimit(stack32sel, proc->stack_down - 1L);
  338.  
  339.  
  340.     /* read in code */
  341.     lseek(fhandle, headoff + N_TXTOFF(aout_hdr), SEEK_SET);
  342.     readin_file(fhandle, proc->data32sel, N_TXTADDR(aout_hdr), aout_hdr.a_text);
  343.  
  344.     /* read in data,bss */
  345.     lseek(fhandle, headoff + N_DATOFF(aout_hdr), SEEK_SET);
  346.     readin_file(fhandle, proc->data32sel, N_DATADDR(aout_hdr),
  347.         aout_hdr.a_data + aout_hdr.a_bss);
  348.  
  349.     close(fhandle);
  350.  
  351.     /* zero bss segment */
  352.     if (aout_hdr.a_bss)
  353.     bzero32(proc->data32sel, N_BSSADDR(aout_hdr), aout_hdr.a_bss);
  354.  
  355.     /* if dpmi 1.0, set first page read-only */
  356.     if (dpmi10) {
  357.     WORD page0;
  358.     GetPageAttibutes(proc->memhandle, 0L, 1, &page0);
  359.     page0 &= ~8;        /* mask out read/write */
  360.     ModifyPageAttibutes(proc->memhandle, 0L, 1, &page0);
  361.     }
  362.  
  363.     return 0;
  364. }
  365.