revert between 56095 -> 55830 in arch
[AROS.git] / arch / ppc-chrp / boot / openfirmware / src / bootstrap.c
blob70de7659b1a2753944ef696003ddcf15752a8687
1 /*
2 Copyright © 2008-2014, The AROS Development Team. All rights reserved.
3 $Id$
4 */
6 #define DEBUG 0
8 #include <debug.h>
9 #include <support.h>
10 #include <inttypes.h>
11 #include <of1275.h>
12 #include <menu.h>
13 #include <elf.h>
14 #include <kernel.h>
16 typedef uint32_t ti_Tag;
17 typedef intptr_t ti_Data;
19 typedef struct {uintptr_t ti_Tag; intptr_t ti_Data; } tagitem_t;
20 extern struct bss_tracker tracker[MAX_BSS_SECTIONS];
21 list_t *debug_info;
23 char *bootpath = NULL;
24 char *bootargs;
26 static void flush_cache(char *start, char *end)
28 start = (char*)((unsigned long)start & 0xffffffe0);
29 end = (char*)((unsigned long)end & 0xffffffe0);
30 char *ptr;
32 for (ptr = start; ptr < end; ptr +=32)
34 asm volatile("dcbst 0,%0"::"r"(ptr));
36 asm volatile("sync");
38 for (ptr = start; ptr < end; ptr +=32)
40 asm volatile("icbi 0,%0"::"r"(ptr));
43 asm volatile("sync; isync; ");
46 char *cmdline;
48 /* Loads either a single ELF file, or the package of elf files */
49 static int load_elf_or_package(char *name, uint8_t *base, unsigned long virt)
51 if (base[0] == 0x7f && base[1] == 'E' && base[2] == 'L' && base[3] == 'F')
53 return load_elf_file(name, base, virt);
55 else if (base[0] == 'P' && base[1] == 'K' && base[2] == 'G' && base[3] == 0x01)
57 uint8_t *file = base+4;
58 uint32_t total_length = *(uint32_t*)file; /* Total length of the module */
59 const uint8_t *file_end = base+total_length;
60 uint32_t len;
62 file = base + 8;
64 while(file < file_end)
66 const char *filename = remove_path(file+4);
68 printf("\r\n");
70 /* get text length */
71 len = *(uint32_t*)file;
72 /* display the file name */
73 printf(" %s ", filename);
75 file += len + 5;
77 /* get the ELF size */
78 len = *(uint32_t*)file;
79 file += 4;
81 /* load it */
82 if (!load_elf_file(filename, file, virt))
83 return 0;
85 /* go to the next file */
86 file += len;
88 return 1;
90 else
92 printf("UNSUPPORTED FILE");
93 /* Unknown files are just ignored, it's not a critical error */
94 return 1;
98 int bootstrap(uint32_t r3, uint32_t r4, void *r5)
100 void *rtas, *handle;
101 uint32_t rtas_size;
102 uint8_t *rtas_base=NULL, *load_base=NULL;
103 void *rtas_entry;
104 int i;
105 ofw_node_t *rootnode;
106 tagitem_t *tags;
107 int tagcnt = 0;
109 int (*kernel_phys_entry)(tagitem_t *, uint32_t) = (int (*)())KERNEL_PHYS_BASE;
110 unsigned long virt;
112 struct of_region memory_region = {NULL, 0};
114 ofw_init(r5);
116 printf("\r\nSecond Level Bootloader for OpenFirmware\r\n");
117 printf("Build %s from %s\r\n", VERSION, __DATE__);
119 // void *ih1 = ofw_open("scsi0");
120 // D(bug("%p\n", ih1));
121 // if (ih1 != (void*)0xffffffff && ih1 != (void*)0)
122 // {
123 // char buf[2048];
124 // long size;
125 // D(bug("%p\n", ofw_seek(ih1, 0, 2048)));
126 // ofw_read(ih1, buf, 2048);
127 // ofw_close(ih1);
130 // int j;
131 // for (j=0; j <128; j++)
132 // D(bug("%c", buf[j]));
133 // }
134 //return -1;
136 handle = ofw_find_device("/memory");
137 if (handle)
139 if (ofw_get_prop_len(handle, "reg") == 8)
141 ofw_get_prop(handle, "reg", &memory_region, sizeof(memory_region));
143 printf("Available memory %dMB at 0x%p\r\n", memory_region.size >> 20, memory_region.base);
147 if (!memory_region.size)
149 printf("Failed to obtain memory information\n");
150 return -1;
153 handle = ofw_find_device("/options");
155 debug_info = __claim(sizeof(list_t));
156 new_list(debug_info);
158 if (handle)
160 char str[20];
161 char *c = str;
162 int i = 0;
163 intptr_t temp = 0;
164 int base = 10;
166 D(printf("load_base proplen = %d\r\n", ofw_get_prop_len(handle, "load-base")));
168 ofw_get_prop(handle, "load-base", str, 20);
169 str[ofw_get_prop_len(handle, "load-base")] = 0;
171 if (str[0] == '0' && str[1] == 'x')
173 base = 16;
174 c += 2;
175 i += 2;
178 while (i < 20 && *c != 0)
180 temp = temp * base;
181 if (*c >= '0' && *c <= '9')
182 temp += *c - '0';
183 else if (*c >= 'A' && *c <= 'F')
184 temp += *c - 'A' + 10;
185 else if (*c >= 'a' && *c <= 'f')
186 temp += *c - 'a' + 10;
188 c++;
191 load_base = (uint8_t *)temp;
192 D(printf("Load base @ %p\r\n", load_base));
195 D(bug("Locking load-base (%p-%p) and kernel area (%p-%p)\r\n",
196 load_base, load_base + LOAD_SIZE - 1,
197 0x07000000, 0x07ffffff));
199 ofw_claim(load_base, LOAD_SIZE, 0);
200 ofw_claim((void*)0x07000000, 0x01000000, 0);
202 tags = ofw_claim(NULL, sizeof(tagitem_t) * 20, 4);
204 cmdline = ofw_claim(NULL, 10240, 4);
206 rootnode = ofw_scan_tree();
208 tags[tagcnt].ti_Tag = KRN_OpenFirmwareTree;
209 tags[tagcnt].ti_Data = (intptr_t)rootnode;
210 tagcnt++;
212 handle = ofw_find_device("/chosen");
213 bootargs = ofw_GetString(handle, "bootargs");
215 D(bug("[BOOT] bootargs='%s'\n", bootargs));
217 /* Parse owr own command line options */
218 for(;;)
220 /* Skip leading spaces */
221 while (isspace(*bootargs))
222 bootargs++;
224 if (!strncasecmp(bootargs, "--root", 6))
227 * --root command line option overrides boot path.
228 * Useful on Pegasos where /chosen/bootpath doesn't include anything
229 * beyond physical device.
231 bootpath = &bootargs[6];
233 /* Skip all spaces between keyword and value */
234 while (isspace(*bootpath))
235 bootpath++;
237 bootargs = bootpath + 1;
238 /* Now skip non-spaces. This will skip the value. */
239 while (!isspace(*bootargs))
240 bootargs++;
242 /* Separate bootpath from the rest of command line */
243 *bootargs++ = 0;
245 else
246 break;
249 if (!bootpath)
250 bootpath = ofw_GetString(handle, "bootpath");
252 D(bug("[BOOT] bootpath='%s' bootargs='%s'\n", bootpath, bootargs));
254 if (!load_menu(load_base))
256 int res = 0;
257 menu_entry_t *selection;
259 parse_menu((unsigned long)kernel_phys_entry);
260 selection = execute_menu();
262 if (selection)
264 char buff[1024];
266 printf("\r\nLoading \"%s\"\r\n", selection->m_title);
268 virt = selection->m_virtual;
270 if (selection->m_kernel)
272 /* "kernel" line is optional and obsolete */
273 sprintf(buff, "load %s %s", bootpath, selection->m_kernel);
274 printf(" %s ", selection->m_kernel);
275 ofw_interpret(buff);
276 res = load_elf_file(remove_path(selection->m_kernel), load_base, virt);
277 printf("\r\n");
280 for (i=0; i < selection->m_modules_cnt; i++)
282 printf(" %s ", selection->m_modules[i]);
283 sprintf(buff, "load %s %s", bootpath, selection->m_modules[i]);
284 if (!ofw_interpret(buff))
286 res = load_elf_or_package(remove_path(selection->m_modules[i]), load_base, virt);
288 else
290 printf(" !!LOAD ERROR!!");
291 res = 0;
293 printf("\r\n");
295 if (!res)
296 break;
299 if (!res)
301 printf("Failed to load kickstart!\r\n");
303 ofw_release(load_base, LOAD_SIZE);
304 ofw_release(rtas_base, rtas_size);
305 ofw_release((void*)0x07000000, 0x01000000 - rtas_size);
307 return -1;
310 if (selection->m_cmdline || strlen(bootargs))
312 if (selection->m_cmdline && strlen(selection->m_cmdline))
313 sprintf(cmdline, "%s %s", selection->m_cmdline, bootargs);
314 else
315 sprintf(cmdline, "%s", bootargs);
317 tags[tagcnt].ti_Tag = KRN_CmdLine;
318 tags[tagcnt].ti_Data = (intptr_t)cmdline;
319 tagcnt++;
324 rtas = ofw_find_device("/rtas");
325 if (rtas)
327 ofw_get_prop(rtas, "rtas-size", &rtas_size, sizeof(rtas_size));
328 D(bug("RTAS services node @ %p\r\n", rtas));
329 D(bug("The size of RTAS handler is %d bytes\r\n", rtas_size));
331 if (rtas_size)
333 void *ihandle;
335 rtas_size = (rtas_size + 4095) & ~4095;
337 /* adjust the ro pointer. It should be aligned at 4K boundary, just for God's sake... */
339 rtas_base = get_ptr_ro();
340 rtas_base = (uint8_t *)(((intptr_t)rtas_base + 4095) &~4095);
341 ptr_ro_add(rtas_size + (intptr_t)rtas_base - (intptr_t)get_ptr_ro());
343 rtas_base[0] = 0;
345 D(printf("RTAS services will be located at %p - %p\r\n",
346 rtas_base, rtas_base + rtas_size - 1));
348 ihandle = ofw_open("/rtas");
350 D(printf("RTAS ihandle = %p\r\n", ihandle));
352 printf("RTAS instantiate returns %d\r\n", ofw_instantiate_rtas(ihandle, rtas_base, &rtas_entry));
354 D(printf("RTAS entry point @ %p\r\n", rtas_entry));
356 ofw_close(ihandle);
358 D(printf("%d%d%d%d\r\n", rtas_base[0], rtas_base[1], rtas_base[2], rtas_base[3]));
363 ofw_node_t *tmp = (ofw_node_t *)rootnode->on_children.l_head;
365 while(tmp->on_node.n_succ)
367 if (!strcasecmp(tmp->on_name, "rtas"))
369 ofw_property_t *prop = ofw_claim(NULL, sizeof(ofw_property_t), 4);
370 prop->op_length = 4;
371 prop->op_name = "load_base";
372 prop->op_value = &rtas_base;
374 add_tail(&tmp->on_properties, &prop->op_node);
376 prop = ofw_claim(NULL, sizeof(ofw_property_t), 4);
377 prop->op_length = 4;
378 prop->op_name = "entry";
379 prop->op_value = &rtas_entry;
381 add_tail(&tmp->on_properties, &prop->op_node);
383 break;
386 tmp = (ofw_node_t *)tmp->on_node.n_succ;
389 tags[tagcnt].ti_Tag = KRN_KernelBss;
390 tags[tagcnt].ti_Data = (intptr_t)tracker;
391 tagcnt++;
393 tags[tagcnt].ti_Tag = KRN_KernelBase;
394 tags[tagcnt].ti_Data = (intptr_t)KERNEL_PHYS_BASE;
395 tagcnt++;
397 tags[tagcnt].ti_Tag = KRN_KernelLowest;
398 tags[tagcnt].ti_Data = (intptr_t)get_ptr_rw();
399 tagcnt++;
401 tags[tagcnt].ti_Tag = KRN_KernelHighest;
402 tags[tagcnt].ti_Data = (intptr_t)get_ptr_ro();
403 tagcnt++;
405 tags[tagcnt].ti_Tag = KRN_DebugInfo;
406 tags[tagcnt].ti_Data = (intptr_t)debug_info;
407 tagcnt++;
409 tags[tagcnt].ti_Tag = TAG_DONE;
410 tags[tagcnt].ti_Data = 0UL;
412 flush_cache(get_ptr_rw(), get_ptr_ro());
414 /* Jump into the JUNGLE! */
415 printf("Entering kickstart at 0x%p...\r\n", kernel_phys_entry);
416 kernel_phys_entry(tags, AROS_BOOT_MAGIC);
418 free_menu();
420 printf("!!!!!FAIL!!!!!\r\n");
421 ofw_release(load_base, LOAD_SIZE);
422 ofw_release(rtas_base, rtas_size);
423 ofw_release((void*)0x07000000, 0x01000000 - rtas_size);
425 return -1;