2 Copyright © 2010, The AROS Development Team. All rights reserved.
9 #include <aros/debug.h>
10 #include <aros/asmcall.h>
12 #include <dos/dosextens.h>
13 #include <dos/filehandler.h>
14 #include <dos/dostags.h>
16 #include <proto/dos.h>
17 #include <proto/exec.h>
19 #include "dos_intern.h"
23 extern void BCPL_dummy(void);
24 #define BCPL(id, name) extern void BCPL_##name(void);
28 #define BCPL_SlotCount (BCPL_GlobVec_PosSize>>2)
30 /* Default Global Vector */
31 #define BCPL(id, name) \
32 [(BCPL_GlobVec_NegSize + id)>>2] = (ULONG)BCPL_##name,
34 const ULONG BCPL_GlobVec
[BCPL_GlobVec_NegSize
+ BCPL_GlobVec_PosSize
] = {
39 #define BCPL_ENTRY(proc) (((APTR *)(proc)->pr_GlobVec)[1])
41 * Set up the process's initial global vector
43 ULONG
BCPL_InstallSeg(BPTR seg
, ULONG
*globvec
)
49 D(bug("BCPL_InstallSeg: Empty segment\n"));
53 if (seg
== (ULONG
)-1) {
54 ULONG slots
= globvec
[0];
56 if (slots
> (BCPL_GlobVec_PosSize
>>2))
57 slots
= (BCPL_GlobVec_PosSize
>>2);
58 D(bug("BCPL_InstallSeg: Inserting %d Faux system entries.\n", slots
));
60 /* Copy over the negative entries from the default global vector */
61 CopyMem(&BCPL_GlobVec
[0], &globvec
[-(BCPL_GlobVec_NegSize
>>2)], BCPL_GlobVec_NegSize
);
63 for (i
= 2; i
< slots
; i
++) {
64 ULONG gv
= BCPL_GlobVec
[(BCPL_GlobVec_NegSize
>>2) + i
];
71 D(bug("BCPL_InstallSeg: Inserting DOSBase global\n"));
72 globvec
[GV_DOSBase
>> 2] = (IPTR
)OpenLibrary("dos.library",0);
77 if (seg
== (ULONG
)-2) {
82 if ((segment
[-1] < segment
[1])) {
83 D(bug("BCPL_InstallSeg: segList @%p does not look like BCPL.\n", segment
));
87 D(bug("BCPL_InstallSeg: SegList @%p\n", segment
));
88 table
= &segment
[segment
[1]];
90 D(bug("\tFill in for %p:\n", segment
));
92 for (; table
[-1] != 0; table
= &table
[-2]) {
93 D(bug("\t globvec[%d] = %p\n", table
[-2], (APTR
)&segment
[1] + table
[-1]));
94 globvec
[table
[-2]] = (ULONG
)((APTR
)&segment
[1] + table
[-1]);
101 /* Create the global vector for a process
103 BOOL
BCPL_AllocGlobVec(struct Process
*me
)
107 ULONG
*seglist
= BADDR(me
->pr_SegList
);
109 globvec
= AllocMem(sizeof(BCPL_GlobVec
), MEMF_ANY
| MEMF_CLEAR
);
113 globvec
+= BCPL_GlobVec_NegSize
;
114 ((ULONG
*)globvec
)[0] = BCPL_GlobVec_PosSize
>> 2;
116 /* Install the segments into the Global Vector */
117 for (i
= 0; i
< seglist
[0]; i
++) {
118 BCPL_InstallSeg(seglist
[i
+1], globvec
);
121 entry
= ((APTR
*)globvec
)[1];
123 me
->pr_GlobVec
= globvec
;
128 void BCPL_FreeGlobVec(struct Process
*me
)
130 APTR globvec
= me
->pr_GlobVec
;
131 struct DosLibrary
*DOSBase
;
133 DOSBase
= *(APTR
*)(globvec
+ GV_DOSBase
);
134 D(bug("[BCPL_FreeGlobVec] Freed globvec %p\n", globvec
));
136 globvec
-= BCPL_GlobVec_NegSize
;
137 FreeMem(globvec
, sizeof(BCPL_GlobVec
));
139 me
->pr_GlobVec
= DOSBase
->dl_GV
;
142 void BCPL_Fixup(struct Process
*me
)
144 BPTR
*segment
= BADDR(me
->pr_SegList
);
146 if (segment
[2] == (BPTR
)0x0000abcd) {
147 D(bug("[BCPL_Fixup] Fixing up overlay\n"));
149 /* overlayed executable, fun..
151 * 3 = filehandle (BPTR)
152 * 4 = overlay table (APTR)
153 * 5 = hunk table (BPTR)
154 * 6 = global vector (APTR)
156 segment
[6] = (ULONG
)me
->pr_GlobVec
;
160 extern void BCPL_thunk(void);
162 /* Under AOS, BCPL handlers expect the OS to build
163 * their GlobalVector, and to receive a pointer to their
164 * startup packet in D1.
166 * Both filesystem handlers and CLI shells use this routine.
168 * The 'Shell' shell is C based, and does not go here.
170 * This wrapper is here to support that.
172 ULONG
BCPL_RunHandler(void)
174 struct DosPacket
*dp
;
175 struct Process
*me
= (struct Process
*)FindTask(NULL
);
180 WaitPort(&me
->pr_MsgPort
);
181 dp
= (struct DosPacket
*)(GetMsg(&me
->pr_MsgPort
)->mn_Node
.ln_Name
);
182 D(bug("[RunHandlerBCPL] Startup packet = %p\n", dp
));
184 if (!BCPL_AllocGlobVec(me
)) {
186 internal_ReplyPkt(dp
, &me
->pr_MsgPort
, DOSFALSE
, ERROR_NO_FREE_STORE
);
187 return ERROR_NO_FREE_STORE
;
190 D(bug("[RunHandlerBCPL] BCPL_ENTRY = %p\n", BCPL_ENTRY(me
)));
192 oldReturnAddr
= me
->pr_ReturnAddr
;
193 ret
= AROS_UFC8(ULONG
, BCPL_thunk
,
194 AROS_UFCA(ULONG
, MKBADDR(dp
), D1
),
195 AROS_UFCA(ULONG
, 0, D2
),
196 AROS_UFCA(ULONG
, 0, D3
),
197 AROS_UFCA(ULONG
, 0, D4
),
198 AROS_UFCA(APTR
, me
->pr_Task
.tc_SPLower
, A1
),
199 AROS_UFCA(APTR
, me
->pr_GlobVec
, A2
),
200 AROS_UFCA(APTR
, &me
->pr_ReturnAddr
, A3
),
201 AROS_UFCA(LONG_FUNC
, BCPL_ENTRY(me
), A4
));
202 me
->pr_ReturnAddr
= oldReturnAddr
;
204 BCPL_FreeGlobVec(me
);
205 oldGlobVec
= me
->pr_GlobVec
;
210 /* Create the necessary process wrappings for a BCPL
211 * segment. Only needed by Workbench's C:Run, C:NewCLI,
212 * C:NewShell, and a few other applications.
214 struct MsgPort
*BCPL_CreateProcBCPL(struct DosLibrary
*DOSBase
, CONST_STRPTR name
, BPTR
*segarray
, ULONG stacksize
, LONG pri
)
216 struct Process
*proc
, *me
= (struct Process
*)FindTask(NULL
);
218 D(bug("[BCPL_CreateProcBCPL] Window=%p name=\"%s\", segArray=%p, stacksize=%u, pri=%d\n", me
->pr_WindowPtr
, name
, segarray
, stacksize
, pri
));
220 proc
= CreateNewProcTags(
222 NP_Entry
, BCPL_RunHandler
,
226 NP_CloseInput
, FALSE
,
227 NP_CloseOutput
, FALSE
,
228 NP_CloseError
, FALSE
,
229 NP_StackSize
, stacksize
,
230 NP_WindowPtr
, me
->pr_WindowPtr
,
236 /* Fix up the segarray before the first packet gets
242 oldsegarray
= BADDR(proc
->pr_SegList
);
243 if (oldsegarray
[0] < segarray
[0]) {
244 FreeVec(oldsegarray
);
245 oldsegarray
= AllocVec(sizeof(BPTR
)*(segarray
[0]+1), MEMF_PUBLIC
| MEMF_CLEAR
);
246 oldsegarray
[0] = segarray
[0];
247 oldsegarray
[1] = (BPTR
)-1;
248 oldsegarray
[2] = (BPTR
)-2;
250 CopyMem(&segarray
[3], &oldsegarray
[3], (oldsegarray
[0]-2)*sizeof(BPTR
));
254 return proc
? &proc
->pr_MsgPort
: NULL
;
257 void bcpl_command_name(void)
259 struct Process
*me
= (struct Process
*)FindTask(NULL
);
260 struct CommandLineInterface
*cli
= BADDR(me
->pr_CLI
);
262 if (cli
== NULL
|| cli
->cli_Module
== BNULL
)
263 bug("%s: ", me
->pr_Task
.tc_Node
.ln_Name
);
265 bug("%b: ", cli
->cli_CommandName
);