17 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
23 #include <aros/kernel.h>
24 #include <aros/multiboot.h>
25 #include <exec/execbase.h>
26 #include <utility/tagitem.h>
28 #include <elfloader.h>
31 #include "bootstrap.h"
33 #include "filesystem.h"
34 #include "kickstart.h"
41 #define PATH_MAX _MAX_PATH
46 /* These macros are defined in both UNIX and AROS headers. Get rid of warnings. */
52 extern void *HostIFace
;
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)
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
")";
83 static struct TagItem km
[] =
85 {KRN_KernelLowest
, 0 },
86 {KRN_KernelHighest
, 0 },
88 {KRN_BootLoader
, 0 },
90 {KRN_HostInterface
, 0 },
91 {KRN_MMAPAddress
, 0 },
92 {KRN_MMAPLength
, sizeof(MemoryMap
)},
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
))
108 /* Skip option name */
111 /* First character must be space */
112 if (!isspace(*str
++))
114 /* Skip the rest of spaces */
121 char *join_string(int argc
, char **argv
)
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
));
133 for (j
= 0; j
< argc
; j
++) {
139 D(fprintf(stderr
, "[Bootstrap] Joined line: %s\n", str
));
144 int bootstrap(int argc
, char ** argv
)
147 unsigned int memSize
= 64;
149 char *config
= DefaultConfig
;
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"));
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!");
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"
181 " --help same as '-h'\n"
182 " --memsize <size> same as '-m <size>'\n"
183 " --config <file> same as '-c'\n"
185 "Please report bugs to the AROS development team. http://www.aros.org/\n", argv
[0], DefaultConfig
);
187 } else if (!strcmp(argv
[i
], "--memsize") || !strcmp(argv
[i
], "-m")) {
188 memSize
= atoi(argv
[++i
]);
191 } else if (!strcmp(argv
[i
], "--config") || !strcmp(argv
[i
], "-c")) {
197 D(fprintf(stderr
, "[Bootstrap] %u arguments processed\n", i
));
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!");
213 file
= file_open(config
, "r");
216 DisplayError("Failed to load configuration file %s!", config
);
220 /* Parse the configuration file */
221 while (fgets(buf
, sizeof(buf
), file
)) {
222 char *c
= strchr(buf
, '\r');
225 c
= strchr(buf
, '\n');
229 c
= GetConfigArg(buf
, "module");
235 /* Command line argument overrides this */
237 c
= GetConfigArg(buf
, "memory");
244 c
= GetConfigArg(buf
, "logfile");
250 DisplayError("Failed to redirect debug output to %s", c
);
253 fprintf(stderr
, "----\n"); /* Separation marker */
256 c
= GetConfigArg(buf
, "arguments");
259 /* If we already have some arguments, append our line to them */
262 char *parts
[] = {KernelArgs
, c
};
263 char *args
= join_string(2, parts
);
273 /* Otherwise just copy the line */
278 KernelArgs
= malloc(i
);
279 memcpy(KernelArgs
, c
, i
);
286 if (!GetKernelSize(FirstELF
, &ro_size
, &rw_size
, &bss_size
))
289 ro_addr
= AllocateRO(ro_size
);
290 D(fprintf(stderr
, "[Bootstrap] Kickstart ROM area: %p\n", ro_addr
));
293 DisplayError("Failed to allocate %u bytes for the kickstart!", ro_size
);
297 rw_addr
= AllocateRW(rw_size
);
298 D(fprintf(stderr
, "[Bootstrap] Kickstart data area: %p\n", rw_addr
));
301 DisplayError("Failed to allocate %u bytes for the kickstart!", rw_size
);
305 __bss_track
= AllocateRO(bss_size
);
306 D(fprintf(stderr
, "[Bootstrap] Kickstart BSS array: %p\n", __bss_track
));
309 DisplayError("Failed to allocate %u bytes for the kickstart!", bss_size
);
313 if (!LoadKernel(FirstELF
, ro_addr
, rw_addr
, __bss_track
, (uintptr_t)&SysBase
, NULL
, &kernel_entry
, &Debug_KickList
))
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
));
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");
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
);
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 */
349 km
[8].ti_Data
= (IPTR
)KernelArgs
;
351 km
[8].ti_Tag
= TAG_DONE
;
353 /* Flush instruction cache */
354 __clear_cache((char *)ro_addr
, (char *)ro_addr
+ ro_size
);
357 /* This is a quickly hacked up sanity test which was used during iOS port development */
361 fprintf(stderr
, "[Bootstrap] Dumping %u bytes of code at %p\n", ro_size
, ro_addr
);
362 for (i
= 0; i
< ro_size
;)
365 fprintf(stderr
, "%p ", ro_addr
+ i
);
366 fprintf(stderr
, "%02X ", ((unsigned char *)ro_addr
)[i
++]);
368 fprintf(stderr
, "\n");
370 fprintf(stderr
, "\n");
373 i
= kick(kernel_entry
, km
);