Support non-MEMF_KICK fast ram boards (Blizzard A1200 accelerators) in arosbootstrap...
[AROS.git] / arch / m68k-amiga / boot / start.c
blob71a27a7362df155bd2f080ec3d1b700d4f6f405e
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 extern const struct Resident Exec_resident;
33 extern struct ExecBase *AbsExecBase;
35 static void protectKick(struct MemHeader *mh, struct MemList *ml, ULONG *mask);
37 extern void __attribute__((interrupt)) Exec_Supervisor_Trap (void);
39 #define _AS_STRING(x) #x
40 #define AS_STRING(x) _AS_STRING(x)
42 /* Create a sign extending call stub:
43 * foo:
44 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
45 * 0x4eb9 .... ....
46 * ext.w %d0 // EXT_BYTE only
47 * 0x4880
48 * ext.l %d0 // EXT_BYTE and EXT_WORD
49 * 0x48c0
50 * rts
51 * 0x4e75
53 #define EXT_BYTE(lib, libname, funcname, funcid) \
54 do { \
55 void libname##_##funcname##_Wrapper(void) \
56 { asm volatile ( \
57 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
58 "ext.w %d0\n" \
59 "ext.l %d0\n" \
60 "rts\n"); } \
61 /* Insert into the library's jumptable */ \
62 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
63 } while (0)
64 #define EXT_WORD(lib, libname, funcname, funcid) \
65 do { \
66 void libname##_##funcname##_Wrapper(void) \
67 { asm volatile ( \
68 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
69 "ext.l %d0\n" \
70 "rts\n"); } \
71 /* Insert into the library's jumptable */ \
72 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
73 } while (0)
75 * Create a register preserving call stub:
76 * foo:
77 * movem.l %d0-%d1/%a0-%a1,%sp@-
78 * 0x48e7 0xc0c0
79 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
80 * 0x4eb9 .... ....
81 * movem.l %sp@+,%d0-%d1/%d0-%a1
82 * 0x4cdf 0x0303
83 * rts
84 * 0x4e75
86 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
87 do { \
88 void libname##_##funcname##_Wrapper(void) \
89 { asm volatile ( \
90 "movem.l %d0-%d1/%a0-%a1,%sp@-\n" \
91 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
92 "movem.l %sp@+,%d0-%d1/%a0-%a1\n" \
93 "rts\n" ); } \
94 /* Insert into the library's jumptable */ \
95 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
96 } while (0)
97 /* Inject arbitrary code into the jump table
98 * Used for GetCC and nano-stubs
100 #define FAKE_IT(lib, libname, funcname, funcid, ...) \
101 do { \
102 UWORD *asmcall = (UWORD *)__AROS_GETJUMPVEC(lib, funcid); \
103 const UWORD code[] = { __VA_ARGS__ }; \
104 asmcall[0] = code[0]; \
105 asmcall[1] = code[1]; \
106 asmcall[2] = code[2]; \
107 } while (0)
108 /* Inject a 'move.w #value,%d0; rts" sequence into the
109 * jump table, to fake an private syscall.
111 #define FAKE_ID(lib, libname, funcname, funcid, value) \
112 FAKE_IT(lib, libname, funcname, funcid, 0x303c, value, 0x4e75)
114 extern void SuperstackSwap(void);
115 /* This calls the register-ABI library
116 * routine Exec/InitCode, for use in NewStackSwap()
118 static LONG doInitCode(void)
120 /* Attempt to allocate a new supervisor stack */
121 do {
122 APTR ss_stack;
124 ss_stack = AllocMem(SS_STACK_SIZE, MEMF_ANY | MEMF_CLEAR | MEMF_REVERSE);
125 if (ss_stack && ((ULONG)ss_stack & (PAGE_SIZE - 1))) {
126 /* Normally ss_stack is page aligned because it is first MEMF_REVERSE
127 * allocation. But we must check it because enabled mungwall or expansion
128 * boot rom code can allocate some memory.
130 FreeMem(ss_stack, SS_STACK_SIZE);
131 ss_stack = AllocMem(SS_STACK_SIZE + PAGE_SIZE - 1, MEMF_ANY | MEMF_CLEAR | MEMF_REVERSE);
132 ss_stack = (APTR)(((ULONG)ss_stack + PAGE_SIZE - 1) & PAGE_MASK);
134 DEBUGPUTHEX(("SS lower", (ULONG)ss_stack));
135 DEBUGPUTHEX(("SS upper", (ULONG)ss_stack + SS_STACK_SIZE - 1));
136 if (ss_stack == NULL) {
137 DEBUGPUTS(("Strange. Can't allocate a new system stack\n"));
138 Early_Alert(CODE_ALLOC_FAIL);
139 break;
141 SysBase->SysStkLower = ss_stack;
142 SysBase->SysStkUpper = ss_stack + SS_STACK_SIZE;
143 SetSysBaseChkSum();
145 Supervisor((ULONG_FUNC)SuperstackSwap);
146 } while(0);
148 InitCode(RTF_COLDSTART, 0);
150 return 0;
153 extern BYTE _rom_start;
154 extern BYTE _rom_end;
155 extern BYTE _ext_start;
156 extern BYTE _ext_end;
157 extern BYTE _ss;
158 extern BYTE _ss_end;
160 /* Protect the 'ROM' if it is actually in RAM.
162 static APTR protectAlloc(struct MemHeader *mh, APTR start, APTR end, const UBYTE *name, BOOL pagealign)
164 APTR tmp;
165 ULONG length;
167 if (pagealign) {
168 start = (APTR)((ULONG)start & PAGE_MASK);
169 length = (end - start + PAGE_SIZE - 1) & PAGE_MASK;
170 } else {
171 length = end - start;
173 tmp = Early_AllocAbs(mh, start, length);
174 DEBUGPUTS(("* "));
175 if (name)
176 DEBUGPUTS((name));
177 else
178 DEBUGPUTS(("<no name>"));
179 if (!tmp)
180 DEBUGPUTS((" !"));
181 DEBUGPUTHEX(("\nStart ", (ULONG)start));
182 DEBUGPUTHEX(("End ", (ULONG)end - 1));
183 DEBUGPUTHEX(("Size ", length));
184 return tmp;
186 static void protectROM(struct MemHeader *mh)
188 DEBUGPUTHEX(("Protect", (IPTR)mh));
189 protectAlloc(mh, &_ss, &_ss_end, "SS", FALSE);
190 DEBUGPUTHEX(("First ", (IPTR)mh->mh_First));
191 DEBUGPUTHEX(("Bytes ", (IPTR)mh->mh_First->mc_Bytes));
194 static struct MemHeader *addmemoryregion(ULONG startaddr, ULONG size, struct MemList *ml, ULONG *mask)
196 if (size < 65536)
197 return NULL;
198 if (startaddr < 0x00c00000) {
199 krnCreateMemHeader("chip memory", -10,
200 (APTR)startaddr, size,
201 MEMF_CHIP | MEMF_KICK | MEMF_PUBLIC | MEMF_LOCAL | MEMF_24BITDMA);
202 } else {
203 krnCreateMemHeader("memory", -5,
204 (APTR)startaddr, size,
205 MEMF_FAST | MEMF_KICK | MEMF_PUBLIC | MEMF_LOCAL | MEMF_24BITDMA);
208 /* Must be done first, in case SS is in it */
209 protectKick((struct MemHeader*)startaddr, ml, mask);
211 protectROM((struct MemHeader*)startaddr);
212 return (struct MemHeader*)startaddr;
215 static BOOL IsSysBaseValidNoVersion(struct ExecBase *sysbase)
217 if (sysbase == NULL || (((ULONG)sysbase) & 0x80000001))
218 return FALSE;
219 if (sysbase->ChkBase != ~(IPTR)sysbase)
220 return FALSE;
221 return GetSysBaseChkSum(sysbase) == 0xffff;
224 /* In the following functions, we use bit 0 of the
225 * MemEntry->me_Addr to indicate whether or not
226 * that MemEntry in the MemList has been 'locked down'
228 * (addr & 1) = unallocated
229 * !(addr & 1) = allocated
232 /* Remove all bit 0 marks
234 /* We support up to 32 KickMemPtr tags in pre-expansion.library RAM */
235 static void markKick(struct MemList *ml, ULONG *mask)
237 int ndx;
238 for (ndx = 0; ml ; ml = (struct MemList*)ml->ml_Node.ln_Succ) {
239 int i;
240 for (i = 0; i < ml->ml_NumEntries; i++, ndx++) {
241 if (ndx < 32)
242 (*mask) |= (1 << ndx);
247 static void protectKick(struct MemHeader *mh, struct MemList *ml, ULONG *mask)
249 int ndx = 0;
250 ULONG protectKickBits = *mask;
252 DEBUGPUTHEX(("protectKick", (IPTR)ml));
254 if (!mh)
255 return;
257 while (ml) {
258 int i;
259 for (i = 0; i < ml->ml_NumEntries; i++, ndx++) {
260 APTR start = (APTR)((IPTR)ml->ml_ME[i].me_Addr & ~1);
261 APTR end = start + ml->ml_ME[i].me_Length;
263 /* Already allocated? */
264 if (ndx >= 32 || !(protectKickBits & (1 << ndx)))
265 continue;
267 if ((mh->mh_Lower > start) ||
268 (mh->mh_Upper < end))
269 continue;
271 if (protectAlloc(mh, start, end, ml->ml_Node.ln_Name, FALSE)) {
272 protectKickBits &= ~(1 << ndx);
275 ml = (struct MemList*)ml->ml_Node.ln_Succ;
278 *mask = protectKickBits;
279 return;
282 void InitKickMemDiag(void)
284 struct MemList *ml = PrivExecBase(SysBase)->PlatformData.ep_KickMemPtr;
285 DEBUGPUTS(("KickMem allocation phase 2/2\n"));
286 while (ml) {
287 int i;
288 for (i = 0; i < ml->ml_NumEntries; i++) {
289 APTR start = ml->ml_ME[i].me_Addr;
290 ULONG len = ml->ml_ME[i].me_Length;
292 DEBUGPUTHEX(("Addr", (IPTR)start));
293 DEBUGPUTHEX(("Len", len));
295 /* Simply attempt to allocate everything again */
296 if (InternalAllocAbs(start, len, SysBase))
297 DEBUGPUTS(("-> Allocated\n"));
300 ml = (struct MemList*)ml->ml_Node.ln_Succ;
304 static BOOL InitKickMem(ULONG *mask, struct ExecBase *SysBase)
306 int ndx = 0;
307 struct MemList *ml = SysBase->KickMemPtr;
308 ULONG protectKickBits = *mask;
309 BOOL ok = TRUE;
311 DEBUGPUTHEX(("KickMemPtr", (IPTR)ml));
313 while (ml) {
314 int i;
315 for (i = 0; i < ml->ml_NumEntries; i++,ndx++) {
316 APTR start = ml->ml_ME[i].me_Addr;
317 ULONG len = ml->ml_ME[i].me_Length;
319 /* Already allocated? */
320 if (ndx < 32 && !(protectKickBits & (1 << ndx)))
321 continue;
323 DEBUGPUTHEX(("Addr", (IPTR)start));
324 DEBUGPUTHEX(("Len", len));
326 if (TypeOfMem(start) == 0) {
327 /* Do not stop if memory is not in memory list yet */
328 DEBUGPUTS(("-> unavailable\n"));
329 ok = FALSE;
330 continue;
333 /* Use the non-mungwalling AllocAbs */
334 if (!InternalAllocAbs(start, len, SysBase))
335 return FALSE;
337 protectKickBits |= (1 << ndx);
339 ml = (struct MemList*)ml->ml_Node.ln_Succ;
342 *mask = protectKickBits;
344 return ok;
346 #if 0 // debug stuff, do not remove
347 static ULONG SumKickDataX(struct ExecBase *sb)
349 ULONG chksum = 0;
350 BOOL isdata = FALSE;
351 struct ExecBase *sysbase = sb;
353 if (sysbase->KickTagPtr) {
354 IPTR *list = sysbase->KickTagPtr;
355 while(*list)
357 chksum += (ULONG)*list;
358 DEBUGPUTHEX(("LIST", (ULONG)list));
359 DEBUGPUTHEX(("LISTP", (ULONG)*list));
360 DEBUGPUTHEX(("CHK", chksum));
361 /* on amiga, if bit 31 is set then this points to another list of
362 * modules rather than pointing to a single module. bit 31 is
363 * inconvenient on architectures where code may be loaded above
364 * 2GB. on these platforms we assume aligned pointers and use bit
365 * 0 instead */
366 #ifdef __mc68000__
367 if(*list & 0x80000000) { list = (IPTR *)(*list & 0x7fffffff); continue; }
368 #else
369 if(*list & 0x1) { list = (IPTR *)(*list & ~(IPTR)0x1); continue; }
370 #endif
371 list++;
372 isdata = TRUE;
376 if (sysbase->KickMemPtr) {
377 struct MemList *ml = (struct MemList*)sysbase->KickMemPtr;
378 while (ml) {
379 UBYTE i;
380 ULONG *p = (ULONG*)ml;
381 for (i = 0; i < sizeof(struct MemList) / sizeof(ULONG); i++)
382 chksum += p[i];
383 DEBUGPUTHEX(("MEM", (ULONG)p));
384 DEBUGPUTHEX(("CHK", chksum));
385 ml = (struct MemList*)ml->ml_Node.ln_Succ;
386 isdata = TRUE;
389 if (isdata && !chksum)
390 chksum--;
391 return chksum;
393 #endif
395 void doColdCapture(void)
397 APTR ColdCapture = SysBase->ColdCapture;
398 if (ColdCapture == NULL)
399 return;
401 if (((ULONG *)ColdCapture)[1] == AROS_MAKE_ID('F','A','K','E')) {
402 /* Fake SysBase installed by AROSBootstrap.
404 * In this case, ColdCapture is the trampoline executed
405 * by the AOS ROM to get into AROS. We need to keep
406 * ColdCapture around in AROS SysBase, but we don't
407 * want to execute it (and cause an infinite loop).
409 DEBUGPUTS(("[ColdCapture] Ignoring AOS->AROS trampoline\n"));
410 return;
413 SysBase->ColdCapture = NULL;
414 /* ColdCapture calling method is a little
415 * strange. It's in supervisor mode, requires
416 * the return location in A5, and SysBase in A6.
418 asm volatile (
419 "move.l %0,%%a0\n"
420 "move.l %1,%%a6\n"
421 "move.l #0f,%%a5\n"
422 "jmp (%%a0)\n"
423 "0:\n"
425 : "m" (ColdCapture), "m" (SysBase)
426 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
427 "a0", "a1", "a2", "a3", "a4", "a5", "a6");
430 static void RomInfo(IPTR rom)
432 APTR ptr = (APTR)rom;
433 CONST_STRPTR str;
435 if ((*(UWORD *)(ptr + 8) == 0x0000) &&
436 (*(UWORD *)(ptr + 10) == 0xffff) &&
437 (*(UWORD *)(ptr + 12) == *(UWORD *)(ptr + 16)) &&
438 (*(UWORD *)(ptr + 14) == *(UWORD *)(ptr + 18)) &&
439 (*(UWORD *)(ptr + 20) == 0xffff) &&
440 (*(UWORD *)(ptr + 22) == 0xffff)) {
441 DEBUGPUTHEX(("ROM Location", rom));
442 DEBUGPUTD((" Version", *(UWORD *)(ptr + 12)));
443 DEBUGPUTD((" Revision", *(UWORD *)(ptr + 14)));
444 str = (ptr + 24);
445 DEBUGPUTS((" ROM Type: ")); DEBUGPUTS((str)); DEBUGPUTS(("\n"));
446 str += strlen(str) + 1;
447 DEBUGPUTS((" Copyright: ")); DEBUGPUTS((str));
448 str += strlen(str) + 1;
449 DEBUGPUTS((str));
450 str += strlen(str) + 1;
451 DEBUGPUTS((str));
452 DEBUGPUTS(("\n"));
453 str += strlen(str) + 1;
454 DEBUGPUTS((" ROM Model: ")); DEBUGPUTS((str));
455 DEBUGPUTS(("\n"));
459 void exec_boot(ULONG *membanks, ULONG *cpupcr)
461 #if 0
462 struct ExecBase *oldSysBase = *(APTR *)4;
463 DebugInit();
464 DEBUGPUTHEX(("X SysBase->KickCheckSum", (ULONG)oldSysBase->KickCheckSum));
465 SumKickDataX(oldSysBase);
466 #endif
468 struct TagItem bootmsg[] = {
469 #if AROS_SERIAL_DEBUG
470 { KRN_CmdLine, (IPTR)"sysdebug=InitCode" },
471 // { KRN_CmdLine, (IPTR)"sysdebug=InitCode,mmu,mungwall" },
472 #endif
473 { KRN_KernelStackBase, (IPTR)&_ss },
474 { KRN_KernelStackSize, (IPTR)(&_ss_end - &_ss) },
475 { TAG_END },
477 struct TagItem *bootmsgptr = bootmsg;
478 volatile APTR *trap;
479 int i;
480 BOOL wasvalid, arosbootstrapmode;
481 UWORD *kickrom[8];
482 struct MemHeader *mh;
483 LONG oldLastAlert[4];
484 ULONG oldmem;
485 UWORD attnflags;
486 APTR ColdCapture = NULL, CoolCapture = NULL, WarmCapture = NULL;
487 ULONG KickMemMask = 0;
488 APTR KickMemPtr = NULL, KickTagPtr = NULL, KickCheckSum = NULL;
489 /* We can't use the global 'SysBase' symbol, since
490 * the compiler does not know that PrepareExecBase
491 * may change it out from under us.
493 struct ExecBase *oldSysBase = *(APTR *)4;
494 #define SysBase CANNOT_USE_SYSBASE_SYMBOL_HERE
496 #if AROS_SERIAL_DEBUG
497 DebugInit();
498 #endif
500 trap = (APTR *)(NULL);
502 /* Set all the exceptions to the Early_Exception
504 for (i = 2; i < 64; i++) {
505 if (i != 31)
506 trap[i] = Early_Exception;
509 /* Let the world know we exist
511 DebugInit();
512 DEBUGPUTS(("[reset]\n"));
513 RomInfo(0xf80000);
514 RomInfo(0xe00000);
515 RomInfo(0xf00000);
517 /* Convert CPU/FPU flags to AttnFlags */
518 attnflags = cpupcr[0] & 0xffff;
519 if (attnflags & (AFF_68030 | AFF_68040 | AFF_68060))
520 attnflags |= AFF_ADDR32;
521 if (cpupcr[0] & 0xffff0000) {
522 attnflags |= AFF_FPU;
523 if (attnflags & (AFF_68040 | AFF_68060))
524 attnflags |= AFF_FPU40;
525 // AFF_68881 | AFF_68882 set only if 040/060 math emulation running
526 else if (((cpupcr[0] >> 16) & 0xff) <= 0x1f)
527 attnflags |= AFF_68881;
528 else
529 attnflags |= AFF_68881 | AFF_68882;
532 #if AROS_SERIAL_DEBUG
533 DEBUGPUTS(("CPU: "));
534 if (attnflags & AFF_68060)
535 DEBUGPUTS(("68060"));
536 else if (attnflags & AFF_68040)
537 DEBUGPUTS(("68040"));
538 else if (attnflags & AFF_68030)
539 DEBUGPUTS(("68030"));
540 else if (attnflags & AFF_68020) {
541 if (attnflags & AFF_ADDR32)
542 DEBUGPUTS(("68020"));
543 else
544 DEBUGPUTS(("68EC020"));
545 } else if (attnflags & AFF_68010)
546 DEBUGPUTS(("68010"));
547 else
548 DEBUGPUTS(("68000"));
549 DEBUGPUTS((" FPU: "));
550 if (attnflags & AFF_FPU40) {
551 if (attnflags & AFF_68060)
552 DEBUGPUTS(("68060"));
553 else if (attnflags & AFF_68040)
554 DEBUGPUTS(("68040"));
555 else
556 DEBUGPUTS(("-"));
557 } else if (attnflags & AFF_68882)
558 DEBUGPUTS(("68882"));
559 else if (attnflags & AFF_68881)
560 DEBUGPUTS(("68881"));
561 else
562 DEBUGPUTS(("-"));
563 DEBUGPUTS(("\n"));
564 if (cpupcr[1])
565 DEBUGPUTHEX(("PCR", cpupcr[1]));
566 #endif
569 /* Zap out old SysBase if invalid */
570 arosbootstrapmode = FALSE;
571 wasvalid = IsSysBaseValid(oldSysBase);
572 if (wasvalid) {
573 DEBUGPUTHEX(("[SysBase] was at", (ULONG)oldSysBase));
574 } else {
575 wasvalid = IsSysBaseValidNoVersion(oldSysBase);
576 if (wasvalid) {
577 arosbootstrapmode = TRUE;
578 DEBUGPUTHEX(("[SysBase] fakebase at", (ULONG)oldSysBase));
579 if (oldSysBase->DebugData)
580 bootmsgptr = (struct TagItem*)oldSysBase->DebugData;
581 wasvalid = TRUE;
582 } else {
583 DEBUGPUTHEX(("[SysBase] invalid at", (ULONG)oldSysBase));
584 wasvalid = FALSE;
587 if (bootmsgptr[0].ti_Tag == KRN_CmdLine) {
588 DEBUGPUTS(("[SysBase] kernel commandline '"));
589 DEBUGPUTS(((CONST_STRPTR)bootmsgptr[0].ti_Data));
590 DEBUGPUTS(("'\n"));
593 if (wasvalid) {
594 /* Save reset proof vectors */
595 ColdCapture = oldSysBase->ColdCapture;
596 CoolCapture = oldSysBase->CoolCapture;
597 WarmCapture = oldSysBase->WarmCapture;
598 KickMemPtr = oldSysBase->KickMemPtr;
599 KickTagPtr = oldSysBase->KickTagPtr;
600 KickCheckSum = oldSysBase->KickCheckSum;
602 /* Mark the oldSysBase as processed */
603 oldSysBase = NULL;
606 /* Adjust to skip the first 1K/4K bytes of
607 * Chip RAM. It's reserved for the Trap area.
609 for (i = 0; membanks[i + 2 + 1]; i += 2);
610 if (arosbootstrapmode || (attnflags & AFF_68030))
611 membanks[i + 0] = 0x1000;
612 else
613 membanks[i + 0] = 0x400;
614 membanks[i + 1] -= membanks[i + 0];
616 #if AROS_SERIAL_DEBUG
617 for (i = 0; membanks[i + 1]; i += 2) {
618 ULONG addr = membanks[i + 0];
619 ULONG size = membanks[i + 1];
620 DEBUGPUTHEX(("RAM lower", addr));
621 DEBUGPUTHEX(("RAM upper", addr + size - 1));
623 #endif
625 kickrom[0] = (UWORD*)&_rom_start;
626 kickrom[1] = (UWORD*)&_rom_end;
627 kickrom[2] = (UWORD*)0x00f00000;
628 kickrom[3] = (UWORD*)0x00f80000;
629 kickrom[4] = (UWORD*)&_ext_start;
630 kickrom[5] = (UWORD*)&_ext_end;
631 kickrom[6] = (UWORD*)~0;
632 kickrom[7] = (UWORD*)~0;
634 /* Look for 'HELP' at address 0 - we're recovering
635 * from a fatal alert
637 if (trap[0] == (APTR)0x48454c50) {
638 for (i = 0; i < 4; i++)
639 oldLastAlert[i] = (LONG)trap[64 + i];
641 DEBUGPUTHEX(("LastAlert Alert", oldLastAlert[0]));
642 DEBUGPUTHEX(("LastAlert Task", oldLastAlert[1]));
643 } else {
644 oldLastAlert[0] = (LONG)-1;
645 oldLastAlert[1] = 0;
646 oldLastAlert[2] = 0;
647 oldLastAlert[2] = 0;
650 /* Clear alert marker */
651 trap[0] = 0;
653 DEBUGPUTHEX(("SS lower", (ULONG)&_ss));
654 DEBUGPUTHEX(("SS upper", (ULONG)&_ss_end - 1));
656 Early_ScreenCode(CODE_RAM_CHECK);
658 /* Mark all the kick memory as 'unprotected' */
659 markKick(KickMemPtr, &KickMemMask);
661 mh = addmemoryregion(membanks[0], membanks[1], KickMemPtr, &KickMemMask);
662 if (mh == NULL) {
663 DEBUGPUTS(("Can't create initial memory header!\n"));
664 Early_Alert(AT_DeadEnd | AG_NoMemory);
668 * Call the SysBase initialization.
670 Early_ScreenCode(CODE_EXEC_CHECK);
671 if (!krnPrepareExecBase(kickrom, mh, bootmsgptr))
672 Early_Alert(AT_DeadEnd | AG_MakeLib | AO_ExecLib);
674 /* From here on, we can reference SysBase */
675 #undef SysBase
676 DEBUGPUTHEX(("[SysBase at]", (ULONG)SysBase));
678 PrivExecBase(SysBase)->PlatformData.BootMsg = bootmsgptr;
679 SysBase->ThisTask->tc_SPLower = &_ss;
680 SysBase->ThisTask->tc_SPUpper = &_ss_end;
682 if (wasvalid) {
683 SysBase->ColdCapture = ColdCapture;
684 SysBase->CoolCapture = CoolCapture;
685 SysBase->WarmCapture = WarmCapture;
686 SysBase->ChkSum = 0;
687 SysBase->ChkSum = GetSysBaseChkSum(SysBase) ^ 0xffff;
688 SysBase->KickMemPtr = KickMemPtr;
689 SysBase->KickTagPtr = KickTagPtr;
690 SysBase->KickCheckSum = KickCheckSum;
693 SysBase->SysStkUpper = (APTR)&_ss_end;
694 SysBase->SysStkLower = (APTR)&_ss;
696 /* Mark what the last alert was */
697 for (i = 0; i < 4; i++)
698 SysBase->LastAlert[i] = oldLastAlert[i];
700 SysBase->AttnFlags = attnflags;
702 /* Inject code for GetCC, depending on CPU model */
703 if (SysBase->AttnFlags & AFF_68010) {
704 /* move.w %ccr,%d0; rts; nop */
705 FAKE_IT(SysBase, Exec, GetCC, 88, 0x42c0, 0x4e75, 0x4e71);
706 } else {
707 /* move.w %sr,%d0; rts; nop */
708 FAKE_IT(SysBase, Exec, GetCC, 88, 0x40c0, 0x4e75, 0x4e71);
711 #ifdef THESE_ARE_KNOWN_SAFE_ASM_ROUTINES
712 PRESERVE_ALL(SysBase, Exec, Disable, 20);
713 PRESERVE_ALL(SysBase, Exec, Enable, 21);
714 PRESERVE_ALL(SysBase, Exec, Forbid, 22);
715 #endif
716 PRESERVE_ALL(SysBase, Exec, Permit, 23);
717 PRESERVE_ALL(SysBase, Exec, ObtainSemaphore, 94);
718 PRESERVE_ALL(SysBase, Exec, ReleaseSemaphore, 95);
719 PRESERVE_ALL(SysBase, Exec, ObtainSemaphoreShared, 113);
721 /* Functions that need sign extension */
722 EXT_BYTE(SysBase, Exec, SetTaskPri, 50);
723 EXT_BYTE(SysBase, Exec, AllocSignal, 55);
725 /* Only add the 2 standard ROM locations, since
726 * we may get memory at 0x00f00000, or when we
727 * are ReKicked, at the rom-in-ram locations.
729 krnCreateROMHeader("Kickstart ROM", (APTR)0x00f80000, (APTR)0x00ffffff);
730 krnCreateROMHeader("Kickstart ROM", (APTR)0x00e00000, (APTR)0x00e7ffff);
732 /* Add remaining memory regions */
733 for (i = 2; membanks[i + 1]; i += 2) {
734 IPTR addr = membanks[i];
735 ULONG size = membanks[i + 1];
737 DEBUGPUTHEX(("RAM Addr: ", addr));
738 DEBUGPUTHEX(("RAM Size: ", size));
739 mh = addmemoryregion(addr, size, KickMemPtr, &KickMemMask);
740 Enqueue(&SysBase->MemList, &mh->mh_Node);
742 /* Adjust MaxLocMem and MaxExtMem as needed */
743 if (addr < 0x00200000)
744 SysBase->MaxLocMem = (size + 0xffff) & 0xffff0000;
745 else if (addr < 0x00d00000)
746 SysBase->MaxExtMem = size ? (APTR)(((0xc00000 + (size + 0xffff)) & 0xffff0000)) : 0;
749 /* Now that we have a valid SysBase,
750 * we can call ColdCapture
752 if (wasvalid)
753 doColdCapture();
755 /* Seal up SysBase's critical variables */
756 SetSysBaseChkSum();
758 /* Set privilege violation trap - we
759 * need this to support the Exec/Supervisor call
761 trap[8] = Exec_Supervisor_Trap;
763 oldmem = AvailMem(MEMF_FAST);
765 /* SysBase is complete, now we can enable instruction caches safely. */
766 CacheControl(CACRF_EnableI, CACRF_EnableI);
767 CacheClearU();
769 /* Ok, let's start the system. We have to
770 * do this in Supervisor context, since some
771 * expansions ROMs (Cyperstorm PPC) expect it.
773 DEBUGPUTS(("[start] InitCode(RTF_SINGLETASK, 0)\n"));
774 InitCode(RTF_SINGLETASK, 0);
776 /* Autoconfig ram expansions are now configured */
778 /* If oldSysBase is not NULL, that means that it
779 * (a) wasn't valid before when we only had MEMF_LOCAL
780 * ram and (b) could possibly be in the MEMF_KICK memory
781 * we just got. Let's check it and find out if we
782 * can use it's capture vectors.
784 if (oldSysBase && IsSysBaseValidNoVersion(oldSysBase)) {
785 /* Save reset proof vectors */
786 SysBase->ColdCapture = oldSysBase->ColdCapture;
787 SysBase->CoolCapture = oldSysBase->CoolCapture;
788 SysBase->WarmCapture = oldSysBase->WarmCapture;
789 /* Save KickData */
790 SysBase->KickMemPtr = oldSysBase->KickMemPtr;
791 SysBase->KickTagPtr = oldSysBase->KickTagPtr;
792 SysBase->KickCheckSum = oldSysBase->KickCheckSum;
793 doColdCapture();
794 /* Re-seal SysBase */
795 SetSysBaseChkSum();
796 wasvalid = TRUE;
799 /* Before we allocate anything else, we need to
800 * lock down the entries in KickMemPtr
802 * If we get a single failure, try again in diag module
804 if (SysBase->KickCheckSum) {
805 if (SysBase->KickCheckSum == (APTR)SumKickData()) {
806 DEBUGPUTS(("KickMem allocation phase 1/2\n"));
807 if (!InitKickMem(&KickMemMask, SysBase)) {
808 /* We'll try again after diag rom module */
809 DEBUGPUTS(("KickMem failed an allocation.\n"));
810 } else {
811 DEBUGPUTS(("All KickMem nodes allocated succesfully.\n"));
813 } else {
814 DEBUGPUTS(("[KickMem] Checksum mismatch\n"));
815 SysBase->KickTagPtr = NULL;
817 PrivExecBase(SysBase)->PlatformData.ep_KickMemPtr = SysBase->KickMemPtr;
818 SysBase->KickMemPtr = NULL;
819 SysBase->KickCheckSum = (APTR)SumKickData();
822 if ((AvailMem(MEMF_FAST) > (oldmem + 256 * 1024)) &&
823 ((TypeOfMem(SysBase) & MEMF_CHIP) ||
824 ((ULONG)SysBase >= 0x00a00000ul && (ULONG)SysBase < 0x01000000ul))) {
825 /* Move execbase to real fast if available now */
826 SysBase = PrepareExecBaseMove(SysBase);
827 AbsExecBase = SysBase;
828 DEBUGPUTHEX(("[Sysbase] now at", (ULONG)SysBase));
831 /* Initialize IRQ subsystem */
832 AmigaIRQInit(SysBase);
834 /* Set privilege violation trap again.
835 * AmigaIRQInit may have blown it away.
837 trap[8] = Exec_Supervisor_Trap;
839 /* Attempt to allocate a real stack, and switch to it. */
840 do {
841 const ULONG size = AROS_STACKSIZE;
842 IPTR *usp;
844 usp = AllocMem(size * sizeof(IPTR), MEMF_PUBLIC);
845 if (usp == NULL) {
846 DEBUGPUTS(("Can't allocate a new stack for Exec... Strange.\n"));
847 Early_Alert(CODE_ALLOC_FAIL);
848 break;
851 SysBase->ThisTask->tc_SPUpper = &usp[size];
852 SysBase->ThisTask->tc_SPLower = usp;
854 /* Leave supervisor mode, switch power led on */
855 asm volatile (
856 "or.b #2,0xbfe001\n"
857 "move.l %0,%%usp\n"
858 "move.w #0,%%sr\n"
859 "pea.l 0f\n"
860 "jmp %1@\n"
861 "0:\n"
863 : "a" (&usp[size-3]),
864 "a" (doInitCode)
866 } while (0);
868 /* We shouldn't get here */
869 Early_Alert(CODE_EXEC_FAIL);
870 for (;;);