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. */
60 extern void *HostIFace
;
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] =
76 static struct mb_mmap MemoryMap
[2] =
80 sizeof(struct mb_mmap
) - 4,
83 #if (__WORDSIZE != 64)
89 #if (__WORDSIZE == 64)
91 sizeof(struct mb_mmap
) - 4,
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
")";
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
)},
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
))
130 /* Skip option name */
133 /* First character must be space */
134 if (!isspace(*str
++))
136 /* Skip the rest of spaces */
143 char *join_string(int argc
, char **argv
)
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
));
155 for (j
= 0; j
< argc
; j
++) {
161 D(fprintf(stderr
, "[Bootstrap] Joined line: %s\n", str
));
166 int bootstrap(int argc
, char ** argv
)
169 unsigned int memSize
= 64;
171 char *config
= DefaultConfig
;
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!");
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"
201 " --help same as '-h'\n"
202 " --memsize <size> same as '-m <size>'\n"
203 " --config <file> same as '-c'\n"
205 "Please report bugs to the AROS development team. http://www.aros.org/\n", argv
[0], DefaultConfig
);
207 } else if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m")) {
208 memSize
= atoi(argv
[++i
]);
211 } else if (!strcmp(argv
[i
], "--config") || !strcmp(argv
[i
], "-c")) {
217 D(fprintf(stderr
, "[Bootstrap] %u argument%s processed\n", i
, i
==1 ? "" : "s"));
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!");
233 D(fprintf(stderr
, "[Bootstrap] Opening configuration file %s\n", config
));
234 file
= fopen(config
, "r");
237 DisplayError("Failed to load configuration file %s!", config
);
241 /* Parse the configuration file */
242 while (fgets(buf
, sizeof(buf
), file
)) {
243 char *c
= strchr(buf
, '\r');
246 c
= strchr(buf
, '\n');
250 c
= GetConfigArg(buf
, "module");
256 /* Command line argument overrides this */
258 c
= GetConfigArg(buf
, "memory");
265 c
= GetConfigArg(buf
, "logfile");
271 DisplayError("Failed to redirect debug output to %s", c
);
274 fprintf(stderr
, "----\n"); /* Separation marker */
277 c
= GetConfigArg(buf
, "arguments");
280 /* If we already have some arguments, append our line to them */
283 char *parts
[] = {KernelArgs
, c
};
284 char *args
= join_string(2, parts
);
294 /* Otherwise just copy the line */
299 KernelArgs
= malloc(i
);
300 memcpy(KernelArgs
, c
, i
);
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
) {
316 DisplayError("[Bootstrap] Failed to allocate %iMB of 'High' RAM for AROS: %08x %s\n", memSize
, err
, strerror(err
));
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
);
326 MemoryMap
[0].len
= memSize
<< 20;
327 MemoryMap
[0].addr
= (IPTR
)AllocateRAM32((size_t)MemoryMap
[0].len
);
329 if (!MemoryMap
[0].addr
) {
331 DisplayError("[Bootstrap] Failed to allocate %iMB of RAM for AROS: %08x %s\n", memSize
, err
, strerror(err
));
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
))
340 ro_addr
= AllocateRO(ro_size
);
341 D(fprintf(stderr
, "[Bootstrap] Kickstart ROM area: %p\n", ro_addr
));
344 DisplayError("Failed to allocate %u bytes for the kickstart!", ro_size
);
348 rw_addr
= AllocateRW(rw_size
);
349 D(fprintf(stderr
, "[Bootstrap] Kickstart data area: %p\n", rw_addr
));
352 DisplayError("Failed to allocate %u bytes for the kickstart!", rw_size
);
356 __bss_track
= AllocateRO(bss_size
);
357 D(fprintf(stderr
, "[Bootstrap] Kickstart BSS array: %p\n", __bss_track
));
360 DisplayError("Failed to allocate %u bytes for the kickstart!", bss_size
);
364 if (!LoadKernel(FirstELF
, ro_addr
, rw_addr
, __bss_track
, (uintptr_t)&SysBase
, NULL
, &kernel_entry
, &Debug_KickList
))
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
));
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");
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 */
389 km
[8].ti_Data
= (IPTR
)KernelArgs
;
391 km
[8].ti_Tag
= TAG_DONE
;
393 /* Flush instruction cache */
394 __clear_cache((char *)ro_addr
, (char *)ro_addr
+ ro_size
);
397 /* This is a quickly hacked up sanity test which was used during iOS port development */
401 fprintf(stderr
, "[Bootstrap] Dumping %u bytes of code at %p\n", ro_size
, ro_addr
);
402 for (i
= 0; i
< ro_size
;)
405 fprintf(stderr
, "%p ", ro_addr
+ i
);
406 fprintf(stderr
, "%02X ", ((unsigned char *)ro_addr
)[i
++]);
408 fprintf(stderr
, "\n");
410 fprintf(stderr
, "\n");
413 i
= kick(kernel_entry
, km
);