2 Copyright © 1995-2018, The AROS Development Team. All rights reserved.
5 Desc: m68k-amiga bootstrap to exec.
10 #include <aros/debug.h>
12 #include <aros/kernel.h>
13 #include <exec/memory.h>
14 #include <exec/resident.h>
15 #include <exec/execbase.h>
16 #include <proto/exec.h>
17 #include <hardware/cpu/memory.h>
21 #include "kernel_romtags.h"
22 #include "kernel_base.h"
24 #define __AROS_KERNEL__
25 #include "exec_intern.h"
27 #include "amiga_hwreg.h"
28 #include "amiga_irq.h"
33 #define SS_STACK_SIZE 0x02000
35 static BOOL
iseven(APTR p
)
37 return (((ULONG
)p
) & 1) == 0;
40 struct BootStruct
*GetBootStruct(struct ExecBase
*eb
)
44 ULONG
*coldcapture
= eb
->ColdCapture
;
45 if (coldcapture
&& iseven(coldcapture
) && coldcapture
[1] == AROS_MAKE_ID('F','A','K','E')) {
46 struct BootStruct
*BootS
= (struct BootStruct
*)(coldcapture
[2]);
47 if (BootS
->magic
== ABS_BOOT_MAGIC
)
54 static void dumpmemory(struct MemHeader
*mh
)
56 struct MemChunk
*mc
= mh
->mh_First
;
58 DEBUGPUTS((mh
->mh_Node
.ln_Name
));
60 DEBUGPUTHEX(("Addr : ", (ULONG
)mh
));
61 DEBUGPUTHEX(("Attrs: ", (ULONG
)mh
->mh_Attributes
));
62 DEBUGPUTHEX(("Lower: ", (ULONG
)mh
->mh_Lower
));
63 DEBUGPUTHEX(("Upper: ", (ULONG
)mh
->mh_Upper
));
64 DEBUGPUTHEX(("Free : ", (ULONG
)mh
->mh_Free
));
65 DEBUGPUTHEX(("First: ", (ULONG
)mc
));
67 DEBUGPUTHEX(("Next : ", (ULONG
)mc
->mc_Next
));
68 DEBUGPUTHEX(("Bytes: ", (ULONG
)mc
->mc_Bytes
));
72 static void dumpallmemory(struct ExecBase
*SysBase
)
74 struct MemHeader
*node
;
75 ForeachNode (&SysBase
->MemList
, node
) {
81 extern const struct Resident Exec_resident
;
82 extern struct ExecBase
*AbsExecBase
;
84 extern void __attribute__((interrupt
)) Exec_Supervisor_Trap (void);
85 extern void __attribute__((interrupt
)) Exec_Supervisor_Trap_00 (void);
87 #define _AS_STRING(x) #x
88 #define AS_STRING(x) _AS_STRING(x)
90 /* Create a sign extending call stub:
92 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
94 * ext.w %d0 // EXT_BYTE only
96 * ext.l %d0 // EXT_BYTE and EXT_WORD
101 #define EXT_BYTE(lib, libname, funcname, funcid) \
103 void libname##_##funcname##_Wrapper(void) \
105 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
109 /* Insert into the library's jumptable */ \
110 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
112 #define EXT_WORD(lib, libname, funcname, funcid) \
114 void libname##_##funcname##_Wrapper(void) \
116 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
119 /* Insert into the library's jumptable */ \
120 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
123 * Create a register preserving call stub:
125 * movem.l %d0-%d1/%a0-%a1,%sp@-
127 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
129 * movem.l %sp@+,%d0-%d1/%d0-%a1
134 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
136 void libname##_##funcname##_Wrapper(void) \
138 "movem.l %d0-%d1/%a0-%a1,%sp@-\n" \
139 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
140 "movem.l %sp@+,%d0-%d1/%a0-%a1\n" \
142 /* Insert into the library's jumptable */ \
143 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
145 /* Inject arbitrary code into the jump table
146 * Used for GetCC and nano-stubs
148 #define FAKE_IT(lib, libname, funcname, funcid, ...) \
150 UWORD *asmcall = (UWORD *)__AROS_GETJUMPVEC(lib, funcid); \
151 const UWORD code[] = { __VA_ARGS__ }; \
152 asmcall[0] = code[0]; \
153 asmcall[1] = code[1]; \
154 asmcall[2] = code[2]; \
156 /* Inject a 'move.w #value,%d0; rts" sequence into the
157 * jump table, to fake an private syscall.
159 #define FAKE_ID(lib, libname, funcname, funcid, value) \
160 FAKE_IT(lib, libname, funcname, funcid, 0x303c, value, 0x4e75)
162 extern void SuperstackSwap(void);
163 /* This calls the register-ABI library
164 * routine Exec/InitCode, for use in NewStackSwap()
166 static LONG
doInitCode(struct BootStruct
*BootS
)
168 /* Attempt to allocate a new supervisor stack */
172 if (BootS
&& BootS
->ss_address
) {
173 ss_stack
= BootS
->ss_address
;
174 ss_stack_size
= BootS
->ss_size
;
175 DEBUGPUTS(("Using AROSBootStrap SS Stack"));
177 ss_stack
= AllocMem(SS_STACK_SIZE
, MEMF_ANY
| MEMF_CLEAR
| MEMF_REVERSE
);
178 if (ss_stack
&& ((ULONG
)ss_stack
& (PAGE_SIZE
- 1))) {
179 /* Normally ss_stack is page aligned because it is first MEMF_REVERSE
180 * allocation. But we must check it because enabled mungwall or expansion
181 * boot rom code can allocate some memory.
183 FreeMem(ss_stack
, SS_STACK_SIZE
);
184 ss_stack
= AllocMem(SS_STACK_SIZE
+ PAGE_SIZE
- 1, MEMF_ANY
| MEMF_CLEAR
| MEMF_REVERSE
);
185 ss_stack
= (APTR
)(((ULONG
)ss_stack
+ PAGE_SIZE
- 1) & PAGE_MASK
);
187 ss_stack_size
= SS_STACK_SIZE
;
189 DEBUGPUTHEX(("SS lower", (ULONG
)ss_stack
));
190 DEBUGPUTHEX(("SS upper", (ULONG
)ss_stack
+ ss_stack_size
- 1));
191 if (ss_stack
== NULL
) {
192 DEBUGPUTS(("PANIC! Can't allocate a new system stack!\n"));
193 Early_Alert(CODE_ALLOC_FAIL
);
196 SysBase
->SysStkLower
= ss_stack
;
197 SysBase
->SysStkUpper
= ss_stack
+ ss_stack_size
;
200 Supervisor((ULONG_FUNC
)SuperstackSwap
);
203 /* Move boot tags from temp supervisor stack. MMU debugging will detect access fault later if not moved. */
204 if (PrivExecBase(SysBase
)->PlatformData
.BootMsg
&& TypeOfMem(PrivExecBase(SysBase
)->PlatformData
.BootMsg
) == 0) {
206 struct TagItem
*bootmsg
, *newbootmsg
;
208 bootmsg
= PrivExecBase(SysBase
)->PlatformData
.BootMsg
;
209 while (bootmsg
[size
].ti_Tag
)
211 newbootmsg
= AllocMem(sizeof(struct TagItem
) * (size
+ 1), MEMF_CLEAR
| MEMF_PUBLIC
);
214 bootmsg
= PrivExecBase(SysBase
)->PlatformData
.BootMsg
;
215 while (bootmsg
[size
].ti_Tag
) {
216 newbootmsg
[size
].ti_Tag
= bootmsg
[size
].ti_Tag
;
217 newbootmsg
[size
].ti_Data
= bootmsg
[size
].ti_Data
;
221 PrivExecBase(SysBase
)->PlatformData
.BootMsg
= newbootmsg
;
224 InitCode(RTF_COLDSTART
, 0);
229 extern BYTE _rom_start
;
230 extern BYTE _rom_end
;
231 extern BYTE _ext_start
;
232 extern BYTE _ext_end
;
236 static BOOL
IsSysBaseValidNoVersion(struct ExecBase
*sysbase
)
238 if (!iseven(sysbase
))
240 if (sysbase
== NULL
|| (((ULONG
)sysbase
) & 0x80000001))
242 if (sysbase
->ChkBase
!= ~(IPTR
)sysbase
)
244 return GetSysBaseChkSum(sysbase
) == 0xffff;
247 #define KICKMEM_MASK 0xc0000000
248 #define KICKMEM_ALLOCATED 0x80000000
249 /* Use following if loaded to memory that is not autoconfig or autodetect */
250 #define KICMMEM_DONOTALLOCATE 0x40000000
252 static void resetKickMem(struct BootStruct
*bs
)
259 /* Mark as unallocated.
260 * This list is guaranteed to be located in memory
261 * that is immediately available after reset.
263 ForeachNode(bs
->mlist
, ml
) {
264 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
265 ml
->ml_ME
[i
].me_Length
&= ~KICKMEM_ALLOCATED
;
269 static void allocKickMem(struct ExecBase
*SysBase
, struct BootStruct
*bs
, struct MemHeader
*mh
, UWORD phase
)
276 bs
= GetBootStruct(SysBase
);
279 DEBUGPUTHEX(("KickMem allocation", phase
));
280 ForeachNode(bs
->mlist
, ml
) {
281 DEBUGPUTHEX(("Type ", ml
->ml_Node
.ln_Type
));
282 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
284 APTR start
= ml
->ml_ME
[i
].me_Addr
;
285 ULONG len
= ml
->ml_ME
[i
].me_Length
;
286 DEBUGPUTHEX(("Address", (ULONG
)start
));
287 DEBUGPUTHEX(("Length ", len
& ~KICKMEM_MASK
));
288 if (len
& KICKMEM_ALLOCATED
) {
289 DEBUGPUTS(("-> already allocated\n"));
292 if (len
& KICMMEM_DONOTALLOCATE
) {
293 DEBUGPUTS(("-> pre-reserved\n"));
297 if (TypeOfMem(start
) == 0) {
299 DEBUGPUTS(("PANIC! Allocation still not in system pool!\n"));
302 DEBUGPUTS(("-> Not in system pool yet\n"));
306 ok
= InternalAllocAbs(start
, len
, SysBase
) != 0 ? 1 : 0;
309 if (start
>= mh
->mh_Lower
&& start
< mh
->mh_Upper
) {
310 ok
= Early_AllocAbs(mh
, start
, len
) != 0 ? 1 : 0;
314 DEBUGPUTS(("-> Allocated\n"));
315 ml
->ml_ME
[i
].me_Length
|= KICKMEM_ALLOCATED
;
316 } else if (ok
== 0) {
317 DEBUGPUTS(("PANIC! Early ROM memory allocation failed!\n"));
318 DEBUGPUTHEX(("LOWER ", (ULONG
)mh
->mh_Lower
));
319 DEBUGPUTHEX(("UPPER ", (ULONG
)mh
->mh_Upper
));
321 } else if (ok
== -1) {
322 DEBUGPUTS(("-> Not yet available\n"));
327 Early_Alert(AT_DeadEnd
| AN_MemoryInsane
);
329 DEBUGPUTS(("KickMem allocation complete\n"));
334 static struct MemHeader
*addmemoryregion(ULONG startaddr
, ULONG size
, struct BootStruct
*bs
, BOOL magicfast
)
339 krnCreateMemHeader("magic fast memory", -8,
340 (APTR
)startaddr
, size
,
341 MEMF_FAST
| MEMF_PUBLIC
| ((startaddr
& 0xff000000) == 0 ? MEMF_24BITDMA
: 0));
342 } else if (startaddr
< 0x00c00000) {
343 krnCreateMemHeader("chip memory", -10,
344 (APTR
)startaddr
, size
,
345 MEMF_CHIP
| MEMF_KICK
| MEMF_PUBLIC
| MEMF_LOCAL
| MEMF_24BITDMA
);
347 krnCreateMemHeader("memory", -5,
348 (APTR
)startaddr
, size
,
349 MEMF_FAST
| MEMF_KICK
| MEMF_PUBLIC
| MEMF_LOCAL
| ((startaddr
& 0xff000000) == 0 ? MEMF_24BITDMA
: 0));
351 DEBUGPUTS(("Added memory header:\n"));
352 DEBUGPUTHEX(("Lower", startaddr
));
353 DEBUGPUTHEX(("Upper", startaddr
+ size
));
354 allocKickMem(NULL
, bs
, (struct MemHeader
*)startaddr
, 0);
355 return (struct MemHeader
*)startaddr
;
358 /* Called after autoconfig. Autoconfig RAM is now available */
359 void InitKickMem(struct ExecBase
*SysBase
)
361 allocKickMem(SysBase
, NULL
, NULL
, 1);
363 /* Called after diag module. Diag ROM enabled RAM is now available */
364 void InitKickMemDiag(struct ExecBase
*SysBase
)
366 allocKickMem(SysBase
, NULL
, NULL
, 2);
369 static void dumpres(struct Resident
**reslist
)
371 #if AROS_SERIAL_DEBUG
373 struct Resident
*RomTag
= *reslist
++;
374 bug("* %p: %4d %02x %3d \"%s\"\n",
384 static ULONG
countres(struct Resident
**reslist
)
388 if (((ULONG
)(*reslist
)) & RESLIST_NEXT
) {
389 reslist
= (struct Resident
**)(((ULONG
)(*reslist
)) & ~RESLIST_NEXT
);
398 static struct Resident
**copyres(struct Resident
**start
, struct Resident
**newreslist
, struct Resident
**oldreslist
)
400 while (*oldreslist
) {
402 if (((ULONG
)(*oldreslist
)) & RESLIST_NEXT
) {
403 oldreslist
= (struct Resident
**)(((ULONG
)(*oldreslist
)) & ~RESLIST_NEXT
);
407 /* Copy only if Resident appears to be accessible */
408 if (r
->rt_MatchWord
== RTC_MATCHWORD
&& r
->rt_MatchTag
== r
) {
409 /* If same Resident is already in list, select higher version/priority */
412 for (i
= 0; start
[i
] != NULL
; i
++) {
413 struct Resident
*r2
= start
[i
];
414 if (!strcmp(r
->rt_Name
, r2
->rt_Name
)) {
415 if (r
->rt_Version
< r2
->rt_Version
||
416 (r
->rt_Version
== r2
->rt_Version
&& r
->rt_Pri
<= r2
->rt_Pri
)) {
435 /* Find remaining residents after autoconfig because part of our ROM image
436 * may have been located in autoconfig RAM that disappeared after reset.
437 * Scan all memory lists, even if memory is not yet allocated, all memory
438 * is mapped at this point but it may not be in system memory list. Yet.
440 static void CollectKickResidents(struct BootStruct
*BootS
, struct ExecBase
*SysBase
)
442 ULONG oldtotal
, newtotal
, total
;
444 struct Resident
**reslist
, **resend
;
446 newtotal
= countres(BootS
->reslist
);
449 oldtotal
= countres(SysBase
->ResModules
);
450 total
= newtotal
+ oldtotal
;
451 DEBUGPUTHEX(("OldRes", oldtotal
));
452 DEBUGPUTHEX(("NewRes", newtotal
));
453 DEBUGPUTHEX(("Total ", total
));
454 reslist
= AllocMem(sizeof(struct Resident
*) * (total
+ 1), MEMF_PUBLIC
);
458 resend
= copyres(reslist
, reslist
, SysBase
->ResModules
);
459 resend
= copyres(reslist
, resend
, BootS
->reslist
);
460 total
= resend
- reslist
;
461 DEBUGPUTHEX(("Total2", total
));
466 for (i
= 0; i
< total
- 1; i
++) {
467 if (reslist
[i
]->rt_Pri
< reslist
[i
+ 1]->rt_Pri
) {
468 struct Resident
*tmp
;
469 tmp
= reslist
[i
+ 1];
470 reslist
[i
+ 1] = reslist
[i
];
477 SysBase
->ResModules
= reslist
;
480 #if 0 // debug stuff, do not remove
481 static ULONG
SumKickDataX(struct ExecBase
*sb
)
485 struct ExecBase
*sysbase
= sb
;
487 if (sysbase
->KickTagPtr
) {
488 IPTR
*list
= sysbase
->KickTagPtr
;
491 chksum
+= (ULONG
)*list
;
492 DEBUGPUTHEX(("LIST", (ULONG
)list
));
493 DEBUGPUTHEX(("LISTP", (ULONG
)*list
));
494 DEBUGPUTHEX(("CHK", chksum
));
495 if(*list
& RESLIST_NEXT
) { list
= (IPTR
*)(*list
& ~RESLIST_NEXT
); continue; }
501 if (sysbase
->KickMemPtr
) {
502 struct MemList
*ml
= (struct MemList
*)sysbase
->KickMemPtr
;
505 ULONG
*p
= (ULONG
*)ml
;
506 for (i
= 0; i
< sizeof(struct MemList
) / sizeof(ULONG
); i
++)
508 DEBUGPUTHEX(("MEM", (ULONG
)p
));
509 DEBUGPUTHEX(("CHK", chksum
));
510 ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
;
514 if (isdata
&& !chksum
)
520 void doColdCapture(void)
522 APTR ColdCapture
= SysBase
->ColdCapture
;
524 if (ColdCapture
== NULL
)
526 if (GetBootStruct(SysBase
)) {
527 /* Fake SysBase installed by AROSBootstrap.
529 * In this case, ColdCapture is the trampoline executed
530 * by the AOS ROM to get into AROS. We need to keep
531 * ColdCapture around in AROS SysBase, but we don't
532 * want to execute it (and cause an infinite loop).
534 DEBUGPUTS(("[ColdCapture] Ignoring AOS->AROS trampoline\n"));
538 SysBase
->ColdCapture
= NULL
;
539 /* ColdCapture calling method is a little
540 * strange. It's in supervisor mode, requires
541 * the return location in A5, and SysBase in A6.
550 : "m" (ColdCapture
), "m" (SysBase
)
551 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
552 "a0", "a1", "a2", "a3", "a4", "a5", "a6");
555 static void RomInfo(IPTR rom
)
557 #if AROS_SERIAL_DEBUG && (DEBUG > 0)
558 APTR ptr
= (APTR
)rom
;
561 if ((*(UWORD
*)(ptr
+ 8) == 0x0000) &&
562 (*(UWORD
*)(ptr
+ 10) == 0xffff) &&
563 (*(UWORD
*)(ptr
+ 12) == *(UWORD
*)(ptr
+ 16)) &&
564 (*(UWORD
*)(ptr
+ 14) == *(UWORD
*)(ptr
+ 18)) &&
565 (*(UWORD
*)(ptr
+ 20) == 0xffff) &&
566 (*(UWORD
*)(ptr
+ 22) == 0xffff)) {
567 DEBUGPUTHEX(("ROM Location", rom
));
568 DEBUGPUTD((" Version", *(UWORD
*)(ptr
+ 12)));
569 DEBUGPUTD((" Revision", *(UWORD
*)(ptr
+ 14)));
571 DEBUGPUTS((" ROM Type: ")); DEBUGPUTS((str
)); DEBUGPUTS(("\n"));
572 str
+= strlen(str
) + 1;
573 DEBUGPUTS((" Copyright: ")); DEBUGPUTS((str
));
574 str
+= strlen(str
) + 1;
576 str
+= strlen(str
) + 1;
579 str
+= strlen(str
) + 1;
580 DEBUGPUTS((" ROM Model: ")); DEBUGPUTS((str
));
586 static UWORD
GetAttnFlags(ULONG
*cpupcr
)
588 /* Convert CPU/FPU flags to AttnFlags */
589 UWORD attnflags
= cpupcr
[0] & 0xffff;
590 if (attnflags
& (AFF_68030
| AFF_68040
| AFF_68060
| AFF_68080
))
591 attnflags
|= AFF_ADDR32
;
592 if (cpupcr
[0] & 0xffff0000) {
593 attnflags
|= AFF_FPU
;
594 if (attnflags
& (AFF_68040
| AFF_68060
))
595 attnflags
|= AFF_FPU40
;
596 // AFF_68881 | AFF_68882 set only if 040/060 math emulation running
597 else if (((cpupcr
[0] >> 16) & 0xff) <= 0x1f)
598 attnflags
|= AFF_68881
;
600 attnflags
|= AFF_68881
| AFF_68882
;
603 #if AROS_SERIAL_DEBUG && (DEBUG > 0)
604 DEBUGPUTS(("CPU: "));
605 if (attnflags
& AFF_68080
)
606 DEBUGPUTS(("Apollo Core 68080"));
607 else if (attnflags
& AFF_68060
)
608 DEBUGPUTS(("68060"));
609 else if (attnflags
& AFF_68040
)
610 DEBUGPUTS(("68040"));
611 else if (attnflags
& AFF_68030
)
612 DEBUGPUTS(("68030"));
613 else if (attnflags
& AFF_68020
) {
614 if (attnflags
& AFF_ADDR32
)
615 DEBUGPUTS(("68020"));
617 DEBUGPUTS(("68EC020"));
618 } else if (attnflags
& AFF_68010
)
619 DEBUGPUTS(("68010"));
621 DEBUGPUTS(("68000"));
622 DEBUGPUTS((" FPU: "));
623 if (attnflags
& AFF_FPU40
) {
624 if (attnflags
& AFF_68060
)
625 DEBUGPUTS(("68060"));
626 else if (attnflags
& AFF_68040
)
627 DEBUGPUTS(("68040"));
630 } else if (attnflags
& AFF_68882
)
631 DEBUGPUTS(("68882"));
632 else if (attnflags
& AFF_68881
)
633 DEBUGPUTS(("68881"));
638 DEBUGPUTHEX(("PCR", cpupcr
[1]));
643 void exec_boot(ULONG
*membanks
, ULONG
*cpupcr
)
645 struct TagItem bootmsg
[] = {
646 /* nomonitors - Until we have working m68k PCI support,
647 * attempting to load the monitor drivers
648 * just wastes a lot of time during boot
650 #if AROS_SERIAL_DEBUG
651 { KRN_CmdLine
, (IPTR
)"nomonitors sysdebug=InitCode" },
652 // { KRN_CmdLine, (IPTR)"nomonitors sysdebug=InitCode,debugmmu,mungwall" },
654 { KRN_CmdLine
, (IPTR
)"nomonitors" },
656 { KRN_KernelStackBase
, (IPTR
)&_ss
},
657 { KRN_KernelStackSize
, (IPTR
)(&_ss_end
- &_ss
) },
660 struct TagItem
*bootmsgptr
= bootmsg
;
663 BOOL wasvalid
, arosbootstrapmode
;
665 struct MemHeader
*mh
;
666 LONG oldLastAlert
[4];
669 APTR ColdCapture
= NULL
, CoolCapture
= NULL
, WarmCapture
= NULL
;
670 APTR KickMemPtr
= NULL
, KickTagPtr
= NULL
, KickCheckSum
= NULL
;
671 struct BootStruct
*BootS
= NULL
;
672 /* We can't use the global 'SysBase' symbol, since
673 * the compiler does not know that PrepareExecBase
674 * may change it out from under us.
676 struct ExecBase
*oldSysBase
= *(APTR
*)4;
677 #define SysBase CANNOT_USE_SYSBASE_SYMBOL_HERE
679 #if AROS_SERIAL_DEBUG
683 trap
= (APTR
*)(NULL
);
685 /* Set all the exceptions to the Early_Exception */
686 for (i
= 2; i
< 64; i
++) {
687 if (i
!= 31) // Do not overwrite NMI
688 trap
[i
] = Early_Exception
;
691 /* Let the world know we exist */
693 DEBUGPUTS(("[reset]\n"));
698 attnflags
= GetAttnFlags(cpupcr
);
700 /* Zap out old SysBase if invalid */
701 arosbootstrapmode
= FALSE
;
702 wasvalid
= IsSysBaseValid(oldSysBase
);
704 DEBUGPUTHEX(("[SysBase] was at", (ULONG
)oldSysBase
));
706 wasvalid
= IsSysBaseValidNoVersion(oldSysBase
);
708 DEBUGPUTHEX(("[SysBase] fakebase at", (ULONG
)oldSysBase
));
709 BootS
= GetBootStruct(oldSysBase
);
711 DEBUGPUTHEX(("BootStruct at", (ULONG
)BootS
));
712 DEBUGPUTHEX(("Original SysBase at", (ULONG
)BootS
->RealBase
));
713 DEBUGPUTHEX(("Secondary SysBase at", (ULONG
)BootS
->RealBase2
));
714 bootmsgptr
= BootS
->kerneltags
;
715 arosbootstrapmode
= TRUE
;
719 DEBUGPUTHEX(("[SysBase] invalid at", (ULONG
)oldSysBase
));
723 if (bootmsgptr
[0].ti_Tag
== KRN_CmdLine
) {
724 DEBUGPUTS(("[SysBase] kernel commandline '"));
725 DEBUGPUTS(((CONST_STRPTR
)bootmsgptr
[0].ti_Data
));
730 /* Save reset proof vectors */
731 ColdCapture
= oldSysBase
->ColdCapture
;
732 CoolCapture
= oldSysBase
->CoolCapture
;
733 WarmCapture
= oldSysBase
->WarmCapture
;
734 KickMemPtr
= oldSysBase
->KickMemPtr
;
735 KickTagPtr
= oldSysBase
->KickTagPtr
;
736 KickCheckSum
= oldSysBase
->KickCheckSum
;
738 /* Mark the oldSysBase as processed */
742 if (BootS
&& BootS
->magicfastmem
) {
743 /* Add early magic fast ram pool
744 * Makes it possible to have execbase and others in fast ram even
745 * if fast ram is non-autocnfig diagrom type.
748 membanks
[0] = (ULONG
)BootS
->magicfastmem
;
749 membanks
[1] = BootS
->magicfastmemsize
;
752 /* Adjust to skip the first 1K/4K bytes of
753 * Chip RAM. It's reserved for the Trap area.
755 for (i
= 0; membanks
[i
+ 2 + 1]; i
+= 2);
756 if (arosbootstrapmode
|| (attnflags
& AFF_68030
))
757 membanks
[i
+ 0] = 0x1000;
759 membanks
[i
+ 0] = 0x400;
760 membanks
[i
+ 1] -= membanks
[i
+ 0];
762 #if AROS_SERIAL_DEBUG && (DEBUG > 0)
763 for (i
= 0; membanks
[i
+ 1]; i
+= 2) {
764 ULONG addr
= membanks
[i
+ 0];
765 ULONG size
= membanks
[i
+ 1];
766 DEBUGPUTHEX(("RAM lower", addr
));
767 DEBUGPUTHEX(("RAM upper", addr
+ size
- 1));
771 /* Look for 'HELP' at address 0 - we're recovering
774 if (trap
[0] == (APTR
)0x48454c50) {
775 for (i
= 0; i
< 4; i
++)
776 oldLastAlert
[i
] = (LONG
)trap
[64 + i
];
778 DEBUGPUTHEX(("LastAlert Alert", oldLastAlert
[0]));
779 DEBUGPUTHEX(("LastAlert Task", oldLastAlert
[1]));
781 oldLastAlert
[0] = (LONG
)-1;
787 /* Clear alert marker */
790 DEBUGPUTHEX(("SS lower", (ULONG
)&_ss
));
791 DEBUGPUTHEX(("SS upper", (ULONG
)&_ss_end
- 1));
793 Early_ScreenCode(CODE_RAM_CHECK
);
795 if (arosbootstrapmode
) {
796 /* Scan only first rom image.
797 * The rest is in BootStruct resident list
799 kickrom
[0] = (UWORD
*)&_rom_start
;
800 kickrom
[1] = (UWORD
*)&_rom_end
;
801 kickrom
[2] = (UWORD
*)0x00f00000;
802 kickrom
[3] = (UWORD
*)0x00f80000;
803 kickrom
[4] = (UWORD
*)~0;
804 kickrom
[5] = (UWORD
*)~0;
805 resetKickMem (BootS
);
807 kickrom
[0] = (UWORD
*)&_rom_start
;
808 kickrom
[1] = (UWORD
*)&_rom_end
;
809 kickrom
[2] = (UWORD
*)0x00f00000;
810 kickrom
[3] = (UWORD
*)0x00f80000;
811 kickrom
[4] = (UWORD
*)&_ext_start
;
812 kickrom
[5] = (UWORD
*)&_ext_end
;
813 kickrom
[6] = (UWORD
*)~0;
814 kickrom
[7] = (UWORD
*)~0;
817 mh
= addmemoryregion(membanks
[0], membanks
[1],
818 BootS
, BootS
&& (ULONG
)BootS
->magicfastmem
== membanks
[0]);
820 DEBUGPUTS(("Can't create initial memory header!\n"));
821 Early_Alert(AT_DeadEnd
| AG_NoMemory
);
824 #if AROS_SERIAL_DEBUG && (DEBUG > 0)
825 for (i
= 0; kickrom
[i
] != (UWORD
*)~0; i
+= 2) {
826 DEBUGPUTHEX(("Resident start", (ULONG
)kickrom
[i
]));
827 DEBUGPUTHEX(("Resident end ", (ULONG
)kickrom
[i
+ 1]));
832 * Call the SysBase initialization.
834 Early_ScreenCode(CODE_EXEC_CHECK
);
835 if (!krnPrepareExecBase(kickrom
, mh
, bootmsgptr
))
836 Early_Alert(AT_DeadEnd
| AG_MakeLib
| AO_ExecLib
);
838 /* From here on, we can reference SysBase */
840 DEBUGPUTHEX(("[SysBase] at", (ULONG
)SysBase
));
842 PrivExecBase(SysBase
)->PlatformData
.BootMsg
= bootmsgptr
;
843 SysBase
->ThisTask
->tc_SPLower
= &_ss
;
844 SysBase
->ThisTask
->tc_SPUpper
= &_ss_end
;
847 SysBase
->ColdCapture
= ColdCapture
;
848 SysBase
->CoolCapture
= CoolCapture
;
849 SysBase
->WarmCapture
= WarmCapture
;
851 SysBase
->ChkSum
= GetSysBaseChkSum(SysBase
) ^ 0xffff;
852 SysBase
->KickMemPtr
= KickMemPtr
;
853 SysBase
->KickTagPtr
= KickTagPtr
;
854 SysBase
->KickCheckSum
= KickCheckSum
;
857 SysBase
->SysStkUpper
= (APTR
)&_ss_end
;
858 SysBase
->SysStkLower
= (APTR
)&_ss
;
860 /* Mark what the last alert was */
861 for (i
= 0; i
< 4; i
++)
862 SysBase
->LastAlert
[i
] = oldLastAlert
[i
];
864 SysBase
->AttnFlags
= attnflags
;
866 /* Inject code for GetCC, depending on CPU model */
867 if (SysBase
->AttnFlags
& AFF_68010
) {
868 /* move.w %ccr,%d0; rts; nop */
869 FAKE_IT(SysBase
, Exec
, GetCC
, 88, 0x42c0, 0x4e75, 0x4e71);
871 /* move.w %sr,%d0; rts; nop */
872 FAKE_IT(SysBase
, Exec
, GetCC
, 88, 0x40c0, 0x4e75, 0x4e71);
875 #ifdef THESE_ARE_KNOWN_SAFE_ASM_ROUTINES
876 PRESERVE_ALL(SysBase
, Exec
, Disable
, 20);
877 PRESERVE_ALL(SysBase
, Exec
, Enable
, 21);
878 PRESERVE_ALL(SysBase
, Exec
, Forbid
, 22);
880 PRESERVE_ALL(SysBase
, Exec
, Permit
, 23);
881 PRESERVE_ALL(SysBase
, Exec
, ObtainSemaphore
, 94);
882 PRESERVE_ALL(SysBase
, Exec
, ReleaseSemaphore
, 95);
883 PRESERVE_ALL(SysBase
, Exec
, ObtainSemaphoreShared
, 113);
885 /* Functions that need sign extension */
886 EXT_BYTE(SysBase
, Exec
, SetTaskPri
, 50);
887 EXT_BYTE(SysBase
, Exec
, AllocSignal
, 55);
889 /* Only add the 2 standard ROM locations, since
890 * we may get memory at 0x00f00000, or when we
891 * are ReKicked, at the rom-in-ram locations.
893 krnCreateROMHeader("Kickstart ROM", (APTR
)0x00f80000, (APTR
)0x00ffffff);
894 krnCreateROMHeader("Kickstart ROM", (APTR
)0x00e00000, (APTR
)0x00e7ffff);
896 /* Add remaining memory regions */
897 for (i
= 2; membanks
[i
+ 1]; i
+= 2) {
898 IPTR addr
= membanks
[i
];
899 ULONG size
= membanks
[i
+ 1];
901 mh
= addmemoryregion(addr
, size
, BootS
, FALSE
);
902 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);
904 /* Adjust MaxLocMem and MaxExtMem as needed */
905 if (addr
< 0x00200000)
906 SysBase
->MaxLocMem
= (size
+ 0xffff) & 0xffff0000;
907 else if (addr
< 0x00d00000)
908 SysBase
->MaxExtMem
= size
? (APTR
)(((0xc00000 + (size
+ 0xffff)) & 0xffff0000)) : 0;
911 /* Now that we have a valid SysBase, we can call ColdCapture */
915 /* Seal up SysBase's critical variables */
918 /* Set privilege violation trap - we
919 * need this to support the Exec/Supervisor call
921 trap
[8] = (SysBase
->AttnFlags
& AFF_68010
) ? Exec_Supervisor_Trap
: Exec_Supervisor_Trap_00
;
923 /* SysBase is complete, now we can enable instruction caches safely. */
924 CacheControl(CACRF_EnableI
, CACRF_EnableI
);
927 oldmem
= AvailMem(MEMF_FAST
);
929 /* Ok, let's start the system. We have to
930 * do this in Supervisor context, since some
931 * expansions ROMs (Cyperstorm PPC) expect it.
933 DEBUGPUTS(("[start] InitCode(RTF_SINGLETASK, 0)\n"));
934 InitCode(RTF_SINGLETASK
, 0);
936 /* Autoconfig ram expansions are now configured */
938 /* Our original AROS SysBase was in autoconfig RAM?
939 * ArosBootStrap needs special handling because AOS autoconfigs all boards
940 * before jumping to ColdCapture if SysBase is in autoconfig RAM
942 * Technically we don't need this but it saves KickTags and KickMems
943 * if someone decides to use them. ArosBootStrap does not anymore need them,
944 * it only needs ColdCapture.
947 if (BootS
->RealBase2
) /* SysBase in autoconfig hack */
948 BootS
->RealBase
= BootS
->RealBase2
;
949 if (BootS
->RealBase
&& iseven(BootS
->RealBase
)) {
950 BootS
->RealBase
->ColdCapture
= SysBase
->ColdCapture
;
951 if (IsSysBaseValid(BootS
->RealBase
)) {
952 oldSysBase
= BootS
->RealBase
;
953 DEBUGPUTHEX(("[SysBase] Found original at", (ULONG
)oldSysBase
));
955 DEBUGPUTHEX(("[SysBase] Found original invalid at", (ULONG
)BootS
->RealBase
));
957 BootS
->RealBase
= NULL
;
958 BootS
->RealBase2
= NULL
;
962 /* If oldSysBase is not NULL, that means that it
963 * (a) wasn't valid before when we only had MEMF_LOCAL
964 * ram and (b) could possibly be in the MEMF_KICK memory
965 * we just got. Let's check it and find out if we
966 * can use it's capture vectors.
968 if (oldSysBase
&& IsSysBaseValidNoVersion(oldSysBase
)) {
969 /* Save reset proof vectors */
970 SysBase
->ColdCapture
= oldSysBase
->ColdCapture
;
971 SysBase
->CoolCapture
= oldSysBase
->CoolCapture
;
972 SysBase
->WarmCapture
= oldSysBase
->WarmCapture
;
974 SysBase
->KickMemPtr
= oldSysBase
->KickMemPtr
;
975 SysBase
->KickTagPtr
= oldSysBase
->KickTagPtr
;
976 SysBase
->KickCheckSum
= oldSysBase
->KickCheckSum
;
978 /* Re-seal SysBase */
983 /* Before we allocate anything else, we need to
984 * lock down the mem entries in BootStruct.
986 * Diag module does final allocation attempt.
988 if (arosbootstrapmode
) {
989 if (SysBase
->KickCheckSum
== (APTR
)SumKickData()) {
990 InitKickMem(SysBase
);
991 CollectKickResidents(BootS
, SysBase
);
993 DEBUGPUTS(("PANIC! KickCheckSum mismatch!\n"));
994 Early_Alert(AT_DeadEnd
| AN_MemoryInsane
);
998 if ((AvailMem(MEMF_FAST
) > (oldmem
+ 256 * 1024)) &&
999 ((TypeOfMem(SysBase
) & MEMF_CHIP
) ||
1000 ((ULONG
)SysBase
>= 0x00a00000ul
&& (ULONG
)SysBase
< 0x01000000ul
))) {
1001 /* Move execbase to real fast if available now */
1002 SysBase
= PrepareExecBaseMove(SysBase
);
1003 AbsExecBase
= SysBase
;
1004 DEBUGPUTHEX(("[Sysbase] now at", (ULONG
)SysBase
));
1007 /* Initialize IRQ subsystem */
1008 AmigaIRQInit(SysBase
);
1010 /* Set privilege violation trap again.
1011 * AmigaIRQInit may have blown it away.
1013 trap
[8] = (SysBase
->AttnFlags
& AFF_68010
) ? Exec_Supervisor_Trap
: Exec_Supervisor_Trap_00
;
1015 /* Attempt to allocate a real stack, and switch to it. */
1017 const ULONG size
= AROS_STACKSIZE
;
1020 usp
= AllocMem(size
* sizeof(IPTR
), MEMF_PUBLIC
);
1022 DEBUGPUTS(("PANIC! Can't allocate a new stack for Exec!\n"));
1023 Early_Alert(CODE_ALLOC_FAIL
);
1026 /* Leave supervisor mode, switch power led on */
1028 "or.b #2,0xbfe001\n"
1031 "move.l %2,%%sp@-\n"
1036 : "a" (&usp
[size
-3]),
1042 /* We shouldn't get here */
1043 DEBUGPUTS(("PANIC! doInitCode() returned!\n"));
1044 Early_Alert(CODE_EXEC_FAIL
);