2 * Copyright (c) 1992, 1993, 1996
3 * Berkeley Software Design, Inc. All rights reserved.
5 * Redistribution and use in source and binary forms, with or without
6 * modification, are permitted provided that the following conditions
8 * 1. Redistributions of source code must retain the above copyright
9 * notice, this list of conditions and the following disclaimer.
10 * 2. Redistributions in binary form must reproduce the above copyright
11 * notice, this list of conditions and the following disclaimer in the
12 * documentation and/or other materials provided with the distribution.
13 * 3. All advertising materials mentioning features or use of this software
14 * must display the following acknowledgement:
15 * This product includes software developed by Berkeley Software
18 * THIS SOFTWARE IS PROVIDED BY Berkeley Software Design, Inc. ``AS IS'' AND
19 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
20 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
21 * ARE DISCLAIMED. IN NO EVENT SHALL Berkeley Software Design, Inc. BE LIABLE
22 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
23 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
30 * BSDI exe.c,v 2.2 1996/04/08 19:32:34 bostic Exp
34 #include <sys/types.h>
48 static int psp_s[10] = { 0 };
50 static regcontext_t frames[10];
53 make_environment (char *cmdname, char **env)
63 for (i = 0; env[i]; i++) {
64 debug (D_EXEC,"env: %s\n", env[i]);
65 len = strlen (env[i]);
66 if (total + len >= 32 * 1024)
71 total++; /* terminating null */
72 total += 2; /* word count */
73 total += strlen (cmdname) + 1;
74 total += 4; /* some more zeros, just in case */
76 if ((envseg = mem_alloc(total/16 + 1, 1, NULL)) == 0)
77 fatal("out of memory for env\n");
79 env_block = (char *)MAKEPTR(envseg, 0);
80 memset (env_block, 0, total);
84 for (i = 0; env[i]; i++) {
85 len = strlen (env[i]);
86 if (total + len >= 32 * 1024)
93 *(short *)p = strlen(cmdname);
108 load_com(int fd, int start_segment)
113 start_addr = (char *)MAKEPTR(start_segment, 0);
116 i = read (fd, start_addr, 0xff00);
118 debug(D_EXEC, "Read %05x into %04x\n",
123 load_exe(int fd, int start_segment, int reloc_segment, struct exehdr *hdr, int text_size)
127 struct reloc_entry *reloc_tbl, *rp;
131 start_addr = (char *)MAKEPTR(start_segment, 0);
133 lseek (fd, hdr->hdr_size * 16, 0);
134 if (read (fd, start_addr, text_size) != text_size)
135 fatal ("error reading program text\n");
136 debug(D_EXEC, "Read %05x into %04x\n",
137 text_size, start_segment);
140 reloc_size = hdr->nreloc * sizeof (struct reloc_entry);
142 if ((reloc_tbl = (struct reloc_entry *)malloc (reloc_size)) == NULL)
143 fatal ("out of memory for program\n");
145 lseek (fd, hdr->reloc_offset, 0);
146 if (read (fd, reloc_tbl, reloc_size) != reloc_size)
147 fatal ("error reading reloc table\n");
149 for (i = 0, rp = reloc_tbl; i < hdr->nreloc; i++, rp++) {
150 segp = (u_short *)MAKEPTR(start_segment + rp->seg, rp->off);
151 *segp += start_segment;
153 free((char *)reloc_tbl);
158 load_command(regcontext_t *REGS, int run, int fd, char *cmdname,
159 u_short *param, char **argv, char **envs)
162 int min_memory, max_memory;
174 u_short init_cs, init_ip, init_ss, init_sp, init_ds, init_es;
177 envseg = make_environment(cmdname, envs);
179 envseg = env_s[curpsp];
181 /* read exe header */
182 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
183 fatal ("can't read header\n");
185 /* proper header ? */
186 if (hdr.magic == 0x5a4d) {
188 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
190 min_memory = hdr.min_memory + (text_size + 15)/16;
191 max_memory = hdr.max_memory + (text_size + 15)/16;
194 min_memory = 64 * (1024/16);
198 /* alloc mem block */
199 pspseg = mem_alloc(max_memory, 1, &biggest);
201 if (biggest < min_memory ||
202 (pspseg = mem_alloc(biggest, 1, NULL)) == 0)
203 fatal("not enough memory: needed %d have %d\n",
204 min_memory, biggest);
206 max_memory = biggest;
209 mem_change_owner(pspseg, pspseg);
210 mem_change_owner(envseg, pspseg);
214 psp_s[newpsp] = pspseg;
215 env_s[newpsp] = envseg;
217 psp = (char *)MAKEPTR(pspseg, 0);
223 *(u_short *)&psp[2] = pspseg + max_memory;
226 * this is supposed to be a long call to dos ... try to fake it
232 *(u_short *)&psp[0x16] = psp_s[curpsp];
238 memset(psp + 0x1d, 0xff, 15);
240 *(u_short *)&psp[0x2c] = envseg;
242 *(u_short *)&psp[0x32] = 20;
243 *(u_long *)&psp[0x34] = MAKEVEC(pspseg, 0x18);
244 *(u_long *)&psp[0x38] = 0xffffffff;
253 for (i = 0; argv[i]; i++) {
255 if (used + 1 + n > 0x7d)
258 memcpy(p, argv[i], n);
263 psp[0x80] = strlen(psp + 0x81);
264 psp[0x81 + psp[0x80]] = 0x0d;
265 psp[0x82 + psp[0x80]] = 0;
268 parse_filename(0x00, p, psp + 0x5c, &n);
270 parse_filename(0x00, p, psp + 0x6c, &n);
273 fcb = (char *)MAKEPTR(param[4], param[3]);
274 memcpy(psp + 0x5c, fcb, 16);
277 fcb = (char *)MAKEPTR(param[6], param[5]);
278 memcpy(psp + 0x6c, fcb, 16);
283 for (n = 0; n < 16; n++)
284 printf(" %02x", psp[0x5c + n]);
287 for (n = 0; n < 16; n++)
288 printf(" %02x", psp[0x6c + n]);
292 disk_transfer_addr = MAKEVEC(pspseg, 0x80);
294 start_segment = pspseg + 0x10;
297 load_com(fd, start_segment);
306 load_exe(fd, start_segment, start_segment, &hdr, text_size);
308 init_cs = hdr.init_cs + start_segment;
309 init_ip = hdr.init_ip;
310 init_ss = hdr.init_ss + start_segment;
311 init_sp = hdr.init_sp;
316 debug(D_EXEC, "cs:ip = %04x:%04x, ss:sp = %04x:%04x, "
317 "ds = %04x, es = %04x\n",
318 init_cs, init_ip, init_ss, init_sp, init_ds, init_es);
321 frames[newpsp] = *REGS;
332 R_AX = R_BX = R_CX = R_DX = R_SI = R_DI = R_BP = 0;
343 load_overlay(int fd, int start_segment, int reloc_segment)
349 /* read exe header */
350 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
351 fatal ("can't read header\n");
353 /* proper header ? */
354 if (hdr.magic == 0x5a4d) {
356 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
363 load_com(fd, start_segment);
365 load_exe(fd, start_segment, reloc_segment, &hdr, text_size);
371 return(env_s[curpsp]);
375 exec_command(regcontext_t *REGS, int run,
376 int fd, char *cmdname, u_short *param)
383 env = (char *)MAKEPTR(param[0], 0);
384 arg = (char *)MAKEPTR(param[2], param[1]);
395 debug (D_EXEC, "exec_command: cmdname = %s\n"
396 "env = 0x0%x, arg = %04x:%04x(%s)\n",
397 cmdname, param[0], param[2], param[1], arg);
401 for ( i=0; i < 99 && *env; ++i ) {
403 env += strlen(env)+1;
406 load_command(REGS, run, fd, cmdname, param, argv, envs);
408 load_command(REGS, run, fd, cmdname, param, argv, NULL);
412 exec_return(regcontext_t *REGS, int code)
414 debug(D_EXEC, "Returning from exec\n");
415 mem_free_owner(psp_s[curpsp]);
416 *REGS = frames[curpsp--];
418 R_FLAGS &= ~PSL_C; /* It must have worked */