Documented GVF_SAVE_VAR alongside other flags, and removed a query/doubt
[AROS.git] / arch / all-unix / kernel / kernel_startup.c
blobd2973f0464a9ecbeb8a99e3b79d9a12be63fa642
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)
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;
61 void *hostlib;
62 char *errstr;
63 char *cmdline = NULL;
64 unsigned int mm_PageSize, memsize;
65 struct MemHeader *bootmh = NULL, *chipmh = NULL, *fastmh = NULL;
66 #if (__WORDSIZE == 64)
67 struct MemHeader *highmh = NULL;
68 #endif
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)
79 return -1;
81 while ((tag = LibNextTagItem(&tstate)))
83 switch (tag->ti_Tag)
85 case KRN_KernelLowest:
86 ranges[0] = (UWORD *)tag->ti_Data;
87 break;
89 case KRN_KernelHighest:
90 ranges[1] = (UWORD *)tag->ti_Data;
91 break;
93 case KRN_MMAPAddress:
94 mmap = (struct mb_mmap *)tag->ti_Data;
95 /* we have atleast 1 mmap */
96 if (!mmap_len)
97 mmap_len = sizeof(struct mb_mmap);
98 break;
100 case KRN_MMAPLength:
101 mmap_len = tag->ti_Data;
102 break;
104 case KRN_KernelBss:
105 __clear_bss((struct KernelBSS *)tag->ti_Data);
106 break;
108 case KRN_HostInterface:
109 hif = (struct HostInterface *)tag->ti_Data;
110 break;
112 case KRN_CmdLine:
113 cmdline = (char *)tag->ti_Data;
114 break;
118 /* Set globals only AFTER __clear_bss() */
119 BootMsg = msg;
120 HostIFace = hif;
122 /* If there's no proper HostIFace, we can't even say anything */
123 if (!HostIFace)
124 return -1;
126 if (strcmp(HostIFace->System, AROS_ARCHITECTURE))
127 return -1;
129 if (HostIFace->Version < HOSTINTERFACE_VERSION)
130 return -1;
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"
138 "\n"
139 "Kickstart start 0x%p, end 0x%p\n"
140 "Memory map address: 0x%p",
141 ranges[0], ranges[1], mmap);
142 return -1;
145 hostlib = HostIFace->hostlib_Open(LIBC_NAME, &errstr);
146 AROS_HOST_BARRIER
147 if (!hostlib)
149 krnPanic(NULL, "Failed to load %s\n%s", LIBC_NAME, errstr);
150 return -1;
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);
157 AROS_HOST_BARRIER
158 return -1;
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 */
167 mem_tlsf = TRUE;
168 D(nbug("[KRN] Using TLSF Memory Manager\n"));
171 if (!mm_PageSize)
173 /* krnGetPageSize() panics itself */
174 HostIFace->hostlib_Close(hostlib, NULL);
175 AROS_HOST_BARRIER
176 return -1;
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);
186 if (mem_tlsf)
187 chipmh = krnConvertMemHeaderToTLSF(chipmh);
188 bootmh = 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);
195 if (mem_tlsf)
196 fastmh = krnConvertMemHeaderToTLSF(fastmh);
197 if (memsize > (1024 * 1024))
198 bootmh = fastmh;
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);
210 if (mem_tlsf)
211 highmh = krnConvertMemHeaderToTLSF(highmh);
213 #endif
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))
220 SysBase = NULL;
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);
228 AROS_HOST_BARRIER
229 return -1;
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);
243 #endif
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);
267 AROS_HOST_BARRIER
269 return 1;