prism2.device: Compiler delint
[AROS.git] / arch / m68k-amiga / boot / start.c
blob7c55bb09631a74971781b076edfd54a9122ad680
1 /*
2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
3 $Id$
5 Desc: m68k-amiga bootstrap to exec.
6 Lang: english
7 */
9 #include <aros/kernel.h>
10 #include <aros/debug.h>
11 #include <exec/memory.h>
12 #include <exec/resident.h>
13 #include <exec/execbase.h>
14 #include <proto/exec.h>
15 #include <hardware/cpu/memory.h>
17 #include "memory.h"
19 #include "kernel_romtags.h"
20 #include "kernel_base.h"
22 #include "exec_intern.h"
24 #include "amiga_hwreg.h"
25 #include "amiga_irq.h"
27 #include "early.h"
28 #include "debug.h"
30 #define SS_STACK_SIZE 0x02000
32 /* Must match with AROSBootstrap.c! */
33 #define ABS_BOOT_MAGIC 0x4d363802
34 struct BootStruct
36 ULONG magic;
37 struct TagItem *kerneltags;
38 APTR ss_address;
39 ULONG ss_size;
40 APTR magicfastmem;
41 LONG magicfastmemsize;
44 static struct BootStruct *GetBootStruct(struct ExecBase *eb)
46 if (eb->DebugData) {
47 struct BootStruct *BootS = (struct BootStruct*)eb->DebugData;
48 if (BootS->magic == ABS_BOOT_MAGIC)
49 return BootS;
51 return NULL;
54 extern const struct Resident Exec_resident;
55 extern struct ExecBase *AbsExecBase;
57 static void protectKick(struct MemHeader *mh, struct MemList *ml, ULONG *mask);
59 extern void __attribute__((interrupt)) Exec_Supervisor_Trap (void);
61 #define _AS_STRING(x) #x
62 #define AS_STRING(x) _AS_STRING(x)
64 /* Create a sign extending call stub:
65 * foo:
66 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
67 * 0x4eb9 .... ....
68 * ext.w %d0 // EXT_BYTE only
69 * 0x4880
70 * ext.l %d0 // EXT_BYTE and EXT_WORD
71 * 0x48c0
72 * rts
73 * 0x4e75
75 #define EXT_BYTE(lib, libname, funcname, funcid) \
76 do { \
77 void libname##_##funcname##_Wrapper(void) \
78 { asm volatile ( \
79 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
80 "ext.w %d0\n" \
81 "ext.l %d0\n" \
82 "rts\n"); } \
83 /* Insert into the library's jumptable */ \
84 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
85 } while (0)
86 #define EXT_WORD(lib, libname, funcname, funcid) \
87 do { \
88 void libname##_##funcname##_Wrapper(void) \
89 { asm volatile ( \
90 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
91 "ext.l %d0\n" \
92 "rts\n"); } \
93 /* Insert into the library's jumptable */ \
94 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
95 } while (0)
97 * Create a register preserving call stub:
98 * foo:
99 * movem.l %d0-%d1/%a0-%a1,%sp@-
100 * 0x48e7 0xc0c0
101 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
102 * 0x4eb9 .... ....
103 * movem.l %sp@+,%d0-%d1/%d0-%a1
104 * 0x4cdf 0x0303
105 * rts
106 * 0x4e75
108 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
109 do { \
110 void libname##_##funcname##_Wrapper(void) \
111 { asm volatile ( \
112 "movem.l %d0-%d1/%a0-%a1,%sp@-\n" \
113 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
114 "movem.l %sp@+,%d0-%d1/%a0-%a1\n" \
115 "rts\n" ); } \
116 /* Insert into the library's jumptable */ \
117 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
118 } while (0)
119 /* Inject arbitrary code into the jump table
120 * Used for GetCC and nano-stubs
122 #define FAKE_IT(lib, libname, funcname, funcid, ...) \
123 do { \
124 UWORD *asmcall = (UWORD *)__AROS_GETJUMPVEC(lib, funcid); \
125 const UWORD code[] = { __VA_ARGS__ }; \
126 asmcall[0] = code[0]; \
127 asmcall[1] = code[1]; \
128 asmcall[2] = code[2]; \
129 } while (0)
130 /* Inject a 'move.w #value,%d0; rts" sequence into the
131 * jump table, to fake an private syscall.
133 #define FAKE_ID(lib, libname, funcname, funcid, value) \
134 FAKE_IT(lib, libname, funcname, funcid, 0x303c, value, 0x4e75)
136 extern void SuperstackSwap(void);
137 /* This calls the register-ABI library
138 * routine Exec/InitCode, for use in NewStackSwap()
140 static LONG doInitCode(struct BootStruct *BootS)
142 /* Attempt to allocate a new supervisor stack */
143 do {
144 APTR ss_stack;
145 ULONG ss_stack_size;
147 if (BootS && BootS->ss_address) {
148 ss_stack = BootS->ss_address;
149 ss_stack_size = BootS->ss_size;
150 } else {
151 ss_stack = AllocMem(SS_STACK_SIZE, MEMF_ANY | MEMF_CLEAR | MEMF_REVERSE);
152 if (ss_stack && ((ULONG)ss_stack & (PAGE_SIZE - 1))) {
153 /* Normally ss_stack is page aligned because it is first MEMF_REVERSE
154 * allocation. But we must check it because enabled mungwall or expansion
155 * boot rom code can allocate some memory.
157 FreeMem(ss_stack, SS_STACK_SIZE);
158 ss_stack = AllocMem(SS_STACK_SIZE + PAGE_SIZE - 1, MEMF_ANY | MEMF_CLEAR | MEMF_REVERSE);
159 ss_stack = (APTR)(((ULONG)ss_stack + PAGE_SIZE - 1) & PAGE_MASK);
161 ss_stack_size = SS_STACK_SIZE;
163 DEBUGPUTHEX(("SS lower", (ULONG)ss_stack));
164 DEBUGPUTHEX(("SS upper", (ULONG)ss_stack + ss_stack_size - 1));
165 if (ss_stack == NULL) {
166 DEBUGPUTS(("Strange. Can't allocate a new system stack\n"));
167 Early_Alert(CODE_ALLOC_FAIL);
168 break;
170 SysBase->SysStkLower = ss_stack;
171 SysBase->SysStkUpper = ss_stack + ss_stack_size;
172 SetSysBaseChkSum();
174 Supervisor((ULONG_FUNC)SuperstackSwap);
175 } while(0);
177 InitCode(RTF_COLDSTART, 0);
179 return 0;
182 extern BYTE _rom_start;
183 extern BYTE _rom_end;
184 extern BYTE _ext_start;
185 extern BYTE _ext_end;
186 extern BYTE _ss;
187 extern BYTE _ss_end;
189 /* Protect the 'ROM' if it is actually in RAM.
191 static APTR protectAlloc(struct MemHeader *mh, APTR start, APTR end, const UBYTE *name, BOOL pagealign)
193 APTR tmp;
194 ULONG length;
196 if (pagealign) {
197 start = (APTR)((ULONG)start & PAGE_MASK);
198 length = (end - start + PAGE_SIZE - 1) & PAGE_MASK;
199 } else {
200 length = end - start;
202 tmp = Early_AllocAbs(mh, start, length);
203 DEBUGPUTS(("* "));
204 if (name)
205 DEBUGPUTS((name));
206 else
207 DEBUGPUTS(("<no name>"));
208 if (!tmp)
209 DEBUGPUTS((" !"));
210 DEBUGPUTHEX(("\nStart ", (ULONG)start));
211 DEBUGPUTHEX(("End ", (ULONG)end - 1));
212 DEBUGPUTHEX(("Size ", length));
213 return tmp;
215 static void protectROM(struct MemHeader *mh)
217 DEBUGPUTHEX(("Protect", (IPTR)mh));
218 protectAlloc(mh, &_ss, &_ss_end, "SS", FALSE);
219 DEBUGPUTHEX(("First ", (IPTR)mh->mh_First));
220 DEBUGPUTHEX(("Bytes ", (IPTR)mh->mh_First->mc_Bytes));
223 static struct MemHeader *addmemoryregion(ULONG startaddr, ULONG size, struct MemList *ml, ULONG *mask, BOOL magicfast)
225 if (size < 65536)
226 return NULL;
227 if (magicfast) {
228 krnCreateMemHeader("magic fast memory", -8,
229 (APTR)startaddr, size,
230 MEMF_FAST | MEMF_PUBLIC | ((startaddr & 0xff000000) == 0 ? MEMF_24BITDMA : 0));
231 } else if (startaddr < 0x00c00000) {
232 krnCreateMemHeader("chip memory", -10,
233 (APTR)startaddr, size,
234 MEMF_CHIP | MEMF_KICK | MEMF_PUBLIC | MEMF_LOCAL | MEMF_24BITDMA);
235 } else {
236 krnCreateMemHeader("memory", -5,
237 (APTR)startaddr, size,
238 MEMF_FAST | MEMF_KICK | MEMF_PUBLIC | MEMF_LOCAL | ((startaddr & 0xff000000) == 0 ? MEMF_24BITDMA : 0));
241 /* Must be done first, in case SS is in it */
242 protectKick((struct MemHeader*)startaddr, ml, mask);
244 protectROM((struct MemHeader*)startaddr);
245 return (struct MemHeader*)startaddr;
248 static BOOL IsSysBaseValidNoVersion(struct ExecBase *sysbase)
250 if (sysbase == NULL || (((ULONG)sysbase) & 0x80000001))
251 return FALSE;
252 if (sysbase->ChkBase != ~(IPTR)sysbase)
253 return FALSE;
254 return GetSysBaseChkSum(sysbase) == 0xffff;
257 /* In the following functions, we use bit 0 of the
258 * MemEntry->me_Addr to indicate whether or not
259 * that MemEntry in the MemList has been 'locked down'
261 * (addr & 1) = unallocated
262 * !(addr & 1) = allocated
265 /* Remove all bit 0 marks
267 /* We support up to 32 KickMemPtr tags in pre-expansion.library RAM */
268 static void markKick(struct MemList *ml, ULONG *mask)
270 int ndx;
271 for (ndx = 0; ml ; ml = (struct MemList*)ml->ml_Node.ln_Succ) {
272 int i;
273 for (i = 0; i < ml->ml_NumEntries; i++, ndx++) {
274 if (ndx < 32)
275 (*mask) |= (1 << ndx);
280 static void protectKick(struct MemHeader *mh, struct MemList *ml, ULONG *mask)
282 int ndx = 0;
283 ULONG protectKickBits = *mask;
285 DEBUGPUTHEX(("protectKick", (IPTR)ml));
287 if (!mh)
288 return;
290 while (ml) {
291 int i;
292 for (i = 0; i < ml->ml_NumEntries; i++, ndx++) {
293 APTR start = (APTR)((IPTR)ml->ml_ME[i].me_Addr & ~1);
294 APTR end = start + ml->ml_ME[i].me_Length;
296 /* Already allocated? */
297 if (ndx >= 32 || !(protectKickBits & (1 << ndx)))
298 continue;
300 if ((mh->mh_Lower > start) ||
301 (mh->mh_Upper < end))
302 continue;
304 if (protectAlloc(mh, start, end, ml->ml_Node.ln_Name, FALSE)) {
305 protectKickBits &= ~(1 << ndx);
308 ml = (struct MemList*)ml->ml_Node.ln_Succ;
311 *mask = protectKickBits;
312 return;
315 void InitKickMemDiag(void)
317 struct MemList *ml = PrivExecBase(SysBase)->PlatformData.ep_KickMemPtr;
318 DEBUGPUTS(("KickMem allocation phase 2/2\n"));
319 while (ml) {
320 int i;
321 for (i = 0; i < ml->ml_NumEntries; i++) {
322 APTR start = ml->ml_ME[i].me_Addr;
323 ULONG len = ml->ml_ME[i].me_Length;
325 DEBUGPUTHEX(("Addr", (IPTR)start));
326 DEBUGPUTHEX(("Len", len));
328 /* Simply attempt to allocate everything again */
329 if (InternalAllocAbs(start, len, SysBase))
330 DEBUGPUTS(("-> Allocated\n"));
332 ml = (struct MemList*)ml->ml_Node.ln_Succ;
336 static BOOL InitKickMem(ULONG *mask, struct ExecBase *SysBase)
338 int ndx = 0;
339 struct MemList *ml = SysBase->KickMemPtr;
340 ULONG protectKickBits = *mask;
341 BOOL ok = TRUE;
343 DEBUGPUTHEX(("KickMemPtr", (IPTR)ml));
345 while (ml) {
346 int i;
347 for (i = 0; i < ml->ml_NumEntries; i++,ndx++) {
348 APTR start = ml->ml_ME[i].me_Addr;
349 ULONG len = ml->ml_ME[i].me_Length;
351 /* Already allocated? */
352 if (ndx < 32 && !(protectKickBits & (1 << ndx)))
353 continue;
355 DEBUGPUTHEX(("Addr", (IPTR)start));
356 DEBUGPUTHEX(("Len", len));
358 if (TypeOfMem(start) == 0) {
359 /* Do not stop if memory is not in memory list yet */
360 DEBUGPUTS(("-> unavailable\n"));
361 ok = FALSE;
362 continue;
365 /* Use the non-mungwalling AllocAbs */
366 if (!InternalAllocAbs(start, len, SysBase))
367 return FALSE;
369 protectKickBits |= (1 << ndx);
371 ml = (struct MemList*)ml->ml_Node.ln_Succ;
374 *mask = protectKickBits;
376 return ok;
378 #if 0 // debug stuff, do not remove
379 static ULONG SumKickDataX(struct ExecBase *sb)
381 ULONG chksum = 0;
382 BOOL isdata = FALSE;
383 struct ExecBase *sysbase = sb;
385 if (sysbase->KickTagPtr) {
386 IPTR *list = sysbase->KickTagPtr;
387 while(*list)
389 chksum += (ULONG)*list;
390 DEBUGPUTHEX(("LIST", (ULONG)list));
391 DEBUGPUTHEX(("LISTP", (ULONG)*list));
392 DEBUGPUTHEX(("CHK", chksum));
393 /* on amiga, if bit 31 is set then this points to another list of
394 * modules rather than pointing to a single module. bit 31 is
395 * inconvenient on architectures where code may be loaded above
396 * 2GB. on these platforms we assume aligned pointers and use bit
397 * 0 instead */
398 #ifdef __mc68000__
399 if(*list & 0x80000000) { list = (IPTR *)(*list & 0x7fffffff); continue; }
400 #else
401 if(*list & 0x1) { list = (IPTR *)(*list & ~(IPTR)0x1); continue; }
402 #endif
403 list++;
404 isdata = TRUE;
408 if (sysbase->KickMemPtr) {
409 struct MemList *ml = (struct MemList*)sysbase->KickMemPtr;
410 while (ml) {
411 UBYTE i;
412 ULONG *p = (ULONG*)ml;
413 for (i = 0; i < sizeof(struct MemList) / sizeof(ULONG); i++)
414 chksum += p[i];
415 DEBUGPUTHEX(("MEM", (ULONG)p));
416 DEBUGPUTHEX(("CHK", chksum));
417 ml = (struct MemList*)ml->ml_Node.ln_Succ;
418 isdata = TRUE;
421 if (isdata && !chksum)
422 chksum--;
423 return chksum;
425 #endif
427 void doColdCapture(void)
429 APTR ColdCapture = SysBase->ColdCapture;
430 if (ColdCapture == NULL)
431 return;
433 if (((ULONG *)ColdCapture)[1] == AROS_MAKE_ID('F','A','K','E')) {
434 /* Fake SysBase installed by AROSBootstrap.
436 * In this case, ColdCapture is the trampoline executed
437 * by the AOS ROM to get into AROS. We need to keep
438 * ColdCapture around in AROS SysBase, but we don't
439 * want to execute it (and cause an infinite loop).
441 DEBUGPUTS(("[ColdCapture] Ignoring AOS->AROS trampoline\n"));
442 return;
445 SysBase->ColdCapture = NULL;
446 /* ColdCapture calling method is a little
447 * strange. It's in supervisor mode, requires
448 * the return location in A5, and SysBase in A6.
450 asm volatile (
451 "move.l %0,%%a0\n"
452 "move.l %1,%%a6\n"
453 "move.l #0f,%%a5\n"
454 "jmp (%%a0)\n"
455 "0:\n"
457 : "m" (ColdCapture), "m" (SysBase)
458 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
459 "a0", "a1", "a2", "a3", "a4", "a5", "a6");
462 static void RomInfo(IPTR rom)
464 APTR ptr = (APTR)rom;
465 CONST_STRPTR str;
467 if ((*(UWORD *)(ptr + 8) == 0x0000) &&
468 (*(UWORD *)(ptr + 10) == 0xffff) &&
469 (*(UWORD *)(ptr + 12) == *(UWORD *)(ptr + 16)) &&
470 (*(UWORD *)(ptr + 14) == *(UWORD *)(ptr + 18)) &&
471 (*(UWORD *)(ptr + 20) == 0xffff) &&
472 (*(UWORD *)(ptr + 22) == 0xffff)) {
473 DEBUGPUTHEX(("ROM Location", rom));
474 DEBUGPUTD((" Version", *(UWORD *)(ptr + 12)));
475 DEBUGPUTD((" Revision", *(UWORD *)(ptr + 14)));
476 str = (ptr + 24);
477 DEBUGPUTS((" ROM Type: ")); DEBUGPUTS((str)); DEBUGPUTS(("\n"));
478 str += strlen(str) + 1;
479 DEBUGPUTS((" Copyright: ")); DEBUGPUTS((str));
480 str += strlen(str) + 1;
481 DEBUGPUTS((str));
482 str += strlen(str) + 1;
483 DEBUGPUTS((str));
484 DEBUGPUTS(("\n"));
485 str += strlen(str) + 1;
486 DEBUGPUTS((" ROM Model: ")); DEBUGPUTS((str));
487 DEBUGPUTS(("\n"));
491 void exec_boot(ULONG *membanks, ULONG *cpupcr)
493 #if 0
494 struct ExecBase *oldSysBase = *(APTR *)4;
495 DebugInit();
496 DEBUGPUTHEX(("X SysBase->KickCheckSum", (ULONG)oldSysBase->KickCheckSum));
497 SumKickDataX(oldSysBase);
498 #endif
500 struct TagItem bootmsg[] = {
501 /* nomonitors - Until we have working m68k PCI support,
502 * attempting to load the monitor drivers
503 * just wastes a lot of time during boot
505 #if AROS_SERIAL_DEBUG
506 { KRN_CmdLine, (IPTR)"nomonitors sysdebug=InitCode" },
507 // { KRN_CmdLine, (IPTR)"nomonitors sysdebug=InitCode,debugmmu,mungwall" },
508 #else
509 { KRN_CmdLine, (IPTR)"nomonitors" },
510 #endif
511 { KRN_KernelStackBase, (IPTR)&_ss },
512 { KRN_KernelStackSize, (IPTR)(&_ss_end - &_ss) },
513 { TAG_END },
515 struct TagItem *bootmsgptr = bootmsg;
516 volatile APTR *trap;
517 int i;
518 BOOL wasvalid, arosbootstrapmode;
519 UWORD *kickrom[8];
520 struct MemHeader *mh;
521 LONG oldLastAlert[4];
522 ULONG oldmem;
523 UWORD attnflags;
524 APTR ColdCapture = NULL, CoolCapture = NULL, WarmCapture = NULL;
525 ULONG KickMemMask = 0;
526 APTR KickMemPtr = NULL, KickTagPtr = NULL, KickCheckSum = NULL;
527 struct BootStruct *BootS = NULL;
528 /* We can't use the global 'SysBase' symbol, since
529 * the compiler does not know that PrepareExecBase
530 * may change it out from under us.
532 struct ExecBase *oldSysBase = *(APTR *)4;
533 #define SysBase CANNOT_USE_SYSBASE_SYMBOL_HERE
535 #if AROS_SERIAL_DEBUG
536 DebugInit();
537 #endif
539 trap = (APTR *)(NULL);
541 /* Set all the exceptions to the Early_Exception
543 for (i = 2; i < 64; i++) {
544 if (i != 31)
545 trap[i] = Early_Exception;
548 /* Let the world know we exist
550 DebugInit();
551 DEBUGPUTS(("[reset]\n"));
552 RomInfo(0xf80000);
553 RomInfo(0xe00000);
554 RomInfo(0xf00000);
556 /* Convert CPU/FPU flags to AttnFlags */
557 attnflags = cpupcr[0] & 0xffff;
558 if (attnflags & (AFF_68030 | AFF_68040 | AFF_68060))
559 attnflags |= AFF_ADDR32;
560 if (cpupcr[0] & 0xffff0000) {
561 attnflags |= AFF_FPU;
562 if (attnflags & (AFF_68040 | AFF_68060))
563 attnflags |= AFF_FPU40;
564 // AFF_68881 | AFF_68882 set only if 040/060 math emulation running
565 else if (((cpupcr[0] >> 16) & 0xff) <= 0x1f)
566 attnflags |= AFF_68881;
567 else
568 attnflags |= AFF_68881 | AFF_68882;
571 #if AROS_SERIAL_DEBUG
572 DEBUGPUTS(("CPU: "));
573 if (attnflags & AFF_68060)
574 DEBUGPUTS(("68060"));
575 else if (attnflags & AFF_68040)
576 DEBUGPUTS(("68040"));
577 else if (attnflags & AFF_68030)
578 DEBUGPUTS(("68030"));
579 else if (attnflags & AFF_68020) {
580 if (attnflags & AFF_ADDR32)
581 DEBUGPUTS(("68020"));
582 else
583 DEBUGPUTS(("68EC020"));
584 } else if (attnflags & AFF_68010)
585 DEBUGPUTS(("68010"));
586 else
587 DEBUGPUTS(("68000"));
588 DEBUGPUTS((" FPU: "));
589 if (attnflags & AFF_FPU40) {
590 if (attnflags & AFF_68060)
591 DEBUGPUTS(("68060"));
592 else if (attnflags & AFF_68040)
593 DEBUGPUTS(("68040"));
594 else
595 DEBUGPUTS(("-"));
596 } else if (attnflags & AFF_68882)
597 DEBUGPUTS(("68882"));
598 else if (attnflags & AFF_68881)
599 DEBUGPUTS(("68881"));
600 else
601 DEBUGPUTS(("-"));
602 DEBUGPUTS(("\n"));
603 if (cpupcr[1])
604 DEBUGPUTHEX(("PCR", cpupcr[1]));
605 #endif
608 /* Zap out old SysBase if invalid */
609 arosbootstrapmode = FALSE;
610 wasvalid = IsSysBaseValid(oldSysBase);
611 if (wasvalid) {
612 DEBUGPUTHEX(("[SysBase] was at", (ULONG)oldSysBase));
613 } else {
614 wasvalid = IsSysBaseValidNoVersion(oldSysBase);
615 if (wasvalid) {
616 arosbootstrapmode = TRUE;
617 DEBUGPUTHEX(("[SysBase] fakebase at", (ULONG)oldSysBase));
618 BootS = GetBootStruct(oldSysBase);
619 if (BootS)
620 bootmsgptr = BootS->kerneltags;
621 wasvalid = TRUE;
622 } else {
623 DEBUGPUTHEX(("[SysBase] invalid at", (ULONG)oldSysBase));
624 wasvalid = FALSE;
627 if (bootmsgptr[0].ti_Tag == KRN_CmdLine) {
628 DEBUGPUTS(("[SysBase] kernel commandline '"));
629 DEBUGPUTS(((CONST_STRPTR)bootmsgptr[0].ti_Data));
630 DEBUGPUTS(("'\n"));
633 if (wasvalid) {
634 /* Save reset proof vectors */
635 ColdCapture = oldSysBase->ColdCapture;
636 CoolCapture = oldSysBase->CoolCapture;
637 WarmCapture = oldSysBase->WarmCapture;
638 KickMemPtr = oldSysBase->KickMemPtr;
639 KickTagPtr = oldSysBase->KickTagPtr;
640 KickCheckSum = oldSysBase->KickCheckSum;
642 /* Mark the oldSysBase as processed */
643 oldSysBase = NULL;
646 if (BootS && BootS->magicfastmem) {
647 /* Add early magic fast ram pool
648 * Makes it possible to have execbase and others in fast ram even
649 * if fast ram is non-autocnfig diagrom type.
651 membanks -= 2;
652 membanks[0] = (ULONG)BootS->magicfastmem;
653 membanks[1] = BootS->magicfastmemsize;
656 /* Adjust to skip the first 1K/4K bytes of
657 * Chip RAM. It's reserved for the Trap area.
659 for (i = 0; membanks[i + 2 + 1]; i += 2);
660 if (arosbootstrapmode || (attnflags & AFF_68030))
661 membanks[i + 0] = 0x1000;
662 else
663 membanks[i + 0] = 0x400;
664 membanks[i + 1] -= membanks[i + 0];
666 #if AROS_SERIAL_DEBUG
667 for (i = 0; membanks[i + 1]; i += 2) {
668 ULONG addr = membanks[i + 0];
669 ULONG size = membanks[i + 1];
670 DEBUGPUTHEX(("RAM lower", addr));
671 DEBUGPUTHEX(("RAM upper", addr + size - 1));
673 #endif
675 kickrom[0] = (UWORD*)&_rom_start;
676 kickrom[1] = (UWORD*)&_rom_end;
677 kickrom[2] = (UWORD*)0x00f00000;
678 kickrom[3] = (UWORD*)0x00f80000;
679 kickrom[4] = (UWORD*)&_ext_start;
680 kickrom[5] = (UWORD*)&_ext_end;
681 kickrom[6] = (UWORD*)~0;
682 kickrom[7] = (UWORD*)~0;
684 /* Look for 'HELP' at address 0 - we're recovering
685 * from a fatal alert
687 if (trap[0] == (APTR)0x48454c50) {
688 for (i = 0; i < 4; i++)
689 oldLastAlert[i] = (LONG)trap[64 + i];
691 DEBUGPUTHEX(("LastAlert Alert", oldLastAlert[0]));
692 DEBUGPUTHEX(("LastAlert Task", oldLastAlert[1]));
693 } else {
694 oldLastAlert[0] = (LONG)-1;
695 oldLastAlert[1] = 0;
696 oldLastAlert[2] = 0;
697 oldLastAlert[2] = 0;
700 /* Clear alert marker */
701 trap[0] = 0;
703 DEBUGPUTHEX(("SS lower", (ULONG)&_ss));
704 DEBUGPUTHEX(("SS upper", (ULONG)&_ss_end - 1));
706 Early_ScreenCode(CODE_RAM_CHECK);
708 /* Mark all the kick memory as 'unprotected' */
709 markKick(KickMemPtr, &KickMemMask);
711 mh = addmemoryregion(membanks[0], membanks[1], KickMemPtr, &KickMemMask, BootS && (ULONG)BootS->magicfastmem == membanks[0]);
712 if (mh == NULL) {
713 DEBUGPUTS(("Can't create initial memory header!\n"));
714 Early_Alert(AT_DeadEnd | AG_NoMemory);
718 * Call the SysBase initialization.
720 Early_ScreenCode(CODE_EXEC_CHECK);
721 if (!krnPrepareExecBase(kickrom, mh, bootmsgptr))
722 Early_Alert(AT_DeadEnd | AG_MakeLib | AO_ExecLib);
724 /* From here on, we can reference SysBase */
725 #undef SysBase
726 DEBUGPUTHEX(("[SysBase at]", (ULONG)SysBase));
728 PrivExecBase(SysBase)->PlatformData.BootMsg = bootmsgptr;
729 SysBase->ThisTask->tc_SPLower = &_ss;
730 SysBase->ThisTask->tc_SPUpper = &_ss_end;
732 if (wasvalid) {
733 SysBase->ColdCapture = ColdCapture;
734 SysBase->CoolCapture = CoolCapture;
735 SysBase->WarmCapture = WarmCapture;
736 SysBase->ChkSum = 0;
737 SysBase->ChkSum = GetSysBaseChkSum(SysBase) ^ 0xffff;
738 SysBase->KickMemPtr = KickMemPtr;
739 SysBase->KickTagPtr = KickTagPtr;
740 SysBase->KickCheckSum = KickCheckSum;
743 SysBase->SysStkUpper = (APTR)&_ss_end;
744 SysBase->SysStkLower = (APTR)&_ss;
746 /* Mark what the last alert was */
747 for (i = 0; i < 4; i++)
748 SysBase->LastAlert[i] = oldLastAlert[i];
750 SysBase->AttnFlags = attnflags;
752 /* Inject code for GetCC, depending on CPU model */
753 if (SysBase->AttnFlags & AFF_68010) {
754 /* move.w %ccr,%d0; rts; nop */
755 FAKE_IT(SysBase, Exec, GetCC, 88, 0x42c0, 0x4e75, 0x4e71);
756 } else {
757 /* move.w %sr,%d0; rts; nop */
758 FAKE_IT(SysBase, Exec, GetCC, 88, 0x40c0, 0x4e75, 0x4e71);
761 #ifdef THESE_ARE_KNOWN_SAFE_ASM_ROUTINES
762 PRESERVE_ALL(SysBase, Exec, Disable, 20);
763 PRESERVE_ALL(SysBase, Exec, Enable, 21);
764 PRESERVE_ALL(SysBase, Exec, Forbid, 22);
765 #endif
766 PRESERVE_ALL(SysBase, Exec, Permit, 23);
767 PRESERVE_ALL(SysBase, Exec, ObtainSemaphore, 94);
768 PRESERVE_ALL(SysBase, Exec, ReleaseSemaphore, 95);
769 PRESERVE_ALL(SysBase, Exec, ObtainSemaphoreShared, 113);
771 /* Functions that need sign extension */
772 EXT_BYTE(SysBase, Exec, SetTaskPri, 50);
773 EXT_BYTE(SysBase, Exec, AllocSignal, 55);
775 /* Only add the 2 standard ROM locations, since
776 * we may get memory at 0x00f00000, or when we
777 * are ReKicked, at the rom-in-ram locations.
779 krnCreateROMHeader("Kickstart ROM", (APTR)0x00f80000, (APTR)0x00ffffff);
780 krnCreateROMHeader("Kickstart ROM", (APTR)0x00e00000, (APTR)0x00e7ffff);
782 /* Add remaining memory regions */
783 for (i = 2; membanks[i + 1]; i += 2) {
784 IPTR addr = membanks[i];
785 ULONG size = membanks[i + 1];
787 DEBUGPUTHEX(("RAM Addr: ", addr));
788 DEBUGPUTHEX(("RAM Size: ", size));
789 mh = addmemoryregion(addr, size, KickMemPtr, &KickMemMask, FALSE);
790 Enqueue(&SysBase->MemList, &mh->mh_Node);
792 /* Adjust MaxLocMem and MaxExtMem as needed */
793 if (addr < 0x00200000)
794 SysBase->MaxLocMem = (size + 0xffff) & 0xffff0000;
795 else if (addr < 0x00d00000)
796 SysBase->MaxExtMem = size ? (APTR)(((0xc00000 + (size + 0xffff)) & 0xffff0000)) : 0;
799 /* Now that we have a valid SysBase,
800 * we can call ColdCapture
802 if (wasvalid)
803 doColdCapture();
805 /* Seal up SysBase's critical variables */
806 SetSysBaseChkSum();
808 /* Set privilege violation trap - we
809 * need this to support the Exec/Supervisor call
811 trap[8] = Exec_Supervisor_Trap;
813 oldmem = AvailMem(MEMF_FAST);
815 /* SysBase is complete, now we can enable instruction caches safely. */
816 CacheControl(CACRF_EnableI, CACRF_EnableI);
817 CacheClearU();
819 /* Ok, let's start the system. We have to
820 * do this in Supervisor context, since some
821 * expansions ROMs (Cyperstorm PPC) expect it.
823 DEBUGPUTS(("[start] InitCode(RTF_SINGLETASK, 0)\n"));
824 InitCode(RTF_SINGLETASK, 0);
826 /* Autoconfig ram expansions are now configured */
828 /* If oldSysBase is not NULL, that means that it
829 * (a) wasn't valid before when we only had MEMF_LOCAL
830 * ram and (b) could possibly be in the MEMF_KICK memory
831 * we just got. Let's check it and find out if we
832 * can use it's capture vectors.
834 if (oldSysBase && IsSysBaseValidNoVersion(oldSysBase)) {
835 /* Save reset proof vectors */
836 SysBase->ColdCapture = oldSysBase->ColdCapture;
837 SysBase->CoolCapture = oldSysBase->CoolCapture;
838 SysBase->WarmCapture = oldSysBase->WarmCapture;
839 /* Save KickData */
840 SysBase->KickMemPtr = oldSysBase->KickMemPtr;
841 SysBase->KickTagPtr = oldSysBase->KickTagPtr;
842 SysBase->KickCheckSum = oldSysBase->KickCheckSum;
843 doColdCapture();
844 /* Re-seal SysBase */
845 SetSysBaseChkSum();
846 wasvalid = TRUE;
849 /* Before we allocate anything else, we need to
850 * lock down the entries in KickMemPtr
852 * If we get a single failure, try again in diag module
854 if (SysBase->KickCheckSum) {
855 if (SysBase->KickCheckSum == (APTR)SumKickData()) {
856 DEBUGPUTS(("KickMem allocation phase 1/2\n"));
857 if (!InitKickMem(&KickMemMask, SysBase)) {
858 /* We'll try again after diag rom module */
859 DEBUGPUTS(("KickMem failed an allocation.\n"));
860 } else {
861 DEBUGPUTS(("All KickMem nodes allocated succesfully.\n"));
863 } else {
864 DEBUGPUTS(("[KickMem] Checksum mismatch\n"));
865 SysBase->KickTagPtr = NULL;
867 PrivExecBase(SysBase)->PlatformData.ep_KickMemPtr = SysBase->KickMemPtr;
868 SysBase->KickMemPtr = NULL;
869 SysBase->KickCheckSum = (APTR)SumKickData();
872 if ((AvailMem(MEMF_FAST) > (oldmem + 256 * 1024)) &&
873 ((TypeOfMem(SysBase) & MEMF_CHIP) ||
874 ((ULONG)SysBase >= 0x00a00000ul && (ULONG)SysBase < 0x01000000ul))) {
875 /* Move execbase to real fast if available now */
876 SysBase = PrepareExecBaseMove(SysBase);
877 AbsExecBase = SysBase;
878 DEBUGPUTHEX(("[Sysbase] now at", (ULONG)SysBase));
881 /* Initialize IRQ subsystem */
882 AmigaIRQInit(SysBase);
884 /* Set privilege violation trap again.
885 * AmigaIRQInit may have blown it away.
887 trap[8] = Exec_Supervisor_Trap;
889 /* Attempt to allocate a real stack, and switch to it. */
890 do {
891 const ULONG size = AROS_STACKSIZE;
892 IPTR *usp;
894 usp = AllocMem(size * sizeof(IPTR), MEMF_PUBLIC);
895 if (usp == NULL) {
896 DEBUGPUTS(("Can't allocate a new stack for Exec... Strange.\n"));
897 Early_Alert(CODE_ALLOC_FAIL);
898 break;
901 /* Leave supervisor mode, switch power led on */
902 asm volatile (
903 "or.b #2,0xbfe001\n"
904 "move.l %0,%%usp\n"
905 "move.w #0,%%sr\n"
906 "move.l %2,%%sp@-\n"
907 "pea 0f\n"
908 "jmp %1@\n"
909 "0:\n"
911 : "a" (&usp[size-3]),
912 "a" (doInitCode),
913 "a" (BootS)
915 } while (0);
917 /* We shouldn't get here */
918 Early_Alert(CODE_EXEC_FAIL);
919 for (;;);