Minor fixes to comments.
[AROS.git] / rom / exec / prepareexecbase.c
blob6cfce649133b7ca98f50c02cccd5a6479ea431b0
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: Sets up the ExecBase a bit. (Mostly clearing).
6 Lang:
7 */
9 #include <aros/asmcall.h>
10 #include <aros/debug.h>
11 #include <aros/kernel.h>
12 #include <clib/macros.h>
13 #include <exec/types.h>
14 #include <exec/lists.h>
15 #include <exec/memory.h>
16 #include <exec/memheaderext.h>
17 #include <exec/resident.h>
18 #include <exec/execbase.h>
19 #include <exec/libraries.h>
20 #include <aros/arossupportbase.h>
22 #include <string.h>
24 #include <proto/alib.h>
25 #include <proto/exec.h>
26 #include <proto/kernel.h>
28 #include LC_LIBDEFS_FILE
29 #include "etask.h"
30 #include "memory.h"
31 #include "exec_util.h"
32 #include "exec_debug.h"
33 #include "exec_intern.h"
35 #undef kprintf /* This can't be used in the code here */
37 extern void *LIBFUNCTABLE[];
39 extern struct Resident Exec_resident; /* Need this for lib_IdString */
41 extern void Exec_TrapHandler(ULONG trapNum);
42 AROS_LD3(ULONG, MakeFunctions,
43 AROS_LDA(APTR, target, A0),
44 AROS_LDA(CONST_APTR, functionArray, A1),
45 AROS_LDA(CONST_APTR, funcDispBase, A2),
46 struct ExecBase *, SysBase, 15, Exec);
48 /* Default finaliser. */
49 static void Exec_TaskFinaliser(void)
51 /* Get rid of current task. */
52 RemTask(SysBase->ThisTask);
55 #undef kprintf
56 #undef rkprintf
57 #undef vkprintf
59 void _aros_not_implemented(char *X)
61 kprintf("Unsupported function at offset -0x%h in %s\n",
62 ABS(*(WORD *)((&X)[-1]-2)),
63 ((struct Library *)(&X)[-2])->lib_Node.ln_Name);
66 struct Library *PrepareAROSSupportBase (struct MemHeader *mh)
68 struct AROSSupportBase *AROSSupportBase;
70 AROSSupportBase = Allocate(mh, sizeof(struct AROSSupportBase));
72 AROSSupportBase->kprintf = (void *)kprintf;
73 AROSSupportBase->rkprintf = (void *)rkprintf;
74 AROSSupportBase->vkprintf = (void *)vkprintf;
76 AROSSupportBase->StdOut = NULL;
77 AROSSupportBase->DebugConfig = NULL;
79 return (struct Library *)AROSSupportBase;
82 BOOL IsSysBaseValid(struct ExecBase *sysbase)
84 if (sysbase == NULL)
85 return FALSE;
86 #ifdef __mc68000
87 if (((IPTR)sysbase) & 0x80000001)
88 return FALSE;
89 #endif
90 if (sysbase->ChkBase != ~(IPTR)sysbase)
91 return FALSE;
92 if (sysbase->SoftVer != VERSION_NUMBER)
93 return FALSE;
94 /* more tests? */
95 return GetSysBaseChkSum(sysbase) == 0xffff;
98 UWORD GetSysBaseChkSum(struct ExecBase *sysbase)
100 UWORD sum = 0;
101 UWORD *p = (UWORD*)&sysbase->SoftVer;
102 while (p <= &sysbase->ChkSum)
103 sum += *p++;
104 return sum;
107 void SetSysBaseChkSum(void)
109 SysBase->ChkBase=~(IPTR)SysBase;
110 SysBase->ChkSum = 0;
111 SysBase->ChkSum = GetSysBaseChkSum(SysBase) ^ 0xffff;
115 * PrepareExecBase() will initialize the ExecBase to default values.
116 * MemHeader and ExecBase itself will already be added to appropriate
117 * lists. You don't need to do this yourself.
119 * WARNING: this routine intentionally sets up global SysBase.
120 * This is done because:
121 * 1. PrepareAROSSupportBase() calls Allocate() which relies on functional SysBase
122 * 2. After PrepareAROSSupportBase() it is possible to call debug output functions
123 * (kprintf() etc). Yes, KernelBase is not set up yet, but remember that kernel.resource
124 * may have patched functions in AROSSupportBase so that KernelBase is not needed there.
125 * 3. Existing ports (at least UNIX-hosted and Windows-hosted) rely on the fact that SysBase is
126 * set up here.
128 * Resume: please be extremely careful, study existing code, and think five times if you decide to
129 * change this. You WILL break existing ports if you do not modify their code accordingly. There's
130 * nothing really bad in the fact that global SysBase is touched here and changing this does not
131 * really win something.
132 * Pavel Fedin <pavel_fedin@mail.ru>
134 struct ExecBase *PrepareExecBase(struct MemHeader *mh, struct TagItem *msg)
136 ULONG negsize = 0;
137 VOID **fp = LIBFUNCTABLE;
138 APTR ColdCapture = NULL, CoolCapture = NULL, WarmCapture = NULL;
139 APTR KickMemPtr = NULL, KickTagPtr = NULL, KickCheckSum = NULL;
140 APTR mem;
141 ULONG i;
142 char *args;
145 * Copy reset proof pointers if old SysBase is valid.
146 * Additional platform-specific code is needed in order to test
147 * address validity. This routine should zero out SysBase if it is invalid.
149 if (IsSysBaseValid(SysBase))
151 ColdCapture = SysBase->ColdCapture;
152 CoolCapture = SysBase->CoolCapture;
153 WarmCapture = SysBase->WarmCapture;
154 KickMemPtr = SysBase->KickMemPtr;
155 KickTagPtr = SysBase->KickTagPtr;
156 KickCheckSum = SysBase->KickCheckSum;
159 /* Calculate the size of the vector table */
160 while (*fp++ != (VOID *) -1) negsize += LIB_VECTSIZE;
162 /* Align library base */
163 negsize = AROS_ALIGN(negsize);
165 /* Allocate memory for library base */
166 mem = stdAlloc(mh, negsize + sizeof(struct IntExecBase), MEMF_CLEAR, NULL, NULL);
167 if (!mem)
168 return NULL;
170 SysBase = mem + negsize;
172 #ifdef HAVE_PREPAREPLATFORM
173 /* Setup platform-specific data */
174 if (!Exec_PreparePlatform(&PD(SysBase), msg))
175 return NULL;
176 #endif
178 /* Setup function vectors */
179 AROS_CALL3(ULONG, AROS_SLIB_ENTRY(MakeFunctions, Exec, 15),
180 AROS_UFCA(APTR, SysBase, A0),
181 AROS_UFCA(CONST_APTR, LIBFUNCTABLE, A1),
182 AROS_UFCA(CONST_APTR, NULL, A2),
183 struct ExecBase *, SysBase);
185 /* Set default values */
186 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
187 SysBase->LibNode.lib_Node.ln_Pri = -100;
188 SysBase->LibNode.lib_Node.ln_Name = (char *)Exec_resident.rt_Name;
189 SysBase->LibNode.lib_IdString = (char *)Exec_resident.rt_IdString;
190 SysBase->LibNode.lib_Version = VERSION_NUMBER;
191 SysBase->LibNode.lib_Revision = REVISION_NUMBER;
192 SysBase->LibNode.lib_OpenCnt = 1;
193 SysBase->LibNode.lib_NegSize = negsize;
194 SysBase->LibNode.lib_PosSize = sizeof(struct IntExecBase);
195 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
197 NEWLIST(&SysBase->MemList);
198 SysBase->MemList.lh_Type = NT_MEMORY;
200 NEWLIST(&SysBase->ResourceList);
201 SysBase->ResourceList.lh_Type = NT_RESOURCE;
203 NEWLIST(&SysBase->DeviceList);
204 SysBase->DeviceList.lh_Type = NT_DEVICE;
206 NEWLIST(&SysBase->IntrList);
207 SysBase->IntrList.lh_Type = NT_INTERRUPT;
209 NEWLIST(&SysBase->LibList);
210 SysBase->LibList.lh_Type = NT_LIBRARY;
212 /* Add exec.library to system library list */
213 ADDHEAD(&SysBase->LibList, &SysBase->LibNode.lib_Node);
215 NEWLIST(&SysBase->PortList);
216 SysBase->PortList.lh_Type = NT_MSGPORT;
218 NEWLIST(&SysBase->TaskReady);
219 SysBase->TaskReady.lh_Type = NT_TASK;
221 NEWLIST(&SysBase->TaskWait);
222 SysBase->TaskWait.lh_Type = NT_TASK;
224 NEWLIST(&SysBase->SemaphoreList);
225 SysBase->TaskWait.lh_Type = NT_SEMAPHORE;
227 NEWLIST(&SysBase->ex_MemHandlers);
229 for (i = 0; i < 5; i++)
231 NEWLIST(&SysBase->SoftInts[i].sh_List);
232 SysBase->SoftInts[i].sh_List.lh_Type = NT_INTERRUPT;
235 NEWLIST(&PrivExecBase(SysBase)->ResetHandlers);
236 NEWLIST(&PrivExecBase(SysBase)->AllocMemList);
238 InitSemaphore(&PrivExecBase(SysBase)->MemListSem);
239 InitSemaphore(&PrivExecBase(SysBase)->LowMemSem);
241 SysBase->SoftVer = VERSION_NUMBER;
242 SysBase->Quantum = 4;
243 SysBase->TaskTrapCode = Exec_TrapHandler;
244 SysBase->TaskExceptCode = NULL;
245 SysBase->TaskExitCode = Exec_TaskFinaliser;
246 SysBase->TaskSigAlloc = 0xFFFF;
247 SysBase->TaskTrapAlloc = 0;
249 /* Parse some arguments from command line */
250 args = (char *)LibGetTagData(KRN_CmdLine, 0, msg);
251 if (args)
253 char *opts;
256 * Enable mungwall before the first AllocMem().
257 * Yes, we have actually already called stdAlloc() once
258 * in order to allocate memory for SysBase itself, however
259 * this is not a real problem because it is never going
260 * to be freed.
262 * We store mungwall setting in private flags because it must not be
263 * switched at runtime (or hard crash will happen).
265 opts = strcasestr(args, "mungwall");
266 if (opts)
267 PrivExecBase(SysBase)->IntFlags = EXECF_MungWall;
269 opts = strcasestr(args, "stacksnoop");
270 if (opts)
271 PrivExecBase(SysBase)->IntFlags = EXECF_StackSnoop;
274 * Parse system runtime debug flags.
275 * These are public. In future they will be editable by prefs program.
276 * However in order to be able to turn them on during early startup,
277 * we apply them also here.
279 opts = strcasestr(args, "sysdebug=");
280 if (opts)
281 SysBase->ex_DebugFlags = ParseFlags(&opts[9], ExecFlagNames);
284 NEWLIST(&PrivExecBase(SysBase)->TaskStorageSlots);
286 SetSysBaseChkSum();
288 /* Add our initial MemHeader */
289 ADDHEAD(&SysBase->MemList, &mh->mh_Node);
291 /* Bring back saved values (or NULLs) */
292 SysBase->ColdCapture = ColdCapture;
293 SysBase->CoolCapture = CoolCapture;
294 SysBase->WarmCapture = WarmCapture;
295 SysBase->KickMemPtr = KickMemPtr;
296 SysBase->KickTagPtr = KickTagPtr;
297 SysBase->KickCheckSum = KickCheckSum;
299 SysBase->DebugAROSBase = PrepareAROSSupportBase(mh);
301 return SysBase;