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 */