revert between 56095 -> 55830 in arch
[AROS.git] / arch / all-unix / kernel / kernel_startup.c
blobfe0a46ccef5e73f722b79adc28f285684811f8b0
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
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>
16 #include <sys/mman.h>
18 #include <inttypes.h>
19 #include <string.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"
29 #define D(x)
31 /* This macro is defined in both UNIX and AROS headers. Get rid of warnings. */
32 #undef __const
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)
39 #ifdef HOST_OS_linux
40 #define ARCH_31BIT MEMF_31BIT
41 #endif
42 #endif
43 #ifndef ARCH_31BIT
44 #define ARCH_31BIT 0
45 #endif
47 /* Global HostIFace is needed for krnPutC() to work before KernelBase is set up */
48 struct HostInterface *HostIFace;
50 THIS_PROGRAM_HANDLES_SYMBOLSET(STARTUP)
51 DEFINESET(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;
62 void *hostlib;
63 char *errstr;
64 char *cmdline = NULL;
65 unsigned int mm_PageSize, memsize;
66 struct MemHeader *bootmh = NULL, *chipmh = NULL, *fastmh = NULL;
67 #if (__WORDSIZE == 64)
68 struct MemHeader *highmh = NULL;
69 #endif
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)
80 return -1;
82 while ((tag = LibNextTagItem(&tstate)))
84 switch (tag->ti_Tag)
86 case KRN_KernelLowest:
87 ranges[0] = (UWORD *)tag->ti_Data;
88 break;
90 case KRN_KernelHighest:
91 ranges[1] = (UWORD *)tag->ti_Data;
92 break;
94 case KRN_MMAPAddress:
95 mmap = (struct mb_mmap *)tag->ti_Data;
96 /* we have atleast 1 mmap */
97 if (!mmap_len)
98 mmap_len = sizeof(struct mb_mmap);
99 break;
101 case KRN_MMAPLength:
102 mmap_len = tag->ti_Data;
103 break;
105 case KRN_KernelBss:
106 __clear_bss((struct KernelBSS *)tag->ti_Data);
107 break;
109 case KRN_HostInterface:
110 hif = (struct HostInterface *)tag->ti_Data;
111 break;
113 case KRN_CmdLine:
114 cmdline = (char *)tag->ti_Data;
115 break;
119 /* Set globals only AFTER __clear_bss() */
120 BootMsg = msg;
121 HostIFace = hif;
123 /* If there's no proper HostIFace, we can't even say anything */
124 if (!HostIFace)
125 return -1;
127 if (strcmp(HostIFace->System, AROS_ARCHITECTURE))
128 return -1;
130 if (HostIFace->Version < HOSTINTERFACE_VERSION)
131 return -1;
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"
139 "\n"
140 "Kickstart start 0x%p, end 0x%p\n"
141 "Memory map address: 0x%p",
142 ranges[0], ranges[1], mmap);
143 return -1;
146 hostlib = HostIFace->hostlib_Open(LIBC_NAME, &errstr);
147 AROS_HOST_BARRIER
148 if (!hostlib)
150 krnPanic(NULL, "Failed to load %s\n%s", LIBC_NAME, errstr);
151 return -1;
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);
158 AROS_HOST_BARRIER
159 return -1;
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 */
168 mem_tlsf = TRUE;
169 D(nbug("[KRN] Using TLSF Memory Manager\n"));
172 if (!mm_PageSize)
174 /* krnGetPageSize() panics itself */
175 HostIFace->hostlib_Close(hostlib, NULL);
176 AROS_HOST_BARRIER
177 return -1;
181 * The first memory map entry represents low
182 * (32bit) memory, so we allocate the "chip"
183 * memory from it.
185 chipmh = (struct MemHeader *)(IPTR)mmap->addr;
186 memsize = mmap->len > CHIPMEMSIZE ? CHIPMEMSIZE : mmap->len;
188 if (STACKINRANGE(_stack, mmap->addr, mmap->len))
189 host_stack = FALSE;
190 if (((IPTR)SysBase > mmap->addr) && ((IPTR)SysBase + sizeof(struct ExecBase) < mmap->addr + mmap->len))
191 sysb_safe = TRUE;
193 /* Prepare the chip memory's header... */
194 krnCreateMemHeader("CHIP RAM", -5, chipmh, memsize, MEMF_CHIP|MEMF_PUBLIC|MEMF_LOCAL|MEMF_KICK|ARCH_31BIT);
195 if (mem_tlsf)
196 chipmh = krnConvertMemHeaderToTLSF(chipmh);
197 bootmh = 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);
206 if (mem_tlsf)
207 fastmh = krnConvertMemHeaderToTLSF(fastmh);
209 /* if its larger than 1MB, use it for the boot mem */
210 if (memsize > (1024 * 1024))
211 bootmh = fastmh;
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))
222 host_stack = FALSE;
223 if (((IPTR)SysBase > mmapnxt->addr) && ((IPTR)SysBase + sizeof(struct ExecBase) < mmapnxt->addr + mmapnxt->len))
224 sysb_safe = TRUE;
226 krnCreateMemHeader("Fast RAM", 0, highmh, mmapnxt->len, MEMF_FAST|MEMF_PUBLIC|MEMF_LOCAL|MEMF_KICK);
227 if (mem_tlsf)
228 highmh = krnConvertMemHeaderToTLSF(highmh);
230 if ((bootmh == chipmh) && (mmapnxt->len > (1024 * 1024)))
231 bootmh = highmh;
233 #endif
236 * SysBase pre-validation after a warm restart.
237 * This makes sure that it points to a valid accessible memory region.
239 if (!sysb_safe)
240 SysBase = NULL;
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);
248 AROS_HOST_BARRIER
249 return -1;
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);
263 #endif
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]);
271 if (host_stack)
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);
291 AROS_HOST_BARRIER
293 return 1;