bump copyright date on affected files and version
[AROS.git] / arch / all-hosted / bootstrap / bootstrap.c
blob383bfa58d7cd45d72f61ecdaf327915c143d9b55
1 #include <ctype.h>
2 #include <dirent.h>
3 #include <limits.h>
4 #include <stdarg.h>
5 #include <stdio.h>
6 #include <stdlib.h>
7 #include <string.h>
8 #include <sys/stat.h>
10 #ifndef _WIN32
11 #include <unistd.h>
12 #endif
13 #ifndef UNDER_CE
14 #include <locale.h>
15 #endif
17 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
18 #undef __pure
19 #undef __const
20 #undef __pure2
21 #undef __deprecated
23 #include <aros/kernel.h>
24 #include <aros/multiboot.h>
25 #include <exec/execbase.h>
26 #include <utility/tagitem.h>
28 #include <elfloader.h>
29 #include <runtime.h>
31 #include "bootstrap.h"
32 #include "elf_io.h"
33 #include "filesystem.h"
34 #include "kickstart.h"
35 #include "log.h"
36 #include "memory.h"
37 #include "support.h"
38 #include "shutdown.h"
40 #ifndef PATH_MAX
41 #define PATH_MAX _MAX_PATH
42 #endif
44 #define D(x)
46 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
47 #undef __pure
48 #undef __const
49 #undef __pure2
50 #undef __deprecated
52 extern void *HostIFace;
54 /*
55 * External libgcc routine which eventually clears instruction cache.
56 * It is equivalent to gcc's __builtin___clear_cache(char *, char*)
58 extern void __clear_cache(char *begin, char *end);
60 char bootstrapdir[PATH_MAX];
61 char *KernelArgs = NULL;
62 char *SystemVersion = NULL;
63 char buf[BUFFER_SIZE];
65 static struct mb_mmap MemoryMap =
67 sizeof(struct mb_mmap) - 4,
70 #if (__WORDSIZE != 64)
73 #endif
74 MMAP_TYPE_RAM
77 /* gdb can pick up kickstart segments from here */
78 static struct ELF_ModuleInfo *Debug_KickList = NULL;
80 static const char version[] = "$VER: AROS Hosted bootstrap v1.0 (" ADATE ")";
82 /* Kernel message */
83 static struct TagItem km[] =
85 {KRN_KernelLowest , 0 },
86 {KRN_KernelHighest, 0 },
87 {KRN_KernelBss , 0 },
88 {KRN_BootLoader , 0 },
89 {KRN_DebugInfo , 0 },
90 {KRN_HostInterface, 0 },
91 {KRN_MMAPAddress , 0 },
92 {KRN_MMAPLength , sizeof(MemoryMap)},
93 {KRN_CmdLine , 0 },
94 {TAG_DONE , 0 }
97 /* Global SysBase */
98 struct ExecBase *SysBase;
100 static char *GetConfigArg(char *str, char *option)
102 size_t l = strlen(option);
104 /* First check option name */
105 if (strncasecmp(str, option, l))
106 return NULL;
108 /* Skip option name */
109 str += l;
111 /* First character must be space */
112 if (!isspace(*str++))
113 return NULL;
114 /* Skip the rest of spaces */
115 while(isspace(*str))
116 str++;
118 return str;
121 char *join_string(int argc, char **argv)
123 char *str, *s;
124 int j;
125 int x = 0;
127 for (j = 0; j < argc; j++)
128 x += (strlen(argv[j]) + 1);
129 D(fprintf(stderr, "[Bootstrap] Allocating %u bytes for string\n", x));
130 str = malloc(x);
131 if (str) {
132 s = str;
133 for (j = 0; j < argc; j++) {
134 strcpy(s, argv[j]);
135 s += strlen(s);
136 *s++ = ' ';
138 s[-1] = 0;
139 D(fprintf(stderr, "[Bootstrap] Joined line: %s\n", str));
141 return str;
144 int bootstrap(int argc, char ** argv)
146 int i = 1;
147 unsigned int memSize = 64;
148 int def_memSize = 1;
149 char *config = DefaultConfig;
150 FILE *file;
151 kernel_entry_fun_t kernel_entry;
152 void *ro_addr, *rw_addr, *__bss_track;
153 unsigned long ro_size, rw_size, bss_size;
155 D(fprintf(stderr, "[Bootstrap] Started\n"));
157 #ifndef UNDER_CE
159 * This makes national characters to be output properly into
160 * the debug log under Windows
162 setlocale(LC_ALL, "");
163 if (!getcwd(bootstrapdir, sizeof(bootstrapdir)))
165 DisplayError("Failed to get current working directory!");
166 return -1;
168 #endif
169 SaveArgs(argv);
171 while (i < argc) {
172 if (!strcmp(argv[i], "--help") || !strcmp(argv[i], "-h")) {
173 printf ("Hosted AROS bootstrap\n"
174 "usage: %s [options] [kernel arguments]\n"
175 "Available options:\n"
176 " -h show this page\n"
177 " -m <size> allocate <size> Megabytes of memory for AROS\n"
178 " (default is 64M)\n"
179 " -c <file> read configuration from <file>\n"
180 " (default is %s)\n"
181 " --help same as '-h'\n"
182 " --memsize <size> same as '-m <size>'\n"
183 " --config <file> same as '-c'\n"
184 "\n"
185 "Please report bugs to the AROS development team. http://www.aros.org/\n", argv[0], DefaultConfig);
186 return 0;
187 } else if (!strcmp(argv[i], "--memsize") || !strcmp(argv[i], "-m")) {
188 memSize = atoi(argv[++i]);
189 def_memSize = 0;
190 i++;
191 } else if (!strcmp(argv[i], "--config") || !strcmp(argv[i], "-c")) {
192 config = argv[++i];
193 i++;
194 } else
195 break;
197 D(fprintf(stderr, "[Bootstrap] %u arguments processed\n", i));
199 if (i < argc) {
200 KernelArgs = join_string(argc - i, &argv[i]);
201 D(fprintf(stderr, "[Bootstrap] Kernel arguments: %s\n", KernelArgs));
204 SystemVersion = getosversion(&version[6]);
205 D(fprintf(stderr, "[Bootstrap] OS version: %s\n", SystemVersion));
207 if (SetRootDirectory())
209 DisplayError("Failed to locate root directory!");
210 return -1;
213 file = file_open(config, "r");
214 if (!file)
216 DisplayError("Failed to load configuration file %s!", config);
217 return -1;
220 /* Parse the configuration file */
221 while (fgets(buf, sizeof(buf), file)) {
222 char *c = strchr(buf, '\r');
224 if (!c)
225 c = strchr(buf, '\n');
226 if (c)
227 *c = 0;
229 c = GetConfigArg(buf, "module");
230 if (c) {
231 AddKernelFile(c);
232 continue;
235 /* Command line argument overrides this */
236 if (def_memSize) {
237 c = GetConfigArg(buf, "memory");
238 if (c) {
239 memSize = atoi(c);
240 continue;
244 c = GetConfigArg(buf, "logfile");
245 if (c)
247 i = SetLog(c);
248 if (i)
250 DisplayError("Failed to redirect debug output to %s", c);
251 return i;
253 fprintf(stderr, "----\n"); /* Separation marker */
256 c = GetConfigArg(buf, "arguments");
257 if (c)
259 /* If we already have some arguments, append our line to them */
260 if (KernelArgs)
262 char *parts[] = {KernelArgs, c};
263 char *args = join_string(2, parts);
265 if (args)
267 free(KernelArgs);
268 KernelArgs = args;
271 else
273 /* Otherwise just copy the line */
274 i = strlen(c);
275 if (i)
277 i++;
278 KernelArgs = malloc(i);
279 memcpy(KernelArgs, c, i);
284 fclose(file);
286 if (!GetKernelSize(FirstELF, &ro_size, &rw_size, &bss_size))
287 return -1;
289 ro_addr = AllocateRO(ro_size);
290 D(fprintf(stderr, "[Bootstrap] Kickstart ROM area: %p\n", ro_addr));
291 if (!ro_addr)
293 DisplayError("Failed to allocate %u bytes for the kickstart!", ro_size);
294 return -1;
297 rw_addr = AllocateRW(rw_size);
298 D(fprintf(stderr, "[Bootstrap] Kickstart data area: %p\n", rw_addr));
299 if (!rw_addr)
301 DisplayError("Failed to allocate %u bytes for the kickstart!", rw_size);
302 return -1;
305 __bss_track = AllocateRO(bss_size);
306 D(fprintf(stderr, "[Bootstrap] Kickstart BSS array: %p\n", __bss_track));
307 if (!__bss_track)
309 DisplayError("Failed to allocate %u bytes for the kickstart!", bss_size);
310 return -1;
313 if (!LoadKernel(FirstELF, ro_addr, rw_addr, __bss_track, (uintptr_t)&SysBase, NULL, &kernel_entry, &Debug_KickList))
314 return -1;
316 D(fprintf(stderr, "[Bootstrap] Read-only %p - %p, Read-write %p - %p, Entry %p, Debug info %p\n",
317 ro_addr, ro_addr + ro_size - 1, rw_addr, rw_addr + rw_size - 1, kernel_entry, Debug_KickList));
319 FreeKernelList();
321 D(fprintf(stderr, "[Bootstrap] Sealing kernel code memory\n"));
322 if (SetRO(ro_addr, ro_size))
324 DisplayError("Failed to set kernel memory permissions");
325 return -1;
328 D(fprintf(stderr, "[Bootstrap] allocating working mem: %iMb\n",memSize));
330 MemoryMap.len = memSize << 20;
331 MemoryMap.addr = (IPTR)AllocateRAM(MemoryMap.len);
333 if (!MemoryMap.addr) {
334 DisplayError("[Bootstrap] Failed to allocate %i Mb of RAM for AROS!\n", memSize);
335 return -1;
337 D(fprintf(stderr, "[Bootstrap] RAM memory allocated: %p - %p (%u bytes)\n",
338 (void *)(IPTR)MemoryMap.addr, (void *)(IPTR)MemoryMap.addr + MemoryMap.len, MemoryMap.len));
340 km[0].ti_Data = (IPTR)ro_addr;
341 km[1].ti_Data = (IPTR)ro_addr + ro_size - 1;
342 km[2].ti_Data = (IPTR)__bss_track;
343 km[3].ti_Data = (IPTR)SystemVersion;
344 km[4].ti_Data = (IPTR)Debug_KickList;
345 km[5].ti_Data = (IPTR)HostIFace;
346 km[6].ti_Data = (IPTR)&MemoryMap;
347 /* km[7] is statically filled in */
348 if (KernelArgs)
349 km[8].ti_Data = (IPTR)KernelArgs;
350 else
351 km[8].ti_Tag = TAG_DONE;
353 /* Flush instruction cache */
354 __clear_cache((char *)ro_addr, (char *)ro_addr + ro_size);
356 #ifdef DEBUG_CODE
357 /* This is a quickly hacked up sanity test which was used during iOS port development */
358 if (ro_size > 256)
359 ro_size = 256;
361 fprintf(stderr, "[Bootstrap] Dumping %u bytes of code at %p\n", ro_size, ro_addr);
362 for (i = 0; i < ro_size;)
364 if (i % 8 == 0)
365 fprintf(stderr, "%p ", ro_addr + i);
366 fprintf(stderr, "%02X ", ((unsigned char *)ro_addr)[i++]);
367 if (i % 8 == 0)
368 fprintf(stderr, "\n");
370 fprintf(stderr, "\n");
371 #endif
373 i = kick(kernel_entry, km);
375 return i;