2 Copyright © 1995-2015, The AROS Development Team. All rights reserved.
5 Desc: Sets up the ExecBase a bit. (Mostly clearing).
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>
24 #include <proto/alib.h>
25 #include <proto/exec.h>
26 #include <proto/kernel.h>
28 #include LC_LIBDEFS_FILE
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
);
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
)
87 if (((IPTR
)sysbase
) & 0x80000001)
90 if (sysbase
->ChkBase
!= ~(IPTR
)sysbase
)
92 if (sysbase
->SoftVer
!= VERSION_NUMBER
)
95 return GetSysBaseChkSum(sysbase
) == 0xffff;
98 UWORD
GetSysBaseChkSum(struct ExecBase
*sysbase
)
101 UWORD
*p
= (UWORD
*)&sysbase
->SoftVer
;
102 while (p
<= &sysbase
->ChkSum
)
107 void SetSysBaseChkSum(void)
109 SysBase
->ChkBase
=~(IPTR
)SysBase
;
111 SysBase
->ChkSum
= GetSysBaseChkSum(SysBase
) ^ 0xffff;
114 static APTR
allocmem(struct MemHeader
*mh
, ULONG size
, ULONG attributes
)
118 if (IsManagedMem(mh
))
120 struct MemHeaderExt
*mhe
= (struct MemHeaderExt
*)mh
;
123 ret
= mhe
->mhe_Alloc(mhe
, size
, &attributes
);
129 ret
= stdAlloc(mh
, NULL
, size
, attributes
, NULL
, NULL
);
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
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
)
158 VOID
**fp
= LIBFUNCTABLE
;
159 APTR ColdCapture
= NULL
, CoolCapture
= NULL
, WarmCapture
= NULL
;
160 APTR KickMemPtr
= NULL
, KickTagPtr
= NULL
, KickCheckSum
= NULL
;
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
);
191 SysBase
= mem
+ negsize
;
193 #ifdef HAVE_PREPAREPLATFORM
194 /* Setup platform-specific data */
195 if (!Exec_PreparePlatform(&PD(SysBase
), msg
))
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
);
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
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");
289 PrivExecBase(SysBase
)->IntFlags
= EXECF_MungWall
;
291 opts
= strcasestr(args
, "stacksnoop");
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=");
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
);
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
);