2 Copyright © 1995-2011, The AROS Development Team. All rights reserved.
5 Desc: m68k-amiga bootstrap to exec.
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>
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"
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:
44 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
46 * ext.w %d0 // EXT_BYTE only
48 * ext.l %d0 // EXT_BYTE and EXT_WORD
53 #define EXT_BYTE(lib, libname, funcname, funcid) \
55 void libname##_##funcname##_Wrapper(void) \
57 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
61 /* Insert into the library's jumptable */ \
62 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
64 #define EXT_WORD(lib, libname, funcname, funcid) \
66 void libname##_##funcname##_Wrapper(void) \
68 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
71 /* Insert into the library's jumptable */ \
72 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
75 * Create a register preserving call stub:
77 * movem.l %d0-%d1/%a0-%a1,%sp@-
79 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
81 * movem.l %sp@+,%d0-%d1/%d0-%a1
86 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
88 void libname##_##funcname##_Wrapper(void) \
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" \
94 /* Insert into the library's jumptable */ \
95 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
97 /* Inject arbitrary code into the jump table
98 * Used for GetCC and nano-stubs
100 #define FAKE_IT(lib, libname, funcname, funcid, ...) \
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]; \
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 */
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
);
141 SysBase
->SysStkLower
= ss_stack
;
142 SysBase
->SysStkUpper
= ss_stack
+ SS_STACK_SIZE
;
145 Supervisor((ULONG_FUNC
)SuperstackSwap
);
148 InitCode(RTF_COLDSTART
, 0);
153 extern BYTE _rom_start
;
154 extern BYTE _rom_end
;
155 extern BYTE _ext_start
;
156 extern BYTE _ext_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
)
168 start
= (APTR
)((ULONG
)start
& PAGE_MASK
);
169 length
= (end
- start
+ PAGE_SIZE
- 1) & PAGE_MASK
;
171 length
= end
- start
;
173 tmp
= Early_AllocAbs(mh
, start
, length
);
178 DEBUGPUTS(("<no name>"));
181 DEBUGPUTHEX(("\nStart ", (ULONG
)start
));
182 DEBUGPUTHEX(("End ", (ULONG
)end
- 1));
183 DEBUGPUTHEX(("Size ", length
));
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
)
198 if (startaddr
< 0x00c00000) {
199 krnCreateMemHeader("chip memory", -10,
200 (APTR
)startaddr
, size
,
201 MEMF_CHIP
| MEMF_KICK
| MEMF_PUBLIC
| MEMF_LOCAL
| MEMF_24BITDMA
);
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))
219 if (sysbase
->ChkBase
!= ~(IPTR
)sysbase
)
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
)
238 for (ndx
= 0; ml
; ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
) {
240 for (i
= 0; i
< ml
->ml_NumEntries
; i
++, ndx
++) {
242 (*mask
) |= (1 << ndx
);
247 static void protectKick(struct MemHeader
*mh
, struct MemList
*ml
, ULONG
*mask
)
250 ULONG protectKickBits
= *mask
;
252 DEBUGPUTHEX(("protectKick", (IPTR
)ml
));
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
)))
267 if ((mh
->mh_Lower
> start
) ||
268 (mh
->mh_Upper
< end
))
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
;
282 void InitKickMemDiag(void)
284 struct MemList
*ml
= PrivExecBase(SysBase
)->PlatformData
.ep_KickMemPtr
;
285 DEBUGPUTS(("KickMem allocation phase 2/2\n"));
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
)
307 struct MemList
*ml
= SysBase
->KickMemPtr
;
308 ULONG protectKickBits
= *mask
;
311 DEBUGPUTHEX(("KickMemPtr", (IPTR
)ml
));
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
)))
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"));
333 /* Use the non-mungwalling AllocAbs */
334 if (!InternalAllocAbs(start
, len
, SysBase
))
337 protectKickBits
|= (1 << ndx
);
339 ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
;
342 *mask
= protectKickBits
;
346 #if 0 // debug stuff, do not remove
347 static ULONG
SumKickDataX(struct ExecBase
*sb
)
351 struct ExecBase
*sysbase
= sb
;
353 if (sysbase
->KickTagPtr
) {
354 IPTR
*list
= sysbase
->KickTagPtr
;
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
367 if(*list
& 0x80000000) { list
= (IPTR
*)(*list
& 0x7fffffff); continue; }
369 if(*list
& 0x1) { list
= (IPTR
*)(*list
& ~(IPTR
)0x1); continue; }
376 if (sysbase
->KickMemPtr
) {
377 struct MemList
*ml
= (struct MemList
*)sysbase
->KickMemPtr
;
380 ULONG
*p
= (ULONG
*)ml
;
381 for (i
= 0; i
< sizeof(struct MemList
) / sizeof(ULONG
); i
++)
383 DEBUGPUTHEX(("MEM", (ULONG
)p
));
384 DEBUGPUTHEX(("CHK", chksum
));
385 ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
;
389 if (isdata
&& !chksum
)
395 void doColdCapture(void)
397 APTR ColdCapture
= SysBase
->ColdCapture
;
398 if (ColdCapture
== NULL
)
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"));
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.
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
;
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)));
445 DEBUGPUTS((" ROM Type: ")); DEBUGPUTS((str
)); DEBUGPUTS(("\n"));
446 str
+= strlen(str
) + 1;
447 DEBUGPUTS((" Copyright: ")); DEBUGPUTS((str
));
448 str
+= strlen(str
) + 1;
450 str
+= strlen(str
) + 1;
453 str
+= strlen(str
) + 1;
454 DEBUGPUTS((" ROM Model: ")); DEBUGPUTS((str
));
459 void exec_boot(ULONG
*membanks
, ULONG
*cpupcr
)
462 struct ExecBase
*oldSysBase
= *(APTR
*)4;
464 DEBUGPUTHEX(("X SysBase->KickCheckSum", (ULONG
)oldSysBase
->KickCheckSum
));
465 SumKickDataX(oldSysBase
);
468 struct TagItem bootmsg
[] = {
469 #if AROS_SERIAL_DEBUG
470 { KRN_CmdLine
, (IPTR
)"sysdebug=InitCode" },
471 // { KRN_CmdLine, (IPTR)"sysdebug=InitCode,mmu,mungwall" },
473 { KRN_KernelStackBase
, (IPTR
)&_ss
},
474 { KRN_KernelStackSize
, (IPTR
)(&_ss_end
- &_ss
) },
477 struct TagItem
*bootmsgptr
= bootmsg
;
480 BOOL wasvalid
, arosbootstrapmode
;
482 struct MemHeader
*mh
;
483 LONG oldLastAlert
[4];
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
500 trap
= (APTR
*)(NULL
);
502 /* Set all the exceptions to the Early_Exception
504 for (i
= 2; i
< 64; i
++) {
506 trap
[i
] = Early_Exception
;
509 /* Let the world know we exist
512 DEBUGPUTS(("[reset]\n"));
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
;
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"));
544 DEBUGPUTS(("68EC020"));
545 } else if (attnflags
& AFF_68010
)
546 DEBUGPUTS(("68010"));
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"));
557 } else if (attnflags
& AFF_68882
)
558 DEBUGPUTS(("68882"));
559 else if (attnflags
& AFF_68881
)
560 DEBUGPUTS(("68881"));
565 DEBUGPUTHEX(("PCR", cpupcr
[1]));
569 /* Zap out old SysBase if invalid */
570 arosbootstrapmode
= FALSE
;
571 wasvalid
= IsSysBaseValid(oldSysBase
);
573 DEBUGPUTHEX(("[SysBase] was at", (ULONG
)oldSysBase
));
575 wasvalid
= IsSysBaseValidNoVersion(oldSysBase
);
577 arosbootstrapmode
= TRUE
;
578 DEBUGPUTHEX(("[SysBase] fakebase at", (ULONG
)oldSysBase
));
579 if (oldSysBase
->DebugData
)
580 bootmsgptr
= (struct TagItem
*)oldSysBase
->DebugData
;
583 DEBUGPUTHEX(("[SysBase] invalid at", (ULONG
)oldSysBase
));
587 if (bootmsgptr
[0].ti_Tag
== KRN_CmdLine
) {
588 DEBUGPUTS(("[SysBase] kernel commandline '"));
589 DEBUGPUTS(((CONST_STRPTR
)bootmsgptr
[0].ti_Data
));
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 */
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;
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));
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
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]));
644 oldLastAlert
[0] = (LONG
)-1;
650 /* Clear alert marker */
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
);
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 */
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
;
683 SysBase
->ColdCapture
= ColdCapture
;
684 SysBase
->CoolCapture
= CoolCapture
;
685 SysBase
->WarmCapture
= WarmCapture
;
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);
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);
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
755 /* Seal up SysBase's critical variables */
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
);
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
;
790 SysBase
->KickMemPtr
= oldSysBase
->KickMemPtr
;
791 SysBase
->KickTagPtr
= oldSysBase
->KickTagPtr
;
792 SysBase
->KickCheckSum
= oldSysBase
->KickCheckSum
;
794 /* Re-seal SysBase */
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"));
811 DEBUGPUTS(("All KickMem nodes allocated succesfully.\n"));
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. */
841 const ULONG size
= AROS_STACKSIZE
;
844 usp
= AllocMem(size
* sizeof(IPTR
), MEMF_PUBLIC
);
846 DEBUGPUTS(("Can't allocate a new stack for Exec... Strange.\n"));
847 Early_Alert(CODE_ALLOC_FAIL
);
851 SysBase
->ThisTask
->tc_SPUpper
= &usp
[size
];
852 SysBase
->ThisTask
->tc_SPLower
= usp
;
854 /* Leave supervisor mode, switch power led on */
863 : "a" (&usp
[size
-3]),
868 /* We shouldn't get here */
869 Early_Alert(CODE_EXEC_FAIL
);