Patch hosted memory allocation. some systems will not allow AROS to allocate > 1024MB...
[AROS.git] / arch / all-hosted / bootstrap / bootstrap.c
blob2a42748a45eef3410c19e705d46948db88e4bb3c
1 /*
2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #include <ctype.h>
7 #include <dirent.h>
8 #include <errno.h>
9 #include <limits.h>
10 #include <locale.h>
11 #include <stdarg.h>
12 #include <stdio.h>
13 #include <stdlib.h>
14 #include <string.h>
15 #include <sys/stat.h>
17 #ifndef _WIN32
18 #include <unistd.h>
19 #endif
21 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
22 #undef __pure
23 #undef __const
24 #undef __pure2
25 #undef __deprecated
27 #include <aros/kernel.h>
28 #include <aros/multiboot.h>
29 #include <exec/execbase.h>
30 #include <utility/tagitem.h>
32 #include <elfloader.h>
33 #include <runtime.h>
35 #include "bootstrap.h"
36 #include "elf_io.h"
37 #include "filesystem.h"
38 #include "kickstart.h"
39 #include "log.h"
40 #include "memory.h"
41 #include "support.h"
42 #include "shutdown.h"
44 #ifndef PATH_MAX
45 #define PATH_MAX _MAX_PATH
46 #endif
48 #define D(x)
50 #define LOWMEMSIZE (512 * 1024 * 1024)
52 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
53 #undef __pure
54 #undef __const
55 #undef __pure2
56 #undef __deprecated
58 extern int errno;
60 extern void *HostIFace;
62 /*
63 * External libgcc routine which eventually clears instruction cache.
64 * It is equivalent to gcc's __builtin___clear_cache(char *, char*)
66 extern void __clear_cache(char *begin, char *end);
68 char bootstrapdir[PATH_MAX];
69 char *KernelArgs = NULL;
70 char *SystemVersion = NULL;
71 char buf[BUFFER_SIZE];
73 #if (__WORDSIZE != 64)
74 static struct mb_mmap MemoryMap[1] =
75 #else
76 static struct mb_mmap MemoryMap[2] =
77 #endif
80 sizeof(struct mb_mmap) - 4,
83 #if (__WORDSIZE != 64)
86 #endif
87 MMAP_TYPE_RAM
89 #if (__WORDSIZE == 64)
90 , {
91 sizeof(struct mb_mmap) - 4,
94 MMAP_TYPE_RAM
96 #endif
99 /* gdb can pick up kickstart segments from here */
100 static struct ELF_ModuleInfo *Debug_KickList = NULL;
102 static const char version[] = "$VER: AROS Hosted bootstrap v1.0 (" ADATE ")";
104 /* Kernel message */
105 static struct TagItem km[] =
107 {KRN_KernelLowest , 0 },
108 {KRN_KernelHighest, 0 },
109 {KRN_KernelBss , 0 },
110 {KRN_BootLoader , 0 },
111 {KRN_DebugInfo , 0 },
112 {KRN_HostInterface, 0 },
113 {KRN_MMAPAddress , 0 },
114 {KRN_MMAPLength , sizeof(struct mb_mmap)},
115 {KRN_CmdLine , 0 },
116 {TAG_DONE , 0 }
119 /* Global SysBase */
120 struct ExecBase *SysBase;
122 static char *GetConfigArg(char *str, char *option)
124 size_t l = strlen(option);
126 /* First check option name */
127 if (strncasecmp(str, option, l))
128 return NULL;
130 /* Skip option name */
131 str += l;
133 /* First character must be space */
134 if (!isspace(*str++))
135 return NULL;
136 /* Skip the rest of spaces */
137 while(isspace(*str))
138 str++;
140 return str;
143 char *join_string(int argc, char **argv)
145 char *str, *s;
146 int j;
147 int x = 0;
149 for (j = 0; j < argc; j++)
150 x += (strlen(argv[j]) + 1);
151 D(fprintf(stderr, "[Bootstrap] Allocating %u bytes for string\n", x));
152 str = malloc(x);
153 if (str) {
154 s = str;
155 for (j = 0; j < argc; j++) {
156 strcpy(s, argv[j]);
157 s += strlen(s);
158 *s++ = ' ';
160 s[-1] = 0;
161 D(fprintf(stderr, "[Bootstrap] Joined line: %s\n", str));
163 return str;
166 int bootstrap(int argc, char ** argv)
168 int i = 1;
169 unsigned int memSize = 64;
170 int def_memSize = 1;
171 char *config = DefaultConfig;
172 FILE *file;
173 kernel_entry_fun_t kernel_entry;
174 void *ro_addr, *rw_addr, *__bss_track;
175 unsigned long ro_size, rw_size, bss_size;
177 D(fprintf(stderr, "[Bootstrap] Started\n"));
180 * This makes national characters to be output properly into
181 * the debug log under Windows
183 setlocale(LC_ALL, "");
184 if (!getcwd(bootstrapdir, sizeof(bootstrapdir)))
186 DisplayError("Failed to get current working directory!");
187 return -1;
189 SaveArgs(argv);
191 while (i < argc) {
192 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
193 printf ("Hosted AROS bootstrap\n"
194 "usage: %s [options] [kernel arguments]\n"
195 "Available options:\n"
196 " -h show this page\n"
197 " -m <size> allocate <size> Megabytes of memory for AROS\n"
198 " (default is 64MB)\n"
199 " -c <file> read configuration from <file>\n"
200 " (default is %s)\n"
201 " --help same as '-h'\n"
202 " --memsize <size> same as '-m <size>'\n"
203 " --config <file> same as '-c'\n"
204 "\n"
205 "Please report bugs to the AROS development team. http://www.aros.org/\n", argv[0], DefaultConfig);
206 return 0;
207 } else if (!strcmp(argv[i], "--memsize") || !strcmp(argv[i], "-m")) {
208 memSize = atoi(argv[++i]);
209 def_memSize = 0;
210 i++;
211 } else if (!strcmp(argv[i], "--config") || !strcmp(argv[i], "-c")) {
212 config = argv[++i];
213 i++;
214 } else
215 break;
217 D(fprintf(stderr, "[Bootstrap] %u argument%s processed\n", i, i==1 ? "" : "s"));
219 if (i < argc) {
220 KernelArgs = join_string(argc - i, &argv[i]);
221 D(fprintf(stderr, "[Bootstrap] Kernel arguments: %s\n", KernelArgs));
224 SystemVersion = getosversion(&version[6]);
225 D(fprintf(stderr, "[Bootstrap] OS version: %s\n", SystemVersion));
227 if (SetRootDirectory())
229 DisplayError("Failed to locate root directory!");
230 return -1;
233 D(fprintf(stderr, "[Bootstrap] Opening configuration file %s\n", config));
234 file = fopen(config, "r");
235 if (!file)
237 DisplayError("Failed to load configuration file %s!", config);
238 return -1;
241 /* Parse the configuration file */
242 while (fgets(buf, sizeof(buf), file)) {
243 char *c = strchr(buf, '\r');
245 if (!c)
246 c = strchr(buf, '\n');
247 if (c)
248 *c = 0;
250 c = GetConfigArg(buf, "module");
251 if (c) {
252 AddKernelFile(c);
253 continue;
256 /* Command line argument overrides this */
257 if (def_memSize) {
258 c = GetConfigArg(buf, "memory");
259 if (c) {
260 memSize = atoi(c);
261 continue;
265 c = GetConfigArg(buf, "logfile");
266 if (c)
268 i = SetLog(c);
269 if (i)
271 DisplayError("Failed to redirect debug output to %s", c);
272 return i;
274 fprintf(stderr, "----\n"); /* Separation marker */
277 c = GetConfigArg(buf, "arguments");
278 if (c)
280 /* If we already have some arguments, append our line to them */
281 if (KernelArgs)
283 char *parts[] = {KernelArgs, c};
284 char *args = join_string(2, parts);
286 if (args)
288 free(KernelArgs);
289 KernelArgs = args;
292 else
294 /* Otherwise just copy the line */
295 i = strlen(c);
296 if (i)
298 i++;
299 KernelArgs = malloc(i);
300 memcpy(KernelArgs, c, i);
305 fclose(file);
307 D(fprintf(stderr, "[Bootstrap] Allocating %iMB of RAM for AROS\n",memSize));
309 #if (__WORDSIZE == 64)
310 if ((memSize << 20) > LOWMEMSIZE)
312 MemoryMap[1].len = (memSize << 20) - LOWMEMSIZE;
313 MemoryMap[1].addr = (IPTR)AllocateRAM((size_t)MemoryMap[1].len);
314 if (!MemoryMap[1].addr) {
315 int err = errno;
316 DisplayError("[Bootstrap] Failed to allocate %iMB of 'High' RAM for AROS: %08x %s\n", memSize, err, strerror(err));
317 return -1;
319 fprintf(stderr, "[Bootstrap] RAM memory block allocated: %p - %p (%u bytes)\n",
320 (void *)(IPTR)MemoryMap[1].addr, (void *)(IPTR)MemoryMap[1].addr + MemoryMap[1].len, MemoryMap[1].len);
322 memSize = (LOWMEMSIZE >> 20);
323 km[7].ti_Data += sizeof(struct mb_mmap);
325 #endif
326 MemoryMap[0].len = memSize << 20;
327 MemoryMap[0].addr = (IPTR)AllocateRAM32((size_t)MemoryMap[0].len);
329 if (!MemoryMap[0].addr) {
330 int err = errno;
331 DisplayError("[Bootstrap] Failed to allocate %iMB of RAM for AROS: %08x %s\n", memSize, err, strerror(err));
332 return -1;
334 fprintf(stderr, "[Bootstrap] RAM memory block allocated: %p - %p (%u bytes)\n",
335 (void *)(IPTR)MemoryMap[0].addr, (void *)(IPTR)MemoryMap[0].addr + MemoryMap[0].len, MemoryMap[0].len);
337 if (!GetKernelSize(FirstELF, &ro_size, &rw_size, &bss_size))
338 return -1;
340 ro_addr = AllocateRO(ro_size);
341 D(fprintf(stderr, "[Bootstrap] Kickstart ROM area: %p\n", ro_addr));
342 if (!ro_addr)
344 DisplayError("Failed to allocate %u bytes for the kickstart!", ro_size);
345 return -1;
348 rw_addr = AllocateRW(rw_size);
349 D(fprintf(stderr, "[Bootstrap] Kickstart data area: %p\n", rw_addr));
350 if (!rw_addr)
352 DisplayError("Failed to allocate %u bytes for the kickstart!", rw_size);
353 return -1;
356 __bss_track = AllocateRO(bss_size);
357 D(fprintf(stderr, "[Bootstrap] Kickstart BSS array: %p\n", __bss_track));
358 if (!__bss_track)
360 DisplayError("Failed to allocate %u bytes for the kickstart!", bss_size);
361 return -1;
364 if (!LoadKernel(FirstELF, ro_addr, rw_addr, __bss_track, (uintptr_t)&SysBase, NULL, &kernel_entry, &Debug_KickList))
365 return -1;
367 D(fprintf(stderr, "[Bootstrap] Read-only %p - %p, Read-write %p - %p, Entry %p, Debug info %p\n",
368 ro_addr, ro_addr + ro_size - 1, rw_addr, rw_addr + rw_size - 1, kernel_entry, Debug_KickList));
370 FreeKernelList();
372 D(fprintf(stderr, "[Bootstrap] Sealing kernel code memory\n"));
373 if (SetRO(ro_addr, ro_size))
375 DisplayError("Failed to set kernel memory permissions");
376 return -1;
380 km[0].ti_Data = (IPTR)ro_addr;
381 km[1].ti_Data = (IPTR)ro_addr + ro_size - 1;
382 km[2].ti_Data = (IPTR)__bss_track;
383 km[3].ti_Data = (IPTR)SystemVersion;
384 km[4].ti_Data = (IPTR)Debug_KickList;
385 km[5].ti_Data = (IPTR)HostIFace;
386 km[6].ti_Data = (IPTR)&MemoryMap;
387 /* km[7] is statically filled in */
388 if (KernelArgs)
389 km[8].ti_Data = (IPTR)KernelArgs;
390 else
391 km[8].ti_Tag = TAG_DONE;
393 /* Flush instruction cache */
394 __clear_cache((char *)ro_addr, (char *)ro_addr + ro_size);
396 #ifdef DEBUG_CODE
397 /* This is a quickly hacked up sanity test which was used during iOS port development */
398 if (ro_size > 256)
399 ro_size = 256;
401 fprintf(stderr, "[Bootstrap] Dumping %u bytes of code at %p\n", ro_size, ro_addr);
402 for (i = 0; i < ro_size;)
404 if (i % 8 == 0)
405 fprintf(stderr, "%p ", ro_addr + i);
406 fprintf(stderr, "%02X ", ((unsigned char *)ro_addr)[i++]);
407 if (i % 8 == 0)
408 fprintf(stderr, "\n");
410 fprintf(stderr, "\n");
411 #endif
413 i = kick(kernel_entry, km);
415 return i;