Indentation fix, cleanup.
[AROS.git] / rom / exec / prepareexecbase.c
blob9af1d5b9c2340b98f966215f3b6a120a7c7b1d38
1 /*
2 Copyright © 1995-2015, 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(GET_THIS_TASK);
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;
114 static APTR allocmem(struct MemHeader *mh, ULONG size, ULONG attributes)
116 APTR ret;
118 if (IsManagedMem(mh))
120 struct MemHeaderExt *mhe = (struct MemHeaderExt *)mh;
122 if (mhe->mhe_Alloc)
123 ret = mhe->mhe_Alloc(mhe, size, &attributes);
124 else
125 ret = 0;
127 else
129 ret = stdAlloc(mh, NULL, size, attributes, NULL, NULL);
132 return ret;
136 * PrepareExecBase() will initialize the ExecBase to default values.
137 * MemHeader and ExecBase itself will already be added to appropriate
138 * lists. You don't need to do this yourself.
140 * WARNING: this routine intentionally sets up global SysBase.
141 * This is done because:
142 * 1. PrepareAROSSupportBase() calls Allocate() which relies on functional SysBase
143 * 2. After PrepareAROSSupportBase() it is possible to call debug output functions
144 * (kprintf() etc). Yes, KernelBase is not set up yet, but remember that kernel.resource
145 * may have patched functions in AROSSupportBase so that KernelBase is not needed there.
146 * 3. Existing ports (at least UNIX-hosted and Windows-hosted) rely on the fact that SysBase is
147 * set up here.
149 * Resume: please be extremely careful, study existing code, and think five times if you decide to
150 * change this. You WILL break existing ports if you do not modify their code accordingly. There's
151 * nothing really bad in the fact that global SysBase is touched here and changing this does not
152 * really win something.
153 * Pavel Fedin <pavel_fedin@mail.ru>
155 struct ExecBase *PrepareExecBase(struct MemHeader *mh, struct TagItem *msg)
157 ULONG negsize = 0;
158 VOID **fp = LIBFUNCTABLE;
159 APTR ColdCapture = NULL, CoolCapture = NULL, WarmCapture = NULL;
160 APTR KickMemPtr = NULL, KickTagPtr = NULL, KickCheckSum = NULL;
161 APTR mem;
162 ULONG i;
163 char *args;
166 * Copy reset proof pointers if old SysBase is valid.
167 * Additional platform-specific code is needed in order to test
168 * address validity. This routine should zero out SysBase if it is invalid.
170 if (IsSysBaseValid(SysBase))
172 ColdCapture = SysBase->ColdCapture;
173 CoolCapture = SysBase->CoolCapture;
174 WarmCapture = SysBase->WarmCapture;
175 KickMemPtr = SysBase->KickMemPtr;
176 KickTagPtr = SysBase->KickTagPtr;
177 KickCheckSum = SysBase->KickCheckSum;
180 /* Calculate the size of the vector table */
181 while (*fp++ != (VOID *) -1) negsize += LIB_VECTSIZE;
183 /* Align library base */
184 negsize = AROS_ALIGN(negsize);
186 /* Allocate memory for library base */
187 mem = allocmem(mh, negsize + sizeof(struct IntExecBase), MEMF_CLEAR);
188 if (!mem)
189 return NULL;
191 SysBase = mem + negsize;
193 #ifdef HAVE_PREPAREPLATFORM
194 /* Setup platform-specific data */
195 if (!Exec_PreparePlatform(&PD(SysBase), msg))
196 return NULL;
197 #endif
199 /* Setup function vectors */
200 AROS_CALL3(ULONG, AROS_SLIB_ENTRY(MakeFunctions, Exec, 15),
201 AROS_UFCA(APTR, SysBase, A0),
202 AROS_UFCA(CONST_APTR, LIBFUNCTABLE, A1),
203 AROS_UFCA(CONST_APTR, NULL, A2),
204 struct ExecBase *, SysBase);
206 /* Set default values */
207 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
208 SysBase->LibNode.lib_Node.ln_Pri = -100;
209 SysBase->LibNode.lib_Node.ln_Name = (char *)Exec_resident.rt_Name;
210 SysBase->LibNode.lib_IdString = (char *)Exec_resident.rt_IdString;
211 SysBase->LibNode.lib_Version = VERSION_NUMBER;
212 SysBase->LibNode.lib_Revision = REVISION_NUMBER;
213 SysBase->LibNode.lib_OpenCnt = 1;
214 SysBase->LibNode.lib_NegSize = negsize;
215 SysBase->LibNode.lib_PosSize = sizeof(struct IntExecBase);
216 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
218 NEWLIST(&SysBase->MemList);
219 SysBase->MemList.lh_Type = NT_MEMORY;
221 NEWLIST(&SysBase->ResourceList);
222 SysBase->ResourceList.lh_Type = NT_RESOURCE;
224 NEWLIST(&SysBase->DeviceList);
225 SysBase->DeviceList.lh_Type = NT_DEVICE;
227 NEWLIST(&SysBase->IntrList);
228 SysBase->IntrList.lh_Type = NT_INTERRUPT;
230 NEWLIST(&SysBase->LibList);
231 SysBase->LibList.lh_Type = NT_LIBRARY;
233 /* Add exec.library to system library list */
234 ADDHEAD(&SysBase->LibList, &SysBase->LibNode.lib_Node);
236 NEWLIST(&SysBase->PortList);
237 SysBase->PortList.lh_Type = NT_MSGPORT;
239 NEWLIST(&SysBase->TaskReady);
240 SysBase->TaskReady.lh_Type = NT_TASK;
242 NEWLIST(&SysBase->TaskWait);
243 SysBase->TaskWait.lh_Type = NT_TASK;
245 NEWLIST(&SysBase->SemaphoreList);
246 SysBase->TaskWait.lh_Type = NT_SEMAPHORE;
248 NEWLIST(&SysBase->ex_MemHandlers);
250 for (i = 0; i < 5; i++)
252 NEWLIST(&SysBase->SoftInts[i].sh_List);
253 SysBase->SoftInts[i].sh_List.lh_Type = NT_INTERRUPT;
256 NEWLIST(&PrivExecBase(SysBase)->ResetHandlers);
257 NEWLIST(&PrivExecBase(SysBase)->AllocMemList);
258 NEWLIST(&PrivExecBase(SysBase)->AllocatorCtxList);
260 InitSemaphore(&PrivExecBase(SysBase)->MemListSem);
261 InitSemaphore(&PrivExecBase(SysBase)->LowMemSem);
263 SysBase->SoftVer = VERSION_NUMBER;
264 SysBase->Quantum = 4;
265 SysBase->TaskTrapCode = Exec_TrapHandler;
266 SysBase->TaskExceptCode = NULL;
267 SysBase->TaskExitCode = Exec_TaskFinaliser;
268 SysBase->TaskSigAlloc = 0xFFFF;
269 SysBase->TaskTrapAlloc = 0;
271 /* Parse some arguments from command line */
272 args = (char *)LibGetTagData(KRN_CmdLine, 0, msg);
273 if (args)
275 char *opts;
278 * Enable mungwall before the first AllocMem().
279 * Yes, we have actually already called stdAlloc() once
280 * in order to allocate memory for SysBase itself, however
281 * this is not a real problem because it is never going
282 * to be freed.
284 * We store mungwall setting in private flags because it must not be
285 * switched at runtime (or hard crash will happen).
287 opts = strcasestr(args, "mungwall");
288 if (opts)
289 PrivExecBase(SysBase)->IntFlags = EXECF_MungWall;
291 opts = strcasestr(args, "stacksnoop");
292 if (opts)
293 PrivExecBase(SysBase)->IntFlags = EXECF_StackSnoop;
296 * Parse system runtime debug flags.
297 * These are public. In future they will be editable by prefs program.
298 * However in order to be able to turn them on during early startup,
299 * we apply them also here.
301 opts = strcasestr(args, "sysdebug=");
302 if (opts)
303 SysBase->ex_DebugFlags = ParseFlags(&opts[9], ExecFlagNames);
306 NEWLIST(&PrivExecBase(SysBase)->TaskStorageSlots);
308 #if defined(__AROSEXEC_SMP__)
309 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskRunningSpinLock);
310 NEWLIST(&PrivExecBase(SysBase)->TaskRunning);
311 PrivExecBase(SysBase)->TaskRunning.lh_Type = NT_TASK;
312 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskSpinningLock);
313 NEWLIST(&PrivExecBase(SysBase)->TaskSpinning);
314 PrivExecBase(SysBase)->TaskSpinning.lh_Type = NT_TASK;
315 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskReadySpinLock);
316 EXEC_SPINLOCK_INIT(&PrivExecBase(SysBase)->TaskWaitSpinLock);
317 #endif
319 SetSysBaseChkSum();
321 /* Add our initial MemHeader */
322 ADDHEAD(&SysBase->MemList, &mh->mh_Node);
324 /* Bring back saved values (or NULLs) */
325 SysBase->ColdCapture = ColdCapture;
326 SysBase->CoolCapture = CoolCapture;
327 SysBase->WarmCapture = WarmCapture;
328 SysBase->KickMemPtr = KickMemPtr;
329 SysBase->KickTagPtr = KickTagPtr;
330 SysBase->KickCheckSum = KickCheckSum;
332 SysBase->DebugAROSBase = PrepareAROSSupportBase(mh);
334 return SysBase;