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)
56 * Kickstart entry point. Note that our code area is already made read-only by the bootstrap.
58 int __startup
startup(struct TagItem
*msg
, ULONG magic
)
60 void* _stack
= AROS_GET_SP
;
64 unsigned int mm_PageSize
, memsize
;
65 struct MemHeader
*bootmh
= NULL
, *chipmh
= NULL
, *fastmh
= NULL
;
66 #if (__WORDSIZE == 64)
67 struct MemHeader
*highmh
= NULL
;
69 struct TagItem
*tag
, *tstate
= msg
;
70 struct HostInterface
*hif
= NULL
;
71 struct mb_mmap
*mmap
= NULL
;
72 unsigned long mmap_len
= 0;
73 BOOL mem_tlsf
= FALSE
;
75 UWORD
*ranges
[] = {NULL
, NULL
, (UWORD
*)-1};
77 /* This bails out if the user started us from within AROS command line, as common executable */
78 if (magic
!= AROS_BOOT_MAGIC
)
81 while ((tag
= LibNextTagItem(&tstate
)))
85 case KRN_KernelLowest
:
86 ranges
[0] = (UWORD
*)tag
->ti_Data
;
89 case KRN_KernelHighest
:
90 ranges
[1] = (UWORD
*)tag
->ti_Data
;
94 mmap
= (struct mb_mmap
*)tag
->ti_Data
;
95 /* we have atleast 1 mmap */
97 mmap_len
= sizeof(struct mb_mmap
);
101 mmap_len
= tag
->ti_Data
;
105 __clear_bss((struct KernelBSS
*)tag
->ti_Data
);
108 case KRN_HostInterface
:
109 hif
= (struct HostInterface
*)tag
->ti_Data
;
113 cmdline
= (char *)tag
->ti_Data
;
118 /* Set globals only AFTER __clear_bss() */
122 /* If there's no proper HostIFace, we can't even say anything */
126 if (strcmp(HostIFace
->System
, AROS_ARCHITECTURE
))
129 if (HostIFace
->Version
< HOSTINTERFACE_VERSION
)
132 /* Host interface is okay. We have working krnPutC() and can talk now. */
133 D(nbug("[Kernel] Starting up...\n"));
135 if ((!ranges
[0]) || (!ranges
[1]) || (!mmap
))
137 krnPanic(NULL
, "Not enough information from the bootstrap\n"
139 "Kickstart start 0x%p, end 0x%p\n"
140 "Memory map address: 0x%p",
141 ranges
[0], ranges
[1], mmap
);
145 hostlib
= HostIFace
->hostlib_Open(LIBC_NAME
, &errstr
);
149 krnPanic(NULL
, "Failed to load %s\n%s", LIBC_NAME
, errstr
);
153 /* Here we can add some variant-specific things. Android and iOS ports use this. */
154 if (!set_call_libfuncs(SETNAME(STARTUP
), 1, 1, hostlib
))
156 HostIFace
->hostlib_Close(hostlib
, NULL
);
161 /* Now query memory page size. We need in order to get our memory manager functional. */
162 mm_PageSize
= krnGetPageSize(hostlib
);
163 D(nbug("[KRN] Memory page size is %u\n", mm_PageSize
));
164 if (!(cmdline
&& strstr(cmdline
, "notlsf")))
166 /* this should probably be handled directly in krnCreateMemHeader */
168 D(nbug("[KRN] Using TLSF Memory Manager\n"));
173 /* krnGetPageSize() panics itself */
174 HostIFace
->hostlib_Close(hostlib
, NULL
);
179 /* We know that memory map has only one memory range */
180 chipmh
= (struct MemHeader
*)(IPTR
)mmap
->addr
;
181 memsize
= mmap
->len
> CHIPMEMSIZE
? CHIPMEMSIZE
: mmap
->len
;
183 /* Prepare the simulated mem headers */
184 /* NOTE: two mem headers are created to cover more cases of memory system */
185 krnCreateMemHeader("CHIP RAM", -5, chipmh
, memsize
, MEMF_CHIP
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
|ARCH_31BIT
);
187 chipmh
= krnConvertMemHeaderToTLSF(chipmh
);
190 if (mmap
->len
> memsize
)
192 fastmh
= (struct MemHeader
*)(mmap
->addr
+ memsize
);
193 memsize
= mmap
->len
- memsize
;
194 krnCreateMemHeader("Fast RAM", 0, fastmh
, memsize
, MEMF_FAST
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
|ARCH_31BIT
);
196 fastmh
= krnConvertMemHeaderToTLSF(fastmh
);
197 if (memsize
> (1024 * 1024))
201 #if (__WORDSIZE == 64)
202 /* on 64bit platforms, we may be passed an additional mmap */
203 if (mmap_len
> sizeof(struct mb_mmap
))
205 struct mb_mmap
*mmapnxt
= &mmap
[1];
207 highmh
= (void *)mmapnxt
->addr
;
209 krnCreateMemHeader("Fast RAM", 0, highmh
, mmapnxt
->len
, MEMF_FAST
|MEMF_PUBLIC
|MEMF_LOCAL
|MEMF_KICK
);
211 highmh
= krnConvertMemHeaderToTLSF(highmh
);
216 * SysBase pre-validation after a warm restart.
217 * This makes sure that it points to a valid accessible memory region.
219 if (((IPTR
)SysBase
< mmap
->addr
) || ((IPTR
)SysBase
+ sizeof(struct ExecBase
) > mmap
->addr
+ mmap
->len
))
222 /* Create SysBase. After this we can use basic exec services, like memory allocation, lists, etc */
223 D(nbug("[Kernel] calling krnPrepareExecBase(), mh_First = %p\n", bootmh
->mh_First
));
224 if (!krnPrepareExecBase(ranges
, bootmh
, msg
))
226 /* Hosted krnPanic() returns, allowing us to drop back into bootstrap */
227 HostIFace
->hostlib_Close(hostlib
, NULL
);
232 D(nbug("[Kernel] SysBase=%p, mh_First=%p\n", SysBase
, bootmh
->mh_First
));
234 if (bootmh
!= chipmh
&& chipmh
)
235 Enqueue(&SysBase
->MemList
, &chipmh
->mh_Node
);
237 if (bootmh
!= fastmh
&& fastmh
)
238 Enqueue(&SysBase
->MemList
, &fastmh
->mh_Node
);
240 #if (__WORDSIZE == 64)
241 if (bootmh
!= highmh
&& highmh
)
242 Enqueue(&SysBase
->MemList
, &highmh
->mh_Node
);
246 * ROM memory header. This special memory header covers all ROM code and data sections
247 * so that TypeOfMem() will not return 0 for addresses pointing into the kernel.
249 krnCreateROMHeader("Kickstart ROM", ranges
[0], ranges
[1]);
252 * Stack memory header. This special memory header covers a little part of the programs
253 * stack so that TypeOfMem() will not return 0 for addresses pointing into the stack
254 * during initialization.
256 krnCreateROMHeader("Boot stack", _stack
- AROS_STACKSIZE
, _stack
);
258 /* The following is a typical AROS bootup sequence */
259 InitCode(RTF_SINGLETASK
, 0); /* Initialize early modules. This includes hostlib.resource. */
260 core_Start(hostlib
); /* Got hostlib.resource. Initialize our interrupt mechanism. */
261 InitCode(RTF_COLDSTART
, 0); /* Boot! */
263 /* If we returned here, something went wrong, and dos.library failed to take over */
264 krnPanic(getKernelBase(), "Failed to start up the system");
266 HostIFace
->hostlib_Close(hostlib
, NULL
);