BCPL_GlobVec size fix.
[AROS.git] / arch / m68k-all / dos / bcpl_support.c
bloba0450a841cc94afd7fa9803d56f8045e7ec1c963
1 /*
2 Copyright © 2010, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: BCPL support
6 Lang: english
7 */
8 #define DEBUG 0
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"
20 #include "bcpl.h"
22 /* Externs */
23 extern void BCPL_dummy(void);
24 #define BCPL(id, name) extern void BCPL_##name(void);
25 #include "bcpl.inc"
26 #undef BCPL
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) >> 2] = {
35 #include "bcpl.inc"
37 #undef BCPL
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)
45 ULONG *segment;
46 ULONG *table;
48 if (seg == BNULL) {
49 D(bug("BCPL_InstallSeg: Empty segment\n"));
50 return DOSTRUE;
53 if (seg == (ULONG)-1) {
54 ULONG slots = globvec[0];
55 int i;
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];
65 if (gv == 0)
66 continue;
68 globvec[i] = gv;
71 D(bug("BCPL_InstallSeg: Inserting DOSBase global\n"));
72 globvec[GV_DOSBase >> 2] = (IPTR)OpenLibrary("dos.library",0);
74 return DOSTRUE;
77 if (seg == (ULONG)-2) {
78 return DOSTRUE;
81 segment = BADDR(seg);
82 if ((segment[-1] < segment[1])) {
83 D(bug("BCPL_InstallSeg: segList @%p does not look like BCPL.\n", segment));
84 Alert(AN_BadOverlay);
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]);
97 return DOSTRUE;
101 /* Create the global vector for a process
103 BOOL BCPL_AllocGlobVec(struct Process *me)
105 APTR globvec;
106 int i;
107 ULONG *seglist = BADDR(me->pr_SegList);
109 globvec = AllocMem(sizeof(BCPL_GlobVec), MEMF_ANY | MEMF_CLEAR);
110 if (globvec == NULL)
111 return FALSE;
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 me->pr_GlobVec = globvec;
123 return TRUE;
126 void BCPL_FreeGlobVec(struct Process *me)
128 APTR globvec = me->pr_GlobVec;
129 struct DosLibrary *DOSBase;
131 DOSBase = *(APTR *)(globvec + GV_DOSBase);
132 D(bug("[BCPL_FreeGlobVec] Freed globvec %p\n", globvec));
134 globvec -= BCPL_GlobVec_NegSize;
135 FreeMem(globvec, sizeof(BCPL_GlobVec));
137 me->pr_GlobVec = DOSBase->dl_GV;
140 void BCPL_Fixup(struct Process *me)
142 BPTR *segment = BADDR(me->pr_SegList);
144 if (segment[2] == (BPTR)0x0000abcd) {
145 D(bug("[BCPL_Fixup] Fixing up overlay\n"));
147 /* overlayed executable, fun..
148 * 2 = id
149 * 3 = filehandle (BPTR)
150 * 4 = overlay table (APTR)
151 * 5 = hunk table (BPTR)
152 * 6 = global vector (APTR)
154 segment[6] = (ULONG)me->pr_GlobVec;
158 extern void BCPL_thunk(void);
160 /* Under AOS, BCPL handlers expect the OS to build
161 * their GlobalVector, and to receive a pointer to their
162 * startup packet in D1.
164 * Both filesystem handlers and CLI shells use this routine.
166 * The 'Shell' shell is C based, and does not go here.
168 * This wrapper is here to support that.
170 ULONG BCPL_RunHandler(void)
172 struct DosPacket *dp;
173 struct Process *me = (struct Process *)FindTask(NULL);
174 APTR oldReturnAddr;
175 ULONG ret;
177 WaitPort(&me->pr_MsgPort);
178 dp = (struct DosPacket *)(GetMsg(&me->pr_MsgPort)->mn_Node.ln_Name);
179 D(bug("[RunHandlerBCPL] Startup packet = %p\n", dp));
181 if (!BCPL_AllocGlobVec(me)) {
182 if (dp != NULL)
183 internal_ReplyPkt(dp, &me->pr_MsgPort, DOSFALSE, ERROR_NO_FREE_STORE);
184 return ERROR_NO_FREE_STORE;
187 D(bug("[RunHandlerBCPL] BCPL_ENTRY = %p\n", BCPL_ENTRY(me)));
189 oldReturnAddr = me->pr_ReturnAddr;
190 ret = AROS_UFC8(ULONG, BCPL_thunk,
191 AROS_UFCA(ULONG, MKBADDR(dp), D1),
192 AROS_UFCA(ULONG, 0, D2),
193 AROS_UFCA(ULONG, 0, D3),
194 AROS_UFCA(ULONG, 0, D4),
195 AROS_UFCA(APTR, me->pr_Task.tc_SPLower, A1),
196 AROS_UFCA(APTR, me->pr_GlobVec, A2),
197 AROS_UFCA(APTR, &me->pr_ReturnAddr, A3),
198 AROS_UFCA(LONG_FUNC, BCPL_ENTRY(me), A4));
199 me->pr_ReturnAddr = oldReturnAddr;
201 BCPL_FreeGlobVec(me);
203 return ret;
206 /* Create the necessary process wrappings for a BCPL
207 * segment. Only needed by Workbench's C:Run, C:NewCLI,
208 * C:NewShell, and a few other applications.
210 struct MsgPort *BCPL_CreateProcBCPL(struct DosLibrary *DOSBase, CONST_STRPTR name, BPTR *segarray, ULONG stacksize, LONG pri)
212 struct Process *proc, *me = (struct Process *)FindTask(NULL);
214 D(bug("[BCPL_CreateProcBCPL] Window=%p name=\"%s\", segArray=%p, stacksize=%u, pri=%d\n", me->pr_WindowPtr, name, segarray, stacksize, pri));
216 proc = CreateNewProcTags(
217 NP_Name, name,
218 NP_Entry, BCPL_RunHandler,
219 NP_Input, BNULL,
220 NP_Output, BNULL,
221 NP_Error, BNULL,
222 NP_CloseInput, FALSE,
223 NP_CloseOutput, FALSE,
224 NP_CloseError, FALSE,
225 NP_StackSize, stacksize,
226 NP_WindowPtr, me->pr_WindowPtr,
227 NP_CurrentDir, 0,
228 NP_Cli, TRUE,
229 NP_HomeDir, 0,
230 TAG_END);
232 /* Fix up the segarray before the first packet gets
233 * to it.
235 if (proc) {
236 BPTR *oldsegarray;
238 oldsegarray = BADDR(proc->pr_SegList);
239 if (oldsegarray[0] < segarray[0]) {
240 FreeVec(oldsegarray);
241 oldsegarray = AllocVec(sizeof(BPTR)*(segarray[0]+1), MEMF_PUBLIC | MEMF_CLEAR);
242 oldsegarray[0] = segarray[0];
243 oldsegarray[1] = (BPTR)-1;
244 oldsegarray[2] = (BPTR)-2;
246 CopyMem(&segarray[3], &oldsegarray[3], (oldsegarray[0]-2)*sizeof(BPTR));
250 return proc ? &proc->pr_MsgPort : NULL;
253 void bcpl_command_name(void)
255 struct Process *me = (struct Process *)FindTask(NULL);
256 struct CommandLineInterface *cli = BADDR(me->pr_CLI);
258 if (cli == NULL || cli->cli_Module == BNULL)
259 bug("%s: ", me->pr_Task.tc_Node.ln_Name);
260 else
261 bug("%b: ", cli->cli_CommandName);