r4368@vps: verhaegs | 2007-04-14 09:56:18 -0400
[AROS.git] / kernel / exec / exec_init.c
blob6e560c064cbe8c37d21be5df5fd82b2b93f26575
1 /*
2 Copyright C 2003, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: exec.library startup code
6 Lang: English
7 */
9 /*
10 Allthough this file exists inside PPC config code, it's really hardware
11 independant code and should be more commonly spreaded among different
12 platforms. It could be even common exec startup code.
14 Please note, that this kernel version doesn't support restoring data from
15 previous session interrupted by ColdReboot() call. In order to support that
16 both ColdReboot() definition and this kernel has to be re-worked.
18 NOTE (for hosted versions only):
19 Your bootstrap code has to provide full MultiBoot header, MMAP section
20 is mandatory. It has to point to memory area allocated for AROS. If
21 not passed, Exec will assume, that usable memory starts at 0x00000000
24 #include <aros/machine.h>
25 #include <aros/libcall.h>
26 #include <aros/asmcall.h>
28 #include <exec/types.h>
29 #include <exec/execbase.h>
30 #include <exec/resident.h>
31 #include <exec/memory.h>
33 #include <proto/exec.h>
36 Exec startup is our kernel start entry which is executed by proper loader.
37 It may pass MultiBoot-compilant data in order to allow exec work properly.
40 #include <aros/multiboot.h>
42 #include "startup.h"
44 UBYTE SECTION_CODE Exec_LibraryName[] = "exec.library";
45 UBYTE SECTION_CODE Exec_Version[] = "$VER: exec generic 41.1 (3.5.2003)\r\n";
46 UWORD SECTION_CODE Exec_Ver = 41;
47 UWORD SECTION_CODE Exec_Rev = 1;
50 First writable configuration memory area. The RomTagRages may contain up to
51 8 entries, each describing beginning and end of memory area to scan looking
52 for Resident modules. If you modify default config, do not forget to end it
53 with -1 pointer.
56 UWORD SECTION_CODE *RomTagRanges[2*8 + 1] = {
57 (UWORD*)startup, (UWORD*)&_END, (UWORD*)~0
60 struct Resident Exec_Resident SECTION_CODE = {
61 RTC_MATCHWORD,
62 &Exec_Resident,
63 (UBYTE*)&Exec_End,
65 41,
66 NT_LIBRARY,
67 126,
68 (UBYTE*)Exec_LibraryName,
69 (UBYTE*)Exec_Version,
70 startup
74 Gee! Static data? Not really. This one is created before kernel is write-
75 protected. It may allthough go somewhere into RAM even, if kernel is placed
76 in ROM memory.
78 MultiBoot_Storage is 4KB long. It should be rather enough to store all data
79 passed by bootstrap code. It may shrink in future even more.
82 ULONG MultiBoot_Storage[1024] = {0, };
84 #ifdef SysBase
85 #undef SysBase
86 #endif
87 #define SysBase ((struct ExecBase*)ExecBase)
89 void STDCALL NORETURN LaunchKernel(ULONG magic, ULONG addr)
91 struct ExecBase *ExecBase = (struct ExecBase*)0UL;
92 struct multiboot *mbinfo;
93 struct arosmb *arosmb = (struct arosmb*)MultiBoot_Storage;
94 int i;
97 If magic passed to kernel is inproper, it may be ColdReboot() thing.
98 Then just verify that arosmb->magic field is valid. If so, then all
99 data passed by bootstrap was properly saved.
101 If magic is proper, kernel was launched with proper MultiBoot data
102 and we have to parse them.
104 If both magic field and arosmb->magic are wrong, we have undefined
105 situation and may either reboot or halt forever here.
108 if (magic != MULTIBOOT_BOOTLOADER_MAGIC && arosmb->magic == MBRAM_VALID)
111 Handle proper reboot procedure
114 else if (magic == MULTIBOOT_BOOTLOADER_MAGIC && addr != NULL)
116 mbinfo = (struct multiboot*)addr;
117 arosmb->magic = MBRAM_VALID;
118 arosmb->flags = 0L;
120 if (mbinfo->flags && MB_FLAGS_MEM)
122 arosmb->flags |= MB_FLAGS_MEM;
123 arosmb->mem_lower = mbinfo->mem_lower;
124 arosmb->mem_upper = mbinfo->mem_upper;
126 if (mbinfo->flags && MB_FLAGS_LDRNAME)
128 arosmb->flags |= MB_FLAGS_LDRNAME;
129 strncpy(arosmb->ldrname, mbinfo->loader_name, 29);
131 if (mbinfo->flags && MB_FLAGS_CMDLINE)
133 arosmb->flags |= MB_FLAGS_CMDLINE;
134 strncpy(arosmb->cmdline, mbinfo->cmdline, 199);
136 if (mbinfo->flags && MB_FLAGS_MMAP)
138 arosmb->flags |= MB_FLAGS_MMAP;
139 arosmb->mmap_addr = ((ULONG)((ULONG)arosmb + sizeof(struct arosmb)));
140 arosmb->mmap_len = mbinfo->mmap_length;
141 memcpy((APTR)arosmb->mmap_addr,
142 (APTR)mbinfo->mmap_addr,
143 mbinfo->mmap_length);
145 if (mbinfo->flags && MB_FLAGS_DRIVES)
147 if (mbinfo->drives_length > 0)
149 arosmb->flags |= MB_FLAGS_DRIVES;
150 if (arosmb->flags && MB_FLAGS_MMAP)
152 arosmb->drives_addr =
153 ((ULONG)arosmb->mmap_addr + arosmb->mmap_len);
155 else
157 arosmb->drives_addr =
158 ((ULONG)arosmb + sizeof(struct arosmb));
160 arosmb->drives_len = mbinfo->drives_length;
161 memcpy((APTR)arosmb->drives_addr,
162 (APTR)mbinfo->drives_addr,
163 mbinfo->drives_length);
167 else
169 /* Undefined situation. You may halt here only... */
170 do {} while(1);
174 Did we already defined ExecBase address? It might happen before, when
175 we discovered ColdReboot() and found usable ExecBase. If no address
176 assigned, do it now.
178 if (ExecBase == NULL)
180 /* MMAP information is favorized always! */
181 if (arosmb->flags && MB_FLAGS_MMAP)
183 struct mb_mmap *mmap = (struct mb_mmap*)arosmb->mmap_addr;
185 /* Iterate through mmaps and find first RAM area */
186 while(mmap->type != MMAP_TYPE_RAM) mmap++;
188 /* For kernel purpouses, leave first 16KB free. */
189 if (mmap->addr_low < 0x4000) {
190 ExecBase = (struct ExecBase *)0x4000;
191 } else {
192 ExecBase = (struct ExecBase *)mmap->addr_low;
195 else
198 No mmap given? Assume then, that RAM starts at absolute
199 addres 0x00000000, and place ExecBase at 16th KB of mem
201 ExecBase = (struct ExecBase *)0x4000;
204 /* Move ExecBase so you may put functions table */
205 #warning WARNING: Assuming 150 exec functions!
206 (ULONG)ExecBase += 150 * LIB_VECTSIZE;
207 *(struct ExecBase**)4UL = ExecBase;
210 /* Prevent Kick* pointers from beeing deleted */
211 APTR
212 KickMemPtr = ExecBase->KickMemPtr,
213 KickTagPtr = ExecBase->KickTagPtr,
214 KickCheckSum = ExecBase->KickCheckSum;
216 /* Clear most of ExecBase now */
217 bzero(&ExecBase->IntVects[0],
218 sizeof(struct ExecBase) - offsetof(ExecBase, IntVects[0]));
220 /* Restore Kick* fields */
221 ExecBase->KickMemPtr = KickMemPtr;
222 ExecBase->KickTagPtr = KickTagPtr;
223 ExecBase->KickCheckSum = KickCheckSum;
226 Calculate checksum for ExecBase location. It may be used by reboot, to
227 prove LibBase validity.
230 ExecBase->ChkBase = ~(ULONG)ExecBase;
233 Initialize system-wide lists
236 NEWLIST(&SysBase->MemList);
237 SysBase->MemList.lh_Type = NT_MEMORY;
238 NEWLIST(&SysBase->ResourceList);
239 SysBase->ResourceList.lh_Type = NT_RESOURCE;
240 NEWLIST(&SysBase->DeviceList);
241 SysBase->DeviceList.lh_Type = NT_DEVICE;
242 NEWLIST(&SysBase->LibList);
243 SysBase->LibList.lh_Type = NT_LIBRARY;
244 NEWLIST(&SysBase->PortList);
245 SysBase->PortList.lh_Type = NT_MSGPORT;
246 NEWLIST(&SysBase->TaskReady);
247 SysBase->TaskReady.lh_Type = NT_TASK;
248 NEWLIST(&SysBase->TaskWait);
249 SysBase->TaskWait.lh_Type = NT_TASK;
250 NEWLIST(&SysBase->IntrList);
251 SysBase->IntrList.lh_Type = NT_INTERRUPT;
252 NEWLIST(&SysBase->SemaphoreList);
253 SysBase->SemaphoreList.lh_Type = NT_SIGNALSEM;
254 NEWLIST(&SysBase->ex_MemHandlers);
256 for (i=0; i < 5; i++)
258 NEWLIST(&SysBase->SoftInts[i].sh_List);
259 SysBase->SoftInts[i].sh_List.lh_Type = NT_SOFTINT;
263 Lists are already done, prepare ExecBase values
266 SysBase->TaskSigAlloc = 0x0000ffff;
267 SysBase->TaskTrapAlloc = 0x8000;
268 SysBase->TaskTrapCode = NULL; /* These three fields will be filled */
269 SysBase->TaskExceptCode = NULL; /* By kernel.resource */
270 SysBase->TaskExitCode = NULL;
272 SysBase->LibNode.lib_Node.ln_Type = NT_LIBRARY;
273 SysBase->LibNode.lib_Node.ln_Pri = 0;
274 SysBase->LibNode.lib_Node.ln_Name = (UBYTE*)Exec_LibraryName;
275 SysBase->LibNode.lib_Flags = LIBF_CHANGED | LIBF_SUMUSED;
276 SysBase->LibNode.lib_PosSize = sizeof(struct ExecBase);
277 SysBase->LibNode.lib_OpenCnt = 1;
278 SysBase->LibNode.lib_IdString = (UBYTE*)Exec_Version;
279 SysBase->LibNode.lib_Version = Exec_Ver;
280 SysBase->LibNode.lib_Revision = Exec_Rev;
283 NOTE:
284 On some architectures, VBlankFrequency will be used at init by
285 kernel.resource to set up interrupt timer properly.
287 SysBase->Quantum = 4;
288 SysBase->VBlankFrequency = 200; /* Use 200Hz timer by default */
291 Make SysBase functions
293 SysBase->LibNode.lib_NegSize =
294 AROS_UFC4(UWORD, Exec_MakeFunctions,
295 AROS_UFCA(APTR, ExecBase, A0),
296 AROS_UFCA(APTR, ExecFunctions, A1),
297 AROS_UFCA(APTR, NULL, A2),
298 AROS_UFCA(struct ExecBase *, ExecBase, A6));
300 if (arosmb->flags && MB_FLAGS_MMAP)
302 int i=0;
303 struct mb_mmap *map = (struct mb_mmap*)arosmb->mmap_addr;
305 while (i < arosmb->mmap_len)
307 ULONG flags;
309 if (map->type == MMAP_TYPE_RAM)
311 if ((map->addr_low < 0x01000000) &&
312 ((map->addr_low + map->len_low) < 0x01000000))
314 if (map->addr_low <=
315 ((ULONG)ExecBase + sizeof(struct ExecBase)))
317 map->addr_low = (ULONG)ExecBase + sizeof(struct ExecBase);
318 map->addr_low = (map->addr_low + 31) & ~31;
319 map->len_low -= map->addr_low;
321 AddMemList(map->len_low,
322 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK |
323 MEMF_LOCAL | MEMF_24BITDMA,
324 -10,
325 (APTR)map->addr_low,
326 (STRPTR)"dma memory");
328 else
330 AddMemList(map->len_low,
331 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
333 (APTR)map->addr_low,
334 (STRPTR)"fast memory");
337 i++;
338 map++;
341 else
343 ULONG addr = (ULONG)ExecBase + sizeof(struct ExecBase);
344 addr = (addr + 31) & ~31;
346 #warning WARNING: look out - no mmap structures!
348 AddMemList(arosmb->mem_lower - addr,
349 MEMF_CHIP | MEMF_PUBLIC | MEMF_KICK |
350 MEMF_LOCAL | MEMF_24BITDMA,
351 -10,
352 (APTR)addr,
353 (STRPTR)"dma memory");
355 AddMemList(arosmb->mem_upper - (ULONG)&_END,
356 MEMF_FAST | MEMF_PUBLIC | MEMF_KICK | MEMF_LOCAL,
358 (APTR)&_END,
359 (STRPTR)"fast memory");
362 SumLibrary((struct Library*)SysBase);
363 Enqueue(&SysBase->LibList, &SysBase->LibNode.lib_Node);
366 At this point, we do have more or less valid exec.library. Not, it's
367 time to scan for other resident modules. Some of them have to be
368 initialized implictly.
371 SysBase->ResModules = RomTagScanner(SysBase, &RomTagRanges);
374 Initialize kernel.resource!
376 kernel.resource will add some functionality to the working system. It
377 will also patch exec.library properly, in order to implement CPU and
378 hardware specific things.
380 InitResident(FindResident("kernel.resource"), NULL);
383 do {} while(1);