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
35 #include <sys/types.h>
45 static int psp_s[10] = { 0 };
47 static regcontext_t frames[10];
48 static char *env_block;
51 make_environment (char *cmdname, char **env)
61 for (i = 0; env[i]; i++) {
62 debug (D_EXEC,"env: %s\n", env[i]);
63 len = strlen (env[i]);
64 if (total + len >= 32 * 1024)
69 total++; /* terminating null */
70 total += 2; /* word count */
71 total += strlen (cmdname) + 1;
72 total += 4; /* some more zeros, just in case */
74 if ((envseg = mem_alloc(total/16 + 1, 1, NULL)) == 0)
75 fatal("out of memory for env\n");
77 env_block = (char *)MAKEPTR(envseg, 0);
78 memset (env_block, 0, total);
82 for (i = 0; env[i]; i++) {
83 len = strlen (env[i]);
84 if (total + len >= 32 * 1024)
91 *(short *)p = strlen(cmdname);
106 load_com(int fd, int start_segment)
111 start_addr = (char *)MAKEPTR(start_segment, 0);
114 i = read (fd, start_addr, 0xff00);
116 debug(D_EXEC, "Read %05x into %04x\n",
121 load_exe(int fd, int start_segment, int reloc_segment, struct exehdr *hdr, int text_size)
125 struct reloc_entry *reloc_tbl, *rp;
129 start_addr = (char *)MAKEPTR(start_segment, 0);
131 lseek (fd, hdr->hdr_size * 16, 0);
132 if (read (fd, start_addr, text_size) != text_size)
133 fatal ("error reading program text\n");
134 debug(D_EXEC, "Read %05x into %04x\n",
135 text_size, start_segment);
138 reloc_size = hdr->nreloc * sizeof (struct reloc_entry);
140 if ((reloc_tbl = (struct reloc_entry *)malloc (reloc_size)) == NULL)
141 fatal ("out of memory for program\n");
143 lseek (fd, hdr->reloc_offset, 0);
144 if (read (fd, reloc_tbl, reloc_size) != reloc_size)
145 fatal ("error reading reloc table\n");
147 for (i = 0, rp = reloc_tbl; i < hdr->nreloc; i++, rp++) {
148 segp = (u_short *)MAKEPTR(start_segment + rp->seg, rp->off);
149 *segp += start_segment;
151 free((char *)reloc_tbl);
156 load_command(regcontext_t *REGS, int run, int fd, char *cmdname,
157 u_short *param, char **argv, char **envs)
160 int min_memory, max_memory;
172 u_short init_cs, init_ip, init_ss, init_sp, init_ds, init_es;
175 envseg = make_environment(cmdname, envs);
177 envseg = env_s[curpsp];
179 /* read exe header */
180 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
181 fatal ("can't read header\n");
183 /* proper header ? */
184 if (hdr.magic == 0x5a4d) {
186 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
188 min_memory = hdr.min_memory + (text_size + 15)/16;
189 max_memory = hdr.max_memory + (text_size + 15)/16;
192 min_memory = 64 * (1024/16);
196 /* alloc mem block */
197 pspseg = mem_alloc(max_memory, 1, &biggest);
199 if (biggest < min_memory ||
200 (pspseg = mem_alloc(biggest, 1, NULL)) == 0)
201 fatal("not enough memory: needed %d have %d\n",
202 min_memory, biggest);
204 max_memory = biggest;
207 mem_change_owner(pspseg, pspseg);
208 mem_change_owner(envseg, pspseg);
212 psp_s[newpsp] = pspseg;
213 env_s[newpsp] = envseg;
215 psp = (char *)MAKEPTR(pspseg, 0);
221 *(u_short *)&psp[2] = pspseg + max_memory;
224 * this is supposed to be a long call to dos ... try to fake it
230 *(u_short *)&psp[0x16] = psp_s[curpsp];
236 memset(psp + 0x1d, 0xff, 15);
238 *(u_short *)&psp[0x2c] = envseg;
240 *(u_short *)&psp[0x32] = 20;
241 *(u_long *)&psp[0x34] = MAKEVEC(pspseg, 0x18);
242 *(u_long *)&psp[0x38] = 0xffffffff;
251 for (i = 0; argv[i]; i++) {
253 if (used + 1 + n > 0x7d)
256 memcpy(p, argv[i], n);
261 psp[0x80] = strlen(psp + 0x81);
262 psp[0x81 + psp[0x80]] = 0x0d;
263 psp[0x82 + psp[0x80]] = 0;
266 parse_filename(0x00, p, psp + 0x5c, &n);
268 parse_filename(0x00, p, psp + 0x6c, &n);
271 fcb = (char *)MAKEPTR(param[4], param[3]);
272 memcpy(psp + 0x5c, fcb, 16);
275 fcb = (char *)MAKEPTR(param[6], param[5]);
276 memcpy(psp + 0x6c, fcb, 16);
281 for (n = 0; n < 16; n++)
282 printf(" %02x", psp[0x5c + n]);
285 for (n = 0; n < 16; n++)
286 printf(" %02x", psp[0x6c + n]);
290 disk_transfer_addr = MAKEVEC(pspseg, 0x80);
292 start_segment = pspseg + 0x10;
295 load_com(fd, start_segment);
304 load_exe(fd, start_segment, start_segment, &hdr, text_size);
306 init_cs = hdr.init_cs + start_segment;
307 init_ip = hdr.init_ip;
308 init_ss = hdr.init_ss + start_segment;
309 init_sp = hdr.init_sp;
314 debug(D_EXEC, "cs:ip = %04x:%04x, ss:sp = %04x:%04x, "
315 "ds = %04x, es = %04x\n",
316 init_cs, init_ip, init_ss, init_sp, init_ds, init_es);
319 frames[newpsp] = *REGS;
330 R_AX = R_BX = R_CX = R_DX = R_SI = R_DI = R_BP = 0;
341 load_overlay(int fd, int start_segment, int reloc_segment)
347 /* read exe header */
348 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
349 fatal ("can't read header\n");
351 /* proper header ? */
352 if (hdr.magic == 0x5a4d) {
354 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
361 load_com(fd, start_segment);
363 load_exe(fd, start_segment, reloc_segment, &hdr, text_size);
369 return(psp_s[curpsp]);
375 return(env_s[curpsp]);
379 exec_command(regcontext_t *REGS, int run,
380 int fd, char *cmdname, u_short *param)
387 env = (char *)MAKEPTR(param[0], 0);
388 arg = (char *)MAKEPTR(param[2], param[1]);
399 debug (D_EXEC, "exec_command: cmdname = %s\n"
400 "env = 0x0%x, arg = %04x:%04x(%s)\n",
401 cmdname, param[0], param[2], param[1], arg);
405 for ( i=0; i < 99 && *env; ++i ) {
407 env += strlen(env)+1;
410 load_command(REGS, run, fd, cmdname, param, argv, envs);
412 load_command(REGS, run, fd, cmdname, param, argv, NULL);
416 exec_return(regcontext_t *REGS, int code)
418 debug(D_EXEC, "Returning from exec\n");
419 mem_free_owner(psp_s[curpsp]);
420 *REGS = frames[curpsp--];
422 R_FLAGS &= ~PSL_C; /* It must have worked */