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 static BOOL
iseven(APTR p
)
34 return (((ULONG
)p
) & 1) == 0;
37 struct BootStruct
*GetBootStruct(struct ExecBase
*eb
)
41 ULONG
*coldcapture
= eb
->ColdCapture
;
42 if (coldcapture
&& iseven(coldcapture
) && coldcapture
[1] == AROS_MAKE_ID('F','A','K','E')) {
43 struct BootStruct
*BootS
= (struct BootStruct
*)(coldcapture
[2]);
44 if (BootS
->magic
== ABS_BOOT_MAGIC
)
51 static void dumpmemory(struct MemHeader
*mh
)
53 struct MemChunk
*mc
= mh
->mh_First
;
55 DEBUGPUTS((mh
->mh_Node
.ln_Name
));
57 DEBUGPUTHEX(("Addr : ", (ULONG
)mh
));
58 DEBUGPUTHEX(("Attrs: ", (ULONG
)mh
->mh_Attributes
));
59 DEBUGPUTHEX(("Lower: ", (ULONG
)mh
->mh_Lower
));
60 DEBUGPUTHEX(("Upper: ", (ULONG
)mh
->mh_Upper
));
61 DEBUGPUTHEX(("Free : ", (ULONG
)mh
->mh_Free
));
62 DEBUGPUTHEX(("First: ", (ULONG
)mc
));
64 DEBUGPUTHEX(("Next : ", (ULONG
)mc
->mc_Next
));
65 DEBUGPUTHEX(("Bytes: ", (ULONG
)mc
->mc_Bytes
));
69 static void dumpallmemory(struct ExecBase
*SysBase
)
71 struct MemHeader
*node
;
72 ForeachNode (&SysBase
->MemList
, node
) {
78 extern const struct Resident Exec_resident
;
79 extern struct ExecBase
*AbsExecBase
;
81 extern void __attribute__((interrupt
)) Exec_Supervisor_Trap (void);
82 extern void __attribute__((interrupt
)) Exec_Supervisor_Trap_00 (void);
84 #define _AS_STRING(x) #x
85 #define AS_STRING(x) _AS_STRING(x)
87 /* Create a sign extending call stub:
89 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
91 * ext.w %d0 // EXT_BYTE only
93 * ext.l %d0 // EXT_BYTE and EXT_WORD
98 #define EXT_BYTE(lib, libname, funcname, funcid) \
100 void libname##_##funcname##_Wrapper(void) \
102 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
106 /* Insert into the library's jumptable */ \
107 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
109 #define EXT_WORD(lib, libname, funcname, funcid) \
111 void libname##_##funcname##_Wrapper(void) \
113 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
116 /* Insert into the library's jumptable */ \
117 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
120 * Create a register preserving call stub:
122 * movem.l %d0-%d1/%a0-%a1,%sp@-
124 * jsr AROS_SLIB_ENTRY(funcname, libname, funcid)
126 * movem.l %sp@+,%d0-%d1/%d0-%a1
131 #define PRESERVE_ALL(lib, libname, funcname, funcid) \
133 void libname##_##funcname##_Wrapper(void) \
135 "movem.l %d0-%d1/%a0-%a1,%sp@-\n" \
136 "jsr " AS_STRING(AROS_SLIB_ENTRY(funcname, libname, funcid)) "\n" \
137 "movem.l %sp@+,%d0-%d1/%a0-%a1\n" \
139 /* Insert into the library's jumptable */ \
140 __AROS_SETVECADDR(lib, funcid, libname##_##funcname##_Wrapper); \
142 /* Inject arbitrary code into the jump table
143 * Used for GetCC and nano-stubs
145 #define FAKE_IT(lib, libname, funcname, funcid, ...) \
147 UWORD *asmcall = (UWORD *)__AROS_GETJUMPVEC(lib, funcid); \
148 const UWORD code[] = { __VA_ARGS__ }; \
149 asmcall[0] = code[0]; \
150 asmcall[1] = code[1]; \
151 asmcall[2] = code[2]; \
153 /* Inject a 'move.w #value,%d0; rts" sequence into the
154 * jump table, to fake an private syscall.
156 #define FAKE_ID(lib, libname, funcname, funcid, value) \
157 FAKE_IT(lib, libname, funcname, funcid, 0x303c, value, 0x4e75)
159 extern void SuperstackSwap(void);
160 /* This calls the register-ABI library
161 * routine Exec/InitCode, for use in NewStackSwap()
163 static LONG
doInitCode(struct BootStruct
*BootS
)
165 /* Attempt to allocate a new supervisor stack */
169 if (BootS
&& BootS
->ss_address
) {
170 ss_stack
= BootS
->ss_address
;
171 ss_stack_size
= BootS
->ss_size
;
172 DEBUGPUTS(("Using AROSBootStrap SS Stack"));
174 ss_stack
= AllocMem(SS_STACK_SIZE
, MEMF_ANY
| MEMF_CLEAR
| MEMF_REVERSE
);
175 if (ss_stack
&& ((ULONG
)ss_stack
& (PAGE_SIZE
- 1))) {
176 /* Normally ss_stack is page aligned because it is first MEMF_REVERSE
177 * allocation. But we must check it because enabled mungwall or expansion
178 * boot rom code can allocate some memory.
180 FreeMem(ss_stack
, SS_STACK_SIZE
);
181 ss_stack
= AllocMem(SS_STACK_SIZE
+ PAGE_SIZE
- 1, MEMF_ANY
| MEMF_CLEAR
| MEMF_REVERSE
);
182 ss_stack
= (APTR
)(((ULONG
)ss_stack
+ PAGE_SIZE
- 1) & PAGE_MASK
);
184 ss_stack_size
= SS_STACK_SIZE
;
186 DEBUGPUTHEX(("SS lower", (ULONG
)ss_stack
));
187 DEBUGPUTHEX(("SS upper", (ULONG
)ss_stack
+ ss_stack_size
- 1));
188 if (ss_stack
== NULL
) {
189 DEBUGPUTS(("PANIC! Can't allocate a new system stack!\n"));
190 Early_Alert(CODE_ALLOC_FAIL
);
193 SysBase
->SysStkLower
= ss_stack
;
194 SysBase
->SysStkUpper
= ss_stack
+ ss_stack_size
;
197 Supervisor((ULONG_FUNC
)SuperstackSwap
);
200 /* Move boot tags from temp supervisor stack. MMU debugging will detect access fault later if not moved. */
201 if (PrivExecBase(SysBase
)->PlatformData
.BootMsg
&& TypeOfMem(PrivExecBase(SysBase
)->PlatformData
.BootMsg
) == 0) {
203 struct TagItem
*bootmsg
, *newbootmsg
;
205 bootmsg
= PrivExecBase(SysBase
)->PlatformData
.BootMsg
;
206 while (bootmsg
[size
].ti_Tag
)
208 newbootmsg
= AllocMem(sizeof(struct TagItem
) * (size
+ 1), MEMF_CLEAR
| MEMF_PUBLIC
);
211 bootmsg
= PrivExecBase(SysBase
)->PlatformData
.BootMsg
;
212 while (bootmsg
[size
].ti_Tag
) {
213 newbootmsg
[size
].ti_Tag
= bootmsg
[size
].ti_Tag
;
214 newbootmsg
[size
].ti_Data
= bootmsg
[size
].ti_Data
;
218 PrivExecBase(SysBase
)->PlatformData
.BootMsg
= newbootmsg
;
221 InitCode(RTF_COLDSTART
, 0);
226 extern BYTE _rom_start
;
227 extern BYTE _rom_end
;
228 extern BYTE _ext_start
;
229 extern BYTE _ext_end
;
233 static BOOL
IsSysBaseValidNoVersion(struct ExecBase
*sysbase
)
235 if (!iseven(sysbase
))
237 if (sysbase
== NULL
|| (((ULONG
)sysbase
) & 0x80000001))
239 if (sysbase
->ChkBase
!= ~(IPTR
)sysbase
)
241 return GetSysBaseChkSum(sysbase
) == 0xffff;
244 #define KICKMEM_MASK 0xc0000000
245 #define KICKMEM_ALLOCATED 0x80000000
246 /* Use following if loaded to memory that is not autoconfig or autodetect */
247 #define KICMMEM_DONOTALLOCATE 0x40000000
249 static void resetKickMem(struct BootStruct
*bs
)
256 /* Mark as unallocated.
257 * This list is guaranteed to be located in memory
258 * that is immediately available after reset.
260 ForeachNode(bs
->mlist
, ml
) {
261 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
262 ml
->ml_ME
[i
].me_Length
&= ~KICKMEM_ALLOCATED
;
266 static void allocKickMem(struct ExecBase
*SysBase
, struct BootStruct
*bs
, struct MemHeader
*mh
, UWORD phase
)
273 bs
= GetBootStruct(SysBase
);
276 DEBUGPUTHEX(("KickMem allocation", phase
));
277 ForeachNode(bs
->mlist
, ml
) {
278 DEBUGPUTHEX(("Type ", ml
->ml_Node
.ln_Type
));
279 for(i
= 0; i
< ml
->ml_NumEntries
; i
++) {
281 APTR start
= ml
->ml_ME
[i
].me_Addr
;
282 ULONG len
= ml
->ml_ME
[i
].me_Length
;
283 DEBUGPUTHEX(("Address", (ULONG
)start
));
284 DEBUGPUTHEX(("Length ", len
& ~KICKMEM_MASK
));
285 if (len
& KICKMEM_ALLOCATED
) {
286 DEBUGPUTS(("-> already allocated\n"));
289 if (len
& KICMMEM_DONOTALLOCATE
) {
290 DEBUGPUTS(("-> pre-reserved\n"));
294 if (TypeOfMem(start
) == 0) {
296 DEBUGPUTS(("PANIC! Allocation still not in system pool!\n"));
299 DEBUGPUTS(("-> Not in system pool yet\n"));
303 ok
= InternalAllocAbs(start
, len
, SysBase
) != 0 ? 1 : 0;
306 if (start
>= mh
->mh_Lower
&& start
< mh
->mh_Upper
) {
307 ok
= Early_AllocAbs(mh
, start
, len
) != 0 ? 1 : 0;
311 DEBUGPUTS(("-> Allocated\n"));
312 ml
->ml_ME
[i
].me_Length
|= KICKMEM_ALLOCATED
;
313 } else if (ok
== 0) {
314 DEBUGPUTS(("PANIC! Early ROM memory allocation failed!\n"));
315 DEBUGPUTHEX(("LOWER ", (ULONG
)mh
->mh_Lower
));
316 DEBUGPUTHEX(("UPPER ", (ULONG
)mh
->mh_Upper
));
318 } else if (ok
== -1) {
319 DEBUGPUTS(("-> Not yet available\n"));
324 Early_Alert(AT_DeadEnd
| AN_MemoryInsane
);
326 DEBUGPUTS(("KickMem allocation complete\n"));
331 static struct MemHeader
*addmemoryregion(ULONG startaddr
, ULONG size
, struct BootStruct
*bs
, BOOL magicfast
)
336 krnCreateMemHeader("magic fast memory", -8,
337 (APTR
)startaddr
, size
,
338 MEMF_FAST
| MEMF_PUBLIC
| ((startaddr
& 0xff000000) == 0 ? MEMF_24BITDMA
: 0));
339 } else if (startaddr
< 0x00c00000) {
340 krnCreateMemHeader("chip memory", -10,
341 (APTR
)startaddr
, size
,
342 MEMF_CHIP
| MEMF_KICK
| MEMF_PUBLIC
| MEMF_LOCAL
| MEMF_24BITDMA
);
344 krnCreateMemHeader("memory", -5,
345 (APTR
)startaddr
, size
,
346 MEMF_FAST
| MEMF_KICK
| MEMF_PUBLIC
| MEMF_LOCAL
| ((startaddr
& 0xff000000) == 0 ? MEMF_24BITDMA
: 0));
348 DEBUGPUTS(("Added memory header:\n"));
349 DEBUGPUTHEX(("Lower", startaddr
));
350 DEBUGPUTHEX(("Upper", startaddr
+ size
));
351 allocKickMem(NULL
, bs
, (struct MemHeader
*)startaddr
, 0);
352 return (struct MemHeader
*)startaddr
;
355 /* Called after autoconfig. Autoconfig RAM is now available */
356 void InitKickMem(struct ExecBase
*SysBase
)
358 allocKickMem(SysBase
, NULL
, NULL
, 1);
360 /* Called after diag module. Diag ROM enabled RAM is now available */
361 void InitKickMemDiag(struct ExecBase
*SysBase
)
363 allocKickMem(SysBase
, NULL
, NULL
, 2);
366 static void dumpres(struct Resident
**reslist
)
368 #if AROS_SERIAL_DEBUG
370 struct Resident
*RomTag
= *reslist
++;
371 bug("* %p: %4d %02x %3d \"%s\"\n",
381 static ULONG
countres(struct Resident
**reslist
)
385 if (((ULONG
)(*reslist
)) & RESLIST_NEXT
) {
386 reslist
= (struct Resident
**)(((ULONG
)(*reslist
)) & ~RESLIST_NEXT
);
395 static struct Resident
**copyres(struct Resident
**start
, struct Resident
**newreslist
, struct Resident
**oldreslist
)
397 while (*oldreslist
) {
399 if (((ULONG
)(*oldreslist
)) & RESLIST_NEXT
) {
400 oldreslist
= (struct Resident
**)(((ULONG
)(*oldreslist
)) & ~RESLIST_NEXT
);
404 /* Copy only if Resident appears to be accessible */
405 if (r
->rt_MatchWord
== RTC_MATCHWORD
&& r
->rt_MatchTag
== r
) {
406 /* If same Resident is already in list, select higher version/priority */
409 for (i
= 0; start
[i
] != NULL
; i
++) {
410 struct Resident
*r2
= start
[i
];
411 if (!strcmp(r
->rt_Name
, r2
->rt_Name
)) {
412 if (r
->rt_Version
< r2
->rt_Version
||
413 (r
->rt_Version
== r2
->rt_Version
&& r
->rt_Pri
<= r2
->rt_Pri
)) {
432 /* Find remaining residents after autoconfig because part of our ROM image
433 * may have been located in autoconfig RAM that disappeared after reset.
434 * Scan all memory lists, even if memory is not yet allocated, all memory
435 * is mapped at this point but it may not be in system memory list. Yet.
437 static void CollectKickResidents(struct BootStruct
*BootS
, struct ExecBase
*SysBase
)
439 ULONG oldtotal
, newtotal
, total
;
441 struct Resident
**reslist
, **resend
;
443 newtotal
= countres(BootS
->reslist
);
446 oldtotal
= countres(SysBase
->ResModules
);
447 total
= newtotal
+ oldtotal
;
448 DEBUGPUTHEX(("OldRes", oldtotal
));
449 DEBUGPUTHEX(("NewRes", newtotal
));
450 DEBUGPUTHEX(("Total ", total
));
451 reslist
= AllocMem(sizeof(struct Resident
*) * (total
+ 1), MEMF_PUBLIC
);
455 resend
= copyres(reslist
, reslist
, SysBase
->ResModules
);
456 resend
= copyres(reslist
, resend
, BootS
->reslist
);
457 total
= resend
- reslist
;
458 DEBUGPUTHEX(("Total2", total
));
463 for (i
= 0; i
< total
- 1; i
++) {
464 if (reslist
[i
]->rt_Pri
< reslist
[i
+ 1]->rt_Pri
) {
465 struct Resident
*tmp
;
466 tmp
= reslist
[i
+ 1];
467 reslist
[i
+ 1] = reslist
[i
];
474 SysBase
->ResModules
= reslist
;
477 #if 0 // debug stuff, do not remove
478 static ULONG
SumKickDataX(struct ExecBase
*sb
)
482 struct ExecBase
*sysbase
= sb
;
484 if (sysbase
->KickTagPtr
) {
485 IPTR
*list
= sysbase
->KickTagPtr
;
488 chksum
+= (ULONG
)*list
;
489 DEBUGPUTHEX(("LIST", (ULONG
)list
));
490 DEBUGPUTHEX(("LISTP", (ULONG
)*list
));
491 DEBUGPUTHEX(("CHK", chksum
));
492 if(*list
& RESLIST_NEXT
) { list
= (IPTR
*)(*list
& ~RESLIST_NEXT
); continue; }
498 if (sysbase
->KickMemPtr
) {
499 struct MemList
*ml
= (struct MemList
*)sysbase
->KickMemPtr
;
502 ULONG
*p
= (ULONG
*)ml
;
503 for (i
= 0; i
< sizeof(struct MemList
) / sizeof(ULONG
); i
++)
505 DEBUGPUTHEX(("MEM", (ULONG
)p
));
506 DEBUGPUTHEX(("CHK", chksum
));
507 ml
= (struct MemList
*)ml
->ml_Node
.ln_Succ
;
511 if (isdata
&& !chksum
)
517 void doColdCapture(void)
519 APTR ColdCapture
= SysBase
->ColdCapture
;
521 if (ColdCapture
== NULL
)
523 if (GetBootStruct(SysBase
)) {
524 /* Fake SysBase installed by AROSBootstrap.
526 * In this case, ColdCapture is the trampoline executed
527 * by the AOS ROM to get into AROS. We need to keep
528 * ColdCapture around in AROS SysBase, but we don't
529 * want to execute it (and cause an infinite loop).
531 DEBUGPUTS(("[ColdCapture] Ignoring AOS->AROS trampoline\n"));
535 SysBase
->ColdCapture
= NULL
;
536 /* ColdCapture calling method is a little
537 * strange. It's in supervisor mode, requires
538 * the return location in A5, and SysBase in A6.
547 : "m" (ColdCapture
), "m" (SysBase
)
548 : "d0", "d1", "d2", "d3", "d4", "d5", "d6", "d7",
549 "a0", "a1", "a2", "a3", "a4", "a5", "a6");
552 static void RomInfo(IPTR rom
)
554 #if AROS_SERIAL_DEBUG
555 APTR ptr
= (APTR
)rom
;
558 if ((*(UWORD
*)(ptr
+ 8) == 0x0000) &&
559 (*(UWORD
*)(ptr
+ 10) == 0xffff) &&
560 (*(UWORD
*)(ptr
+ 12) == *(UWORD
*)(ptr
+ 16)) &&
561 (*(UWORD
*)(ptr
+ 14) == *(UWORD
*)(ptr
+ 18)) &&
562 (*(UWORD
*)(ptr
+ 20) == 0xffff) &&
563 (*(UWORD
*)(ptr
+ 22) == 0xffff)) {
564 DEBUGPUTHEX(("ROM Location", rom
));
565 DEBUGPUTD((" Version", *(UWORD
*)(ptr
+ 12)));
566 DEBUGPUTD((" Revision", *(UWORD
*)(ptr
+ 14)));
568 DEBUGPUTS((" ROM Type: ")); DEBUGPUTS((str
)); DEBUGPUTS(("\n"));
569 str
+= strlen(str
) + 1;
570 DEBUGPUTS((" Copyright: ")); DEBUGPUTS((str
));
571 str
+= strlen(str
) + 1;
573 str
+= strlen(str
) + 1;
576 str
+= strlen(str
) + 1;
577 DEBUGPUTS((" ROM Model: ")); DEBUGPUTS((str
));
583 static UWORD
GetAttnFlags(ULONG
*cpupcr
)
585 /* Convert CPU/FPU flags to AttnFlags */
586 UWORD attnflags
= cpupcr
[0] & 0xffff;
587 if (attnflags
& (AFF_68030
| AFF_68040
| AFF_68060
))
588 attnflags
|= AFF_ADDR32
;
589 if (cpupcr
[0] & 0xffff0000) {
590 attnflags
|= AFF_FPU
;
591 if (attnflags
& (AFF_68040
| AFF_68060
))
592 attnflags
|= AFF_FPU40
;
593 // AFF_68881 | AFF_68882 set only if 040/060 math emulation running
594 else if (((cpupcr
[0] >> 16) & 0xff) <= 0x1f)
595 attnflags
|= AFF_68881
;
597 attnflags
|= AFF_68881
| AFF_68882
;
600 #if AROS_SERIAL_DEBUG
601 DEBUGPUTS(("CPU: "));
602 if (attnflags
& AFF_68060
)
603 DEBUGPUTS(("68060"));
604 else if (attnflags
& AFF_68040
)
605 DEBUGPUTS(("68040"));
606 else if (attnflags
& AFF_68030
)
607 DEBUGPUTS(("68030"));
608 else if (attnflags
& AFF_68020
) {
609 if (attnflags
& AFF_ADDR32
)
610 DEBUGPUTS(("68020"));
612 DEBUGPUTS(("68EC020"));
613 } else if (attnflags
& AFF_68010
)
614 DEBUGPUTS(("68010"));
616 DEBUGPUTS(("68000"));
617 DEBUGPUTS((" FPU: "));
618 if (attnflags
& AFF_FPU40
) {
619 if (attnflags
& AFF_68060
)
620 DEBUGPUTS(("68060"));
621 else if (attnflags
& AFF_68040
)
622 DEBUGPUTS(("68040"));
625 } else if (attnflags
& AFF_68882
)
626 DEBUGPUTS(("68882"));
627 else if (attnflags
& AFF_68881
)
628 DEBUGPUTS(("68881"));
633 DEBUGPUTHEX(("PCR", cpupcr
[1]));
638 void exec_boot(ULONG
*membanks
, ULONG
*cpupcr
)
640 struct TagItem bootmsg
[] = {
641 /* nomonitors - Until we have working m68k PCI support,
642 * attempting to load the monitor drivers
643 * just wastes a lot of time during boot
645 #if AROS_SERIAL_DEBUG
646 { KRN_CmdLine
, (IPTR
)"nomonitors sysdebug=InitCode" },
647 // { KRN_CmdLine, (IPTR)"nomonitors sysdebug=InitCode,debugmmu,mungwall" },
649 { KRN_CmdLine
, (IPTR
)"nomonitors" },
651 { KRN_KernelStackBase
, (IPTR
)&_ss
},
652 { KRN_KernelStackSize
, (IPTR
)(&_ss_end
- &_ss
) },
655 struct TagItem
*bootmsgptr
= bootmsg
;
658 BOOL wasvalid
, arosbootstrapmode
;
660 struct MemHeader
*mh
;
661 LONG oldLastAlert
[4];
664 APTR ColdCapture
= NULL
, CoolCapture
= NULL
, WarmCapture
= NULL
;
665 APTR KickMemPtr
= NULL
, KickTagPtr
= NULL
, KickCheckSum
= NULL
;
666 struct BootStruct
*BootS
= NULL
;
667 /* We can't use the global 'SysBase' symbol, since
668 * the compiler does not know that PrepareExecBase
669 * may change it out from under us.
671 struct ExecBase
*oldSysBase
= *(APTR
*)4;
672 #define SysBase CANNOT_USE_SYSBASE_SYMBOL_HERE
674 #if AROS_SERIAL_DEBUG
678 trap
= (APTR
*)(NULL
);
680 /* Set all the exceptions to the Early_Exception */
681 for (i
= 2; i
< 64; i
++) {
682 if (i
!= 31) // Do not overwrite NMI
683 trap
[i
] = Early_Exception
;
686 /* Let the world know we exist */
688 DEBUGPUTS(("[reset]\n"));
693 attnflags
= GetAttnFlags(cpupcr
);
695 /* Zap out old SysBase if invalid */
696 arosbootstrapmode
= FALSE
;
697 wasvalid
= IsSysBaseValid(oldSysBase
);
699 DEBUGPUTHEX(("[SysBase] was at", (ULONG
)oldSysBase
));
701 wasvalid
= IsSysBaseValidNoVersion(oldSysBase
);
703 DEBUGPUTHEX(("[SysBase] fakebase at", (ULONG
)oldSysBase
));
704 BootS
= GetBootStruct(oldSysBase
);
706 DEBUGPUTHEX(("BootStruct at", (ULONG
)BootS
));
707 DEBUGPUTHEX(("Original SysBase at", (ULONG
)BootS
->RealBase
));
708 DEBUGPUTHEX(("Secondary SysBase at", (ULONG
)BootS
->RealBase2
));
709 bootmsgptr
= BootS
->kerneltags
;
710 arosbootstrapmode
= TRUE
;
714 DEBUGPUTHEX(("[SysBase] invalid at", (ULONG
)oldSysBase
));
718 if (bootmsgptr
[0].ti_Tag
== KRN_CmdLine
) {
719 DEBUGPUTS(("[SysBase] kernel commandline '"));
720 DEBUGPUTS(((CONST_STRPTR
)bootmsgptr
[0].ti_Data
));
725 /* Save reset proof vectors */
726 ColdCapture
= oldSysBase
->ColdCapture
;
727 CoolCapture
= oldSysBase
->CoolCapture
;
728 WarmCapture
= oldSysBase
->WarmCapture
;
729 KickMemPtr
= oldSysBase
->KickMemPtr
;
730 KickTagPtr
= oldSysBase
->KickTagPtr
;
731 KickCheckSum
= oldSysBase
->KickCheckSum
;
733 /* Mark the oldSysBase as processed */
737 if (BootS
&& BootS
->magicfastmem
) {
738 /* Add early magic fast ram pool
739 * Makes it possible to have execbase and others in fast ram even
740 * if fast ram is non-autocnfig diagrom type.
743 membanks
[0] = (ULONG
)BootS
->magicfastmem
;
744 membanks
[1] = BootS
->magicfastmemsize
;
747 /* Adjust to skip the first 1K/4K bytes of
748 * Chip RAM. It's reserved for the Trap area.
750 for (i
= 0; membanks
[i
+ 2 + 1]; i
+= 2);
751 if (arosbootstrapmode
|| (attnflags
& AFF_68030
))
752 membanks
[i
+ 0] = 0x1000;
754 membanks
[i
+ 0] = 0x400;
755 membanks
[i
+ 1] -= membanks
[i
+ 0];
757 #if AROS_SERIAL_DEBUG
758 for (i
= 0; membanks
[i
+ 1]; i
+= 2) {
759 ULONG addr
= membanks
[i
+ 0];
760 ULONG size
= membanks
[i
+ 1];
761 DEBUGPUTHEX(("RAM lower", addr
));
762 DEBUGPUTHEX(("RAM upper", addr
+ size
- 1));
766 /* Look for 'HELP' at address 0 - we're recovering
769 if (trap
[0] == (APTR
)0x48454c50) {
770 for (i
= 0; i
< 4; i
++)
771 oldLastAlert
[i
] = (LONG
)trap
[64 + i
];
773 DEBUGPUTHEX(("LastAlert Alert", oldLastAlert
[0]));
774 DEBUGPUTHEX(("LastAlert Task", oldLastAlert
[1]));
776 oldLastAlert
[0] = (LONG
)-1;
782 /* Clear alert marker */
785 DEBUGPUTHEX(("SS lower", (ULONG
)&_ss
));
786 DEBUGPUTHEX(("SS upper", (ULONG
)&_ss_end
- 1));
788 Early_ScreenCode(CODE_RAM_CHECK
);
790 if (arosbootstrapmode
) {
791 /* Scan only first rom image.
792 * The rest is in BootStruct resident list
794 kickrom
[0] = (UWORD
*)&_rom_start
;
795 kickrom
[1] = (UWORD
*)&_rom_end
;
796 kickrom
[2] = (UWORD
*)0x00f00000;
797 kickrom
[3] = (UWORD
*)0x00f80000;
798 kickrom
[4] = (UWORD
*)~0;
799 kickrom
[5] = (UWORD
*)~0;
800 resetKickMem (BootS
);
802 kickrom
[0] = (UWORD
*)&_rom_start
;
803 kickrom
[1] = (UWORD
*)&_rom_end
;
804 kickrom
[2] = (UWORD
*)0x00f00000;
805 kickrom
[3] = (UWORD
*)0x00f80000;
806 kickrom
[4] = (UWORD
*)&_ext_start
;
807 kickrom
[5] = (UWORD
*)&_ext_end
;
808 kickrom
[6] = (UWORD
*)~0;
809 kickrom
[7] = (UWORD
*)~0;
812 mh
= addmemoryregion(membanks
[0], membanks
[1],
813 BootS
, BootS
&& (ULONG
)BootS
->magicfastmem
== membanks
[0]);
815 DEBUGPUTS(("Can't create initial memory header!\n"));
816 Early_Alert(AT_DeadEnd
| AG_NoMemory
);
819 #if AROS_SERIAL_DEBUG
820 for (i
= 0; kickrom
[i
] != (UWORD
*)~0; i
+= 2) {
821 DEBUGPUTHEX(("Resident start", (ULONG
)kickrom
[i
]));
822 DEBUGPUTHEX(("Resident end ", (ULONG
)kickrom
[i
+ 1]));
827 * Call the SysBase initialization.
829 Early_ScreenCode(CODE_EXEC_CHECK
);
830 if (!krnPrepareExecBase(kickrom
, mh
, bootmsgptr
))
831 Early_Alert(AT_DeadEnd
| AG_MakeLib
| AO_ExecLib
);
833 /* From here on, we can reference SysBase */
835 DEBUGPUTHEX(("[SysBase] at", (ULONG
)SysBase
));
837 PrivExecBase(SysBase
)->PlatformData
.BootMsg
= bootmsgptr
;
838 SysBase
->ThisTask
->tc_SPLower
= &_ss
;
839 SysBase
->ThisTask
->tc_SPUpper
= &_ss_end
;
842 SysBase
->ColdCapture
= ColdCapture
;
843 SysBase
->CoolCapture
= CoolCapture
;
844 SysBase
->WarmCapture
= WarmCapture
;
846 SysBase
->ChkSum
= GetSysBaseChkSum(SysBase
) ^ 0xffff;
847 SysBase
->KickMemPtr
= KickMemPtr
;
848 SysBase
->KickTagPtr
= KickTagPtr
;
849 SysBase
->KickCheckSum
= KickCheckSum
;
852 SysBase
->SysStkUpper
= (APTR
)&_ss_end
;
853 SysBase
->SysStkLower
= (APTR
)&_ss
;
855 /* Mark what the last alert was */
856 for (i
= 0; i
< 4; i
++)
857 SysBase
->LastAlert
[i
] = oldLastAlert
[i
];
859 SysBase
->AttnFlags
= attnflags
;
861 /* Inject code for GetCC, depending on CPU model */
862 if (SysBase
->AttnFlags
& AFF_68010
) {
863 /* move.w %ccr,%d0; rts; nop */
864 FAKE_IT(SysBase
, Exec
, GetCC
, 88, 0x42c0, 0x4e75, 0x4e71);
866 /* move.w %sr,%d0; rts; nop */
867 FAKE_IT(SysBase
, Exec
, GetCC
, 88, 0x40c0, 0x4e75, 0x4e71);
870 #ifdef THESE_ARE_KNOWN_SAFE_ASM_ROUTINES
871 PRESERVE_ALL(SysBase
, Exec
, Disable
, 20);
872 PRESERVE_ALL(SysBase
, Exec
, Enable
, 21);
873 PRESERVE_ALL(SysBase
, Exec
, Forbid
, 22);
875 PRESERVE_ALL(SysBase
, Exec
, Permit
, 23);
876 PRESERVE_ALL(SysBase
, Exec
, ObtainSemaphore
, 94);
877 PRESERVE_ALL(SysBase
, Exec
, ReleaseSemaphore
, 95);
878 PRESERVE_ALL(SysBase
, Exec
, ObtainSemaphoreShared
, 113);
880 /* Functions that need sign extension */
881 EXT_BYTE(SysBase
, Exec
, SetTaskPri
, 50);
882 EXT_BYTE(SysBase
, Exec
, AllocSignal
, 55);
884 /* Only add the 2 standard ROM locations, since
885 * we may get memory at 0x00f00000, or when we
886 * are ReKicked, at the rom-in-ram locations.
888 krnCreateROMHeader("Kickstart ROM", (APTR
)0x00f80000, (APTR
)0x00ffffff);
889 krnCreateROMHeader("Kickstart ROM", (APTR
)0x00e00000, (APTR
)0x00e7ffff);
891 /* Add remaining memory regions */
892 for (i
= 2; membanks
[i
+ 1]; i
+= 2) {
893 IPTR addr
= membanks
[i
];
894 ULONG size
= membanks
[i
+ 1];
896 mh
= addmemoryregion(addr
, size
, BootS
, FALSE
);
897 Enqueue(&SysBase
->MemList
, &mh
->mh_Node
);
899 /* Adjust MaxLocMem and MaxExtMem as needed */
900 if (addr
< 0x00200000)
901 SysBase
->MaxLocMem
= (size
+ 0xffff) & 0xffff0000;
902 else if (addr
< 0x00d00000)
903 SysBase
->MaxExtMem
= size
? (APTR
)(((0xc00000 + (size
+ 0xffff)) & 0xffff0000)) : 0;
906 /* Now that we have a valid SysBase, we can call ColdCapture */
910 /* Seal up SysBase's critical variables */
913 /* Set privilege violation trap - we
914 * need this to support the Exec/Supervisor call
916 trap
[8] = (SysBase
->AttnFlags
& AFF_68010
) ? Exec_Supervisor_Trap
: Exec_Supervisor_Trap_00
;
918 /* SysBase is complete, now we can enable instruction caches safely. */
919 CacheControl(CACRF_EnableI
, CACRF_EnableI
);
922 oldmem
= AvailMem(MEMF_FAST
);
924 /* Ok, let's start the system. We have to
925 * do this in Supervisor context, since some
926 * expansions ROMs (Cyperstorm PPC) expect it.
928 DEBUGPUTS(("[start] InitCode(RTF_SINGLETASK, 0)\n"));
929 InitCode(RTF_SINGLETASK
, 0);
931 /* Autoconfig ram expansions are now configured */
933 /* Our original AROS SysBase was in autoconfig RAM?
934 * ArosBootStrap needs special handling because AOS autoconfigs all boards
935 * before jumping to ColdCapture if SysBase is in autoconfig RAM
937 * Technically we don't need this but it saves KickTags and KickMems
938 * if someone decides to use them. ArosBootStrap does not anymore need them,
939 * it only needs ColdCapture.
942 if (BootS
->RealBase2
) /* SysBase in autoconfig hack */
943 BootS
->RealBase
= BootS
->RealBase2
;
944 if (BootS
->RealBase
&& iseven(BootS
->RealBase
)) {
945 BootS
->RealBase
->ColdCapture
= SysBase
->ColdCapture
;
946 if (IsSysBaseValid(BootS
->RealBase
)) {
947 oldSysBase
= BootS
->RealBase
;
948 DEBUGPUTHEX(("[SysBase] Found original at", (ULONG
)oldSysBase
));
950 DEBUGPUTHEX(("[SysBase] Found original invalid at", (ULONG
)BootS
->RealBase
));
952 BootS
->RealBase
= NULL
;
953 BootS
->RealBase2
= NULL
;
957 /* If oldSysBase is not NULL, that means that it
958 * (a) wasn't valid before when we only had MEMF_LOCAL
959 * ram and (b) could possibly be in the MEMF_KICK memory
960 * we just got. Let's check it and find out if we
961 * can use it's capture vectors.
963 if (oldSysBase
&& IsSysBaseValidNoVersion(oldSysBase
)) {
964 /* Save reset proof vectors */
965 SysBase
->ColdCapture
= oldSysBase
->ColdCapture
;
966 SysBase
->CoolCapture
= oldSysBase
->CoolCapture
;
967 SysBase
->WarmCapture
= oldSysBase
->WarmCapture
;
969 SysBase
->KickMemPtr
= oldSysBase
->KickMemPtr
;
970 SysBase
->KickTagPtr
= oldSysBase
->KickTagPtr
;
971 SysBase
->KickCheckSum
= oldSysBase
->KickCheckSum
;
973 /* Re-seal SysBase */
978 /* Before we allocate anything else, we need to
979 * lock down the mem entries in BootStruct.
981 * Diag module does final allocation attempt.
983 if (arosbootstrapmode
) {
984 if (SysBase
->KickCheckSum
== (APTR
)SumKickData()) {
985 InitKickMem(SysBase
);
986 CollectKickResidents(BootS
, SysBase
);
988 DEBUGPUTS(("PANIC! KickCheckSum mismatch!\n"));
989 Early_Alert(AT_DeadEnd
| AN_MemoryInsane
);
993 if ((AvailMem(MEMF_FAST
) > (oldmem
+ 256 * 1024)) &&
994 ((TypeOfMem(SysBase
) & MEMF_CHIP
) ||
995 ((ULONG
)SysBase
>= 0x00a00000ul
&& (ULONG
)SysBase
< 0x01000000ul
))) {
996 /* Move execbase to real fast if available now */
997 SysBase
= PrepareExecBaseMove(SysBase
);
998 AbsExecBase
= SysBase
;
999 DEBUGPUTHEX(("[Sysbase] now at", (ULONG
)SysBase
));
1002 /* Initialize IRQ subsystem */
1003 AmigaIRQInit(SysBase
);
1005 /* Set privilege violation trap again.
1006 * AmigaIRQInit may have blown it away.
1008 trap
[8] = (SysBase
->AttnFlags
& AFF_68010
) ? Exec_Supervisor_Trap
: Exec_Supervisor_Trap_00
;
1010 /* Attempt to allocate a real stack, and switch to it. */
1012 const ULONG size
= AROS_STACKSIZE
;
1015 usp
= AllocMem(size
* sizeof(IPTR
), MEMF_PUBLIC
);
1017 DEBUGPUTS(("PANIC! Can't allocate a new stack for Exec!\n"));
1018 Early_Alert(CODE_ALLOC_FAIL
);
1021 /* Leave supervisor mode, switch power led on */
1023 "or.b #2,0xbfe001\n"
1026 "move.l %2,%%sp@-\n"
1031 : "a" (&usp
[size
-3]),
1037 /* We shouldn't get here */
1038 DEBUGPUTS(("PANIC! doInitCode() returned!\n"));
1039 Early_Alert(CODE_EXEC_FAIL
);