2 Copyright © 1995-2014, The AROS Development Team. All rights reserved.
21 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
27 #include <aros/kernel.h>
28 #include <aros/multiboot.h>
29 #include <exec/execbase.h>
30 #include <utility/tagitem.h>
32 #include <elfloader.h>
35 #include "bootstrap.h"
37 #include "filesystem.h"
38 #include "kickstart.h"
45 #define PATH_MAX _MAX_PATH
50 #define LOWMEMSIZE (512 * 1024 * 1024)
52 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
58 extern void *HostIFace
;
61 * External libgcc routine which eventually clears instruction cache.
62 * It is equivalent to gcc's __builtin___clear_cache(char *, char*)
64 extern void __clear_cache(char *begin
, char *end
);
66 char bootstrapdir
[PATH_MAX
];
67 char *KernelArgs
= NULL
;
68 char *SystemVersion
= NULL
;
69 char buf
[BUFFER_SIZE
];
71 #if (__WORDSIZE != 64)
72 static struct mb_mmap MemoryMap
[1] =
74 static struct mb_mmap MemoryMap
[2] =
78 sizeof(struct mb_mmap
) - 4,
81 #if (__WORDSIZE != 64)
87 #if (__WORDSIZE == 64)
89 sizeof(struct mb_mmap
) - 4,
97 /* gdb can pick up kickstart segments from here */
98 static struct ELF_ModuleInfo
*Debug_KickList
= NULL
;
100 static const char version
[] = "$VER: AROS Hosted bootstrap v1.0 (" ADATE
")";
103 static struct TagItem km
[] =
105 {KRN_KernelLowest
, 0 },
106 {KRN_KernelHighest
, 0 },
107 {KRN_KernelBss
, 0 },
108 {KRN_BootLoader
, 0 },
109 {KRN_DebugInfo
, 0 },
110 {KRN_HostInterface
, 0 },
111 {KRN_MMAPAddress
, 0 },
112 {KRN_MMAPLength
, sizeof(struct mb_mmap
)},
118 struct ExecBase
*SysBase
;
120 static char *GetConfigArg(char *str
, char *option
)
122 size_t l
= strlen(option
);
124 /* First check option name */
125 if (strncasecmp(str
, option
, l
))
128 /* Skip option name */
131 /* First character must be space */
132 if (!isspace(*str
++))
134 /* Skip the rest of spaces */
141 char *join_string(int argc
, char **argv
)
147 for (j
= 0; j
< argc
; j
++)
148 x
+= (strlen(argv
[j
]) + 1);
149 D(fprintf(stderr
, "[Bootstrap] Allocating %u bytes for string\n", x
));
153 for (j
= 0; j
< argc
; j
++) {
159 D(fprintf(stderr
, "[Bootstrap] Joined line: %s\n", str
));
164 int bootstrap(int argc
, char ** argv
)
167 unsigned int memSize
= 64;
169 char *config
= DefaultConfig
;
171 kernel_entry_fun_t kernel_entry
;
172 void *ro_addr
, *rw_addr
, *__bss_track
;
173 unsigned long ro_size
, rw_size
, bss_size
;
175 D(fprintf(stderr
, "[Bootstrap] Started\n"));
178 * This makes national characters to be output properly into
179 * the debug log under Windows
181 setlocale(LC_ALL
, "");
182 if (!getcwd(bootstrapdir
, sizeof(bootstrapdir
)))
184 DisplayError("Failed to get current working directory!");
190 if (!strcmp(argv
[i
], "--help") || !strcmp(argv
[i
], "-h")) {
191 printf ("Hosted AROS bootstrap\n"
192 "usage: %s [options] [kernel arguments]\n"
193 "Available options:\n"
194 " -h show this page\n"
195 " -m <size> allocate <size> Megabytes of memory for AROS\n"
196 " (default is 64MB)\n"
197 " -c <file> read configuration from <file>\n"
199 " --help same as '-h'\n"
200 " --memsize <size> same as '-m <size>'\n"
201 " --config <file> same as '-c'\n"
203 "Please report bugs to the AROS development team. http://www.aros.org/\n", argv
[0], DefaultConfig
);
205 } else if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m")) {
206 memSize
= atoi(argv
[++i
]);
209 } else if (!strcmp(argv
[i
], "--config") || !strcmp(argv
[i
], "-c")) {
215 D(fprintf(stderr
, "[Bootstrap] %u argument%s processed\n", i
, i
==1 ? "" : "s"));
218 KernelArgs
= join_string(argc
- i
, &argv
[i
]);
219 D(fprintf(stderr
, "[Bootstrap] Kernel arguments: %s\n", KernelArgs
));
222 SystemVersion
= getosversion(&version
[6]);
223 D(fprintf(stderr
, "[Bootstrap] OS version: %s\n", SystemVersion
));
225 if (SetRootDirectory())
227 DisplayError("Failed to locate root directory!");
231 D(fprintf(stderr
, "[Bootstrap] Opening configuration file %s\n", config
));
232 file
= fopen(config
, "r");
235 DisplayError("Failed to load configuration file %s!", config
);
239 /* Parse the configuration file */
240 while (fgets(buf
, sizeof(buf
), file
)) {
241 char *c
= strchr(buf
, '\r');
244 c
= strchr(buf
, '\n');
248 c
= GetConfigArg(buf
, "module");
254 /* Command line argument overrides this */
256 c
= GetConfigArg(buf
, "memory");
263 c
= GetConfigArg(buf
, "logfile");
269 DisplayError("Failed to redirect debug output to %s", c
);
272 fprintf(stderr
, "----\n"); /* Separation marker */
275 c
= GetConfigArg(buf
, "arguments");
278 /* If we already have some arguments, append our line to them */
281 char *parts
[] = {KernelArgs
, c
};
282 char *args
= join_string(2, parts
);
292 /* Otherwise just copy the line */
297 KernelArgs
= malloc(i
);
298 memcpy(KernelArgs
, c
, i
);
305 D(fprintf(stderr
, "[Bootstrap] Allocating %iMB of RAM for AROS\n",memSize
));
307 #if (__WORDSIZE == 64)
308 if ((memSize
<< 20) > LOWMEMSIZE
)
310 MemoryMap
[1].len
= (memSize
<< 20) - LOWMEMSIZE
;
311 MemoryMap
[1].addr
= (IPTR
)AllocateRAM((size_t)MemoryMap
[1].len
);
312 if (!MemoryMap
[1].addr
) {
314 DisplayError("[Bootstrap] Failed to allocate %iMB of 'High' RAM for AROS: %08x %s\n", memSize
, err
, strerror(err
));
317 fprintf(stderr
, "[Bootstrap] RAM memory block allocated: %p - %p (%llu bytes)\n",
318 (void *)(IPTR
)MemoryMap
[1].addr
, (void *)(IPTR
)MemoryMap
[1].addr
+ MemoryMap
[1].len
, (unsigned long long)MemoryMap
[1].len
);
320 memSize
= (LOWMEMSIZE
>> 20);
321 km
[7].ti_Data
+= sizeof(struct mb_mmap
);
324 MemoryMap
[0].len
= memSize
<< 20;
325 MemoryMap
[0].addr
= (IPTR
)AllocateRAM32((size_t)MemoryMap
[0].len
);
327 if (!MemoryMap
[0].addr
) {
329 DisplayError("[Bootstrap] Failed to allocate %iMB of RAM for AROS: %08x %s\n", memSize
, err
, strerror(err
));
332 fprintf(stderr
, "[Bootstrap] RAM memory block allocated: %p - %p (",
333 (void *)(IPTR
)MemoryMap
[0].addr
, (void *)(IPTR
)MemoryMap
[0].addr
+ MemoryMap
[0].len
);
334 #if (__WORDSIZE == 64)
335 fprintf(stderr
, "%llu bytes)\n", (unsigned long long)MemoryMap
[0].len
);
337 fprintf(stderr
, "%u bytes)\n", MemoryMap
[0].len
);
340 if (!GetKernelSize(FirstELF
, &ro_size
, &rw_size
, &bss_size
))
343 ro_addr
= AllocateRO(ro_size
);
344 D(fprintf(stderr
, "[Bootstrap] Kickstart ROM area: %p\n", ro_addr
));
347 DisplayError("Failed to allocate %u bytes for the kickstart!", ro_size
);
351 rw_addr
= AllocateRW(rw_size
);
352 D(fprintf(stderr
, "[Bootstrap] Kickstart data area: %p\n", rw_addr
));
355 DisplayError("Failed to allocate %u bytes for the kickstart!", rw_size
);
359 __bss_track
= AllocateRO(bss_size
);
360 D(fprintf(stderr
, "[Bootstrap] Kickstart BSS array: %p\n", __bss_track
));
363 DisplayError("Failed to allocate %u bytes for the kickstart!", bss_size
);
367 if (!LoadKernel(FirstELF
, ro_addr
, rw_addr
, __bss_track
, (uintptr_t)&SysBase
, NULL
, &kernel_entry
, &Debug_KickList
))
370 D(fprintf(stderr
, "[Bootstrap] Read-only %p - %p, Read-write %p - %p, Entry %p, Debug info %p\n",
371 ro_addr
, ro_addr
+ ro_size
- 1, rw_addr
, rw_addr
+ rw_size
- 1, kernel_entry
, Debug_KickList
));
375 D(fprintf(stderr
, "[Bootstrap] Sealing kernel code memory\n"));
376 if (SetRO(ro_addr
, ro_size
))
378 DisplayError("Failed to set kernel memory permissions");
383 km
[0].ti_Data
= (IPTR
)ro_addr
;
384 km
[1].ti_Data
= (IPTR
)ro_addr
+ ro_size
- 1;
385 km
[2].ti_Data
= (IPTR
)__bss_track
;
386 km
[3].ti_Data
= (IPTR
)SystemVersion
;
387 km
[4].ti_Data
= (IPTR
)Debug_KickList
;
388 km
[5].ti_Data
= (IPTR
)HostIFace
;
389 km
[6].ti_Data
= (IPTR
)&MemoryMap
;
390 /* km[7] is statically filled in */
392 km
[8].ti_Data
= (IPTR
)KernelArgs
;
394 km
[8].ti_Tag
= TAG_DONE
;
396 /* Flush instruction cache */
397 __clear_cache((char *)ro_addr
, (char *)ro_addr
+ ro_size
);
400 /* This is a quickly hacked up sanity test which was used during iOS port development */
404 fprintf(stderr
, "[Bootstrap] Dumping %u bytes of code at %p\n", ro_size
, ro_addr
);
405 for (i
= 0; i
< ro_size
;)
408 fprintf(stderr
, "%p ", ro_addr
+ i
);
409 fprintf(stderr
, "%02X ", ((unsigned char *)ro_addr
)[i
++]);
411 fprintf(stderr
, "\n");
413 fprintf(stderr
, "\n");
416 i
= kick(kernel_entry
, km
);