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
32 * $FreeBSD: src/usr.bin/doscmd/exe.c,v 1.2.2.1 2002/04/25 11:04:51 tg Exp $
33 * $DragonFly: src/usr.bin/doscmd/exe.c,v 1.2 2003/06/17 04:29:26 dillon Exp $
36 #include <sys/types.h>
50 static int psp_s[10] = { 0 };
52 static regcontext_t frames[10];
55 make_environment(char *cmd_name, char **env)
65 for (i = 0; env[i]; i++) {
66 debug (D_EXEC,"env: %s\n", env[i]);
68 if (total + len >= 32 * 1024)
73 total++; /* terminating null */
74 total += 2; /* word count */
75 total += strlen(cmd_name) + 1;
76 total += 4; /* some more zeros, just in case */
78 if ((envseg = mem_alloc(total/16 + 1, 1, NULL)) == 0)
79 fatal("out of memory for env\n");
81 env_block = (char *)MAKEPTR(envseg, 0);
82 memset (env_block, 0, total);
86 for (i = 0; env[i]; i++) {
88 if (total + len >= 32 * 1024)
95 *(short *)p = strlen(cmd_name);
101 else if (islower(*p))
110 load_com(int fd, int start_segment)
115 start_addr = (char *)MAKEPTR(start_segment, 0);
118 i = read (fd, start_addr, 0xff00);
120 debug(D_EXEC, "Read %05x into %04x\n",
125 load_exe(int fd, int start_segment, int reloc_segment __unused, struct exehdr *hdr, int text_size)
129 struct reloc_entry *reloc_tbl, *rp;
133 start_addr = (char *)MAKEPTR(start_segment, 0);
135 lseek (fd, hdr->hdr_size * 16, 0);
136 if (read (fd, start_addr, text_size) != text_size)
137 fatal ("error reading program text\n");
138 debug(D_EXEC, "Read %05x into %04x\n",
139 text_size, start_segment);
142 reloc_size = hdr->nreloc * sizeof (struct reloc_entry);
144 if ((reloc_tbl = (struct reloc_entry *)malloc (reloc_size)) == NULL)
145 fatal ("out of memory for program\n");
147 lseek (fd, hdr->reloc_offset, 0);
148 if (read (fd, reloc_tbl, reloc_size) != reloc_size)
149 fatal ("error reading reloc table\n");
151 for (i = 0, rp = reloc_tbl; i < hdr->nreloc; i++, rp++) {
152 segp = (u_short *)MAKEPTR(start_segment + rp->seg, rp->off);
153 *segp += start_segment;
155 free((char *)reloc_tbl);
160 load_command(regcontext_t *REGS, int run, int fd, char *cmd_name,
161 u_short *param, char **argv, char **envs)
164 int min_memory, max_memory;
176 u_short init_cs, init_ip, init_ss, init_sp, init_ds, init_es;
179 envseg = make_environment(cmd_name, envs);
181 envseg = env_s[curpsp];
183 /* read exe header */
184 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
185 fatal ("can't read header\n");
187 /* proper header ? */
188 if (hdr.magic == 0x5a4d) {
190 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
192 min_memory = hdr.min_memory + (text_size + 15)/16;
193 max_memory = hdr.max_memory + (text_size + 15)/16;
196 min_memory = 64 * (1024/16);
200 /* alloc mem block */
201 pspseg = mem_alloc(max_memory, 1, &biggest);
203 if (biggest < min_memory ||
204 (pspseg = mem_alloc(biggest, 1, NULL)) == 0)
205 fatal("not enough memory: needed %d have %d\n",
206 min_memory, biggest);
208 max_memory = biggest;
211 mem_change_owner(pspseg, pspseg);
212 mem_change_owner(envseg, pspseg);
216 psp_s[newpsp] = pspseg;
217 env_s[newpsp] = envseg;
219 psp = (char *)MAKEPTR(pspseg, 0);
225 *(u_short *)&psp[2] = pspseg + max_memory;
228 * this is supposed to be a long call to dos ... try to fake it
234 *(u_short *)&psp[0x16] = psp_s[curpsp];
240 memset(psp + 0x1d, 0xff, 15);
242 *(u_short *)&psp[0x2c] = envseg;
244 *(u_short *)&psp[0x32] = 20;
245 *(u_long *)&psp[0x34] = MAKEVEC(pspseg, 0x18);
246 *(u_long *)&psp[0x38] = 0xffffffff;
255 for (i = 0; argv[i]; i++) {
257 if (used + 1 + n > 0x7d)
260 memcpy(p, argv[i], n);
265 psp[0x80] = strlen(psp + 0x81);
266 psp[0x81 + psp[0x80]] = 0x0d;
267 psp[0x82 + psp[0x80]] = 0;
270 parse_filename(0x00, p, psp + 0x5c, &n);
272 parse_filename(0x00, p, psp + 0x6c, &n);
275 fcb = (char *)MAKEPTR(param[4], param[3]);
276 memcpy(psp + 0x5c, fcb, 16);
279 fcb = (char *)MAKEPTR(param[6], param[5]);
280 memcpy(psp + 0x6c, fcb, 16);
285 for (n = 0; n < 16; n++)
286 printf(" %02x", psp[0x5c + n]);
289 for (n = 0; n < 16; n++)
290 printf(" %02x", psp[0x6c + n]);
294 disk_transfer_addr = MAKEVEC(pspseg, 0x80);
296 start_segment = pspseg + 0x10;
299 load_com(fd, start_segment);
308 load_exe(fd, start_segment, start_segment, &hdr, text_size);
310 init_cs = hdr.init_cs + start_segment;
311 init_ip = hdr.init_ip;
312 init_ss = hdr.init_ss + start_segment;
313 init_sp = hdr.init_sp;
318 debug(D_EXEC, "cs:ip = %04x:%04x, ss:sp = %04x:%04x, "
319 "ds = %04x, es = %04x\n",
320 init_cs, init_ip, init_ss, init_sp, init_ds, init_es);
323 frames[newpsp] = *REGS;
334 R_AX = R_BX = R_CX = R_DX = R_SI = R_DI = R_BP = 0;
345 load_overlay(int fd, int start_segment, int reloc_segment)
351 /* read exe header */
352 if (read (fd, &hdr, sizeof hdr) != sizeof hdr)
353 fatal ("can't read header\n");
355 /* proper header ? */
356 if (hdr.magic == 0x5a4d) {
358 text_size = (hdr.size - 1) * 512 + hdr.bytes_on_last_page
365 load_com(fd, start_segment);
367 load_exe(fd, start_segment, reloc_segment, &hdr, text_size);
373 return(env_s[curpsp]);
377 exec_command(regcontext_t *REGS, int run,
378 int fd, char *cmd_name, u_short *param)
385 env = (char *)MAKEPTR(param[0], 0);
386 arg = (char *)MAKEPTR(param[2], param[1]);
397 debug (D_EXEC, "exec_command: cmd_name = %s\n"
398 "env = 0x0%x, arg = %04x:%04x(%s)\n",
399 cmd_name, param[0], param[2], param[1], arg);
403 for ( i=0; i < 99 && *env; ++i ) {
405 env += strlen(env)+1;
408 load_command(REGS, run, fd, cmd_name, param, argv, envs);
410 load_command(REGS, run, fd, cmd_name, param, argv, NULL);
414 exec_return(regcontext_t *REGS, int code)
416 debug(D_EXEC, "Returning from exec\n");
417 mem_free_owner(psp_s[curpsp]);
418 *REGS = frames[curpsp--];
420 R_FLAGS &= ~PSL_C; /* It must have worked */