2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
6 #include <aros/kernel.h>
7 #include <aros/multiboot.h>
8 #include <aros/symbolsets.h>
9 #include <exec/execbase.h>
10 #include <exec/resident.h>
11 #include <exec/memheaderext.h>
12 #include <utility/tagitem.h>
13 #include <proto/arossupport.h>
14 #include <proto/exec.h>
21 #include "hostinterface.h"
22 #include "kernel_base.h"
23 #include "kernel_debug.h"
24 #include "kernel_globals.h"
25 #include "kernel_intern.h"
26 #include "kernel_romtags.h"
27 #include "kernel_unix.h"
31 /* This macro is defined in both UNIX and AROS headers. Get rid of warnings. */
35 * On 64 bit Linux bootloaded gives us RAM region below 2GB.
36 * On other 64-bit unices we have no control over it.
38 #if (__WORDSIZE == 64)
40 #define ARCH_31BIT MEMF_31BIT
47 /* Global HostIFace is needed for krnPutC() to work before KernelBase is set up */
48 struct HostInterface
*HostIFace
;
50 THIS_PROGRAM_HANDLES_SYMBOLSET(STARTUP
)
53 #define CHIPMEMSIZE (16 * 1024 * 1024)
54 #define STACKINRANGE(ptr, start, length) (((IPTR)ptr > start) && ((IPTR)ptr <= (start + length)))
57 * Kickstart entry point. Note that our code area is already made read-only by the bootstrap.
59 int __startup
startup(struct TagItem
*msg
, ULONG magic
)
61 void* _stack
= AROS_GET_SP
;
65 unsigned int mm_PageSize
, memsize
;
66 struct MemHeader
*bootmh
= NULL
, *chipmh
= NULL
, *fastmh
= NULL
;
67 #if (__WORDSIZE == 64)
68 struct MemHeader
*highmh
= NULL
;
70 struct TagItem
*tag
, *tstate
= msg
;
71 struct HostInterface
*hif
= NULL
;
72 struct mb_mmap
*mmap
= NULL
;
73 unsigned long mmap_len
= 0;
74 BOOL mem_tlsf
= FALSE
, host_stack
= TRUE
, sysb_safe
= FALSE
;
76 UWORD
*ranges
[] = {NULL
, NULL
, (UWORD
*)-1};
78 /* This bails out if the user started us from within AROS command line, as common executable */
79 if (magic
!= AROS_BOOT_MAGIC
)
82 while ((tag
= LibNextTagItem(&tstate
)))
86 case KRN_KernelLowest
:
87 ranges
[0] = (UWORD
*)tag
->ti_Data
;
90 case KRN_KernelHighest
:
91 ranges
[1] = (UWORD
*)tag
->ti_Data
;
95 mmap
= (struct mb_mmap
*)tag
->ti_Data
;
96 /* we have atleast 1 mmap */
98 mmap_len
= sizeof(struct mb_mmap
);
102 mmap_len
= tag
->ti_Data
;
106 __clear_bss((struct KernelBSS
*)tag
->ti_Data
);
109 case KRN_HostInterface
:
110 hif
= (struct HostInterface
*)tag
->ti_Data
;
114 cmdline
= (char *)tag
->ti_Data
;
119 /* Set globals only AFTER __clear_bss() */
123 /* If there's no proper HostIFace, we can't even say anything */
127 if (strcmp(HostIFace
->System
, AROS_ARCHITECTURE
))
130 if (HostIFace
->Version
< HOSTINTERFACE_VERSION
)
133 /* Host interface is okay. We have working krnPutC() and can talk now. */
134 D(nbug("[Kernel] Starting up...\n"));
136 if ((!ranges
[0]) || (!ranges
[1]) || (!mmap
))
138 krnPanic(NULL
, "Not enough information from the bootstrap\n"
140 "Kickstart start 0x%p, end 0x%p\n"
141 "Memory map address: 0x%p",
142 ranges
[0], ranges
[1], mmap
);
146 hostlib
= HostIFace
->hostlib_Open(LIBC_NAME
, &errstr
);
150 krnPanic(NULL
, "Failed to load %s\n%s", LIBC_NAME
, errstr
);
154 /* Here we can add some variant-specific things. Android and iOS ports use this. */
155 if (!set_call_libfuncs(SETNAME(STARTUP
), 1, 1, hostlib
))
157 HostIFace
->hostlib_Close(hostlib
, NULL
);
162 /* Now query memory page size. We need in order to get our memory manager functional. */
163 mm_PageSize
= krnGetPageSize(hostlib
);
164 D(nbug("[KRN] Memory page size is %u\n", mm_PageSize
));
165 if (!(cmdline
&& strstr(cmdline
, "notlsf")))
167 /* this should probably be handled directly in krnCreateMemHeader */
169 D(nbug("[KRN] Using TLSF Memory Manager\n"));
174 /* krnGetPageSize() panics itself */
175 HostIFace
->hostlib_Close(hostlib
, NULL
);
181 * The first memory map entry represents low
182 * (32bit) memory, so we allocate the "chip"
185 chipmh
= (struct MemHeader
*)(IPTR
)mmap
->addr
;
186 memsize
= mmap
->len
> CHIPMEMSIZE
? CHIPMEMSIZE
: mmap
->len
;
188 if (STACKINRANGE(_stack
, mmap
->addr
, mmap
->len
))
190 if (((IPTR
)SysBase
> mmap
->addr
) && ((IPTR
)SysBase
+ sizeof(struct ExecBase
) < mmap
->addr
+ mmap
->len
))
193 /* Prepare the chip memory's header... */
194 krnCreateMemHeader("CHIP RAM", -5, chipmh
, memsize
, MEMF_CHIP
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
|ARCH_31BIT
);
196 chipmh
= krnConvertMemHeaderToTLSF(chipmh
);
199 /* If there is sufficient space left after the chip mem block, register it as fast ram... */
200 if (mmap
->len
> (memsize
+ sizeof(struct MemHeader
)))
202 fastmh
= (struct MemHeader
*)(mmap
->addr
+ memsize
);
203 memsize
= mmap
->len
- memsize
;
205 krnCreateMemHeader("Fast RAM", 0, fastmh
, memsize
, MEMF_FAST
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
|ARCH_31BIT
);
207 fastmh
= krnConvertMemHeaderToTLSF(fastmh
);
209 /* if its larger than 1MB, use it for the boot mem */
210 if (memsize
> (1024 * 1024))
214 #if (__WORDSIZE == 64)
215 /* on 64bit platforms, we may be passed an additional mmap */
216 if (mmap_len
> sizeof(struct mb_mmap
))
218 struct mb_mmap
*mmapnxt
= &mmap
[1];
219 highmh
= (void *)mmapnxt
->addr
;
221 if (STACKINRANGE(_stack
, mmapnxt
->addr
, mmapnxt
->len
))
223 if (((IPTR
)SysBase
> mmapnxt
->addr
) && ((IPTR
)SysBase
+ sizeof(struct ExecBase
) < mmapnxt
->addr
+ mmapnxt
->len
))
226 krnCreateMemHeader("Fast RAM", 0, highmh
, mmapnxt
->len
, MEMF_FAST
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
);
228 highmh
= krnConvertMemHeaderToTLSF(highmh
);
230 if ((bootmh
== chipmh
) && (mmapnxt
->len
> (1024 * 1024)))
236 * SysBase pre-validation after a warm restart.
237 * This makes sure that it points to a valid accessible memory region.
242 /* Create SysBase. After this we can use basic exec services, like memory allocation, lists, etc */
243 D(nbug("[Kernel] calling krnPrepareExecBase(), mh_First = %p\n", bootmh
->mh_First
));
244 if (!krnPrepareExecBase(ranges
, bootmh
, msg
))
246 /* Hosted krnPanic() returns, allowing us to drop back into bootstrap */
247 HostIFace
->hostlib_Close(hostlib
, NULL
);
252 D(nbug("[Kernel] SysBase=%p, mh_First=%p\n", SysBase
, bootmh
->mh_First
));
254 if (bootmh
!= chipmh
&& chipmh
)
255 Enqueue(&SysBase
->MemList
, &chipmh
->mh_Node
);
257 if (bootmh
!= fastmh
&& fastmh
)
258 Enqueue(&SysBase
->MemList
, &fastmh
->mh_Node
);
260 #if (__WORDSIZE == 64)
261 if (bootmh
!= highmh
&& highmh
)
262 Enqueue(&SysBase
->MemList
, &highmh
->mh_Node
);
266 * ROM memory header. This special memory header covers all ROM code and data sections
267 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
269 krnCreateROMHeader("Kickstart ROM", ranges
[0], ranges
[1]);
273 nbug("[KRN] Protecting host process stack (0x%p - 0x%p)\n", _stack
- AROS_STACKSIZE
, _stack
);
275 * Stack memory header. This special memory header covers a little part of the programs
276 * stack so that TypeOfMem() will not return 0 for addresses pointing into the stack
277 * during initialization.
279 krnCreateROMHeader("Boot stack", _stack
- AROS_STACKSIZE
, _stack
);
282 /* The following is a typical AROS bootup sequence */
283 InitCode(RTF_SINGLETASK
, 0); /* Initialize early modules. This includes hostlib.resource. */
284 core_Start(hostlib
); /* Got hostlib.resource. Initialize our interrupt mechanism. */
285 InitCode(RTF_COLDSTART
, 0); /* Boot! */
287 /* If we returned here, something went wrong, and dos.library failed to take over */
288 krnPanic(getKernelBase(), "Failed to start up the system");
290 HostIFace
->hostlib_Close(hostlib
, NULL
);