2 Copyright © 2008-2014, The AROS Development Team. All rights reserved.
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
];
23 char *bootpath
= NULL
;
26 static void flush_cache(char *start
, char *end
)
28 start
= (char*)((unsigned long)start
& 0xffffffe0);
29 end
= (char*)((unsigned long)end
& 0xffffffe0);
32 for (ptr
= start
; ptr
< end
; ptr
+=32)
34 asm volatile("dcbst 0,%0"::"r"(ptr
));
38 for (ptr
= start
; ptr
< end
; ptr
+=32)
40 asm volatile("icbi 0,%0"::"r"(ptr
));
43 asm volatile("sync; isync; ");
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
;
64 while(file
< file_end
)
66 const char *filename
= remove_path(file
+4);
71 len
= *(uint32_t*)file
;
72 /* display the file name */
73 printf(" %s ", filename
);
77 /* get the ELF size */
78 len
= *(uint32_t*)file
;
82 if (!load_elf_file(filename
, file
, virt
))
85 /* go to the next file */
92 printf("UNSUPPORTED FILE");
93 /* Unknown files are just ignored, it's not a critical error */
98 int bootstrap(uint32_t r3
, uint32_t r4
, void *r5
)
102 uint8_t *rtas_base
=NULL
, *load_base
=NULL
;
105 ofw_node_t
*rootnode
;
109 int (*kernel_phys_entry
)(tagitem_t
*, uint32_t) = (int (*)())KERNEL_PHYS_BASE
;
112 struct of_region memory_region
= {NULL
, 0};
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)
125 // D(bug("%p\n", ofw_seek(ih1, 0, 2048)));
126 // ofw_read(ih1, buf, 2048);
131 // for (j=0; j <128; j++)
132 // D(bug("%c", buf[j]));
136 handle
= ofw_find_device("/memory");
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");
153 handle
= ofw_find_device("/options");
155 debug_info
= __claim(sizeof(list_t
));
156 new_list(debug_info
);
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')
178 while (i
< 20 && *c
!= 0)
181 if (*c
>= '0' && *c
<= '9')
183 else if (*c
>= 'A' && *c
<= 'F')
184 temp
+= *c
- 'A' + 10;
185 else if (*c
>= 'a' && *c
<= 'f')
186 temp
+= *c
- 'a' + 10;
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
;
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 */
220 /* Skip leading spaces */
221 while (isspace(*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
))
237 bootargs
= bootpath
+ 1;
238 /* Now skip non-spaces. This will skip the value. */
239 while (!isspace(*bootargs
))
242 /* Separate bootpath from the rest of command line */
250 bootpath
= ofw_GetString(handle
, "bootpath");
252 D(bug("[BOOT] bootpath='%s' bootargs='%s'\n", bootpath
, bootargs
));
254 if (!load_menu(load_base
))
257 menu_entry_t
*selection
;
259 parse_menu((unsigned long)kernel_phys_entry
);
260 selection
= execute_menu();
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
);
276 res
= load_elf_file(remove_path(selection
->m_kernel
), load_base
, virt
);
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
);
290 printf(" !!LOAD ERROR!!");
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
);
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
);
315 sprintf(cmdline
, "%s", bootargs
);
317 tags
[tagcnt
].ti_Tag
= KRN_CmdLine
;
318 tags
[tagcnt
].ti_Data
= (intptr_t)cmdline
;
324 rtas
= ofw_find_device("/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
));
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());
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
));
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);
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);
378 prop
->op_name
= "entry";
379 prop
->op_value
= &rtas_entry
;
381 add_tail(&tmp
->on_properties
, &prop
->op_node
);
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
;
393 tags
[tagcnt
].ti_Tag
= KRN_KernelBase
;
394 tags
[tagcnt
].ti_Data
= (intptr_t)KERNEL_PHYS_BASE
;
397 tags
[tagcnt
].ti_Tag
= KRN_KernelLowest
;
398 tags
[tagcnt
].ti_Data
= (intptr_t)get_ptr_rw();
401 tags
[tagcnt
].ti_Tag
= KRN_KernelHighest
;
402 tags
[tagcnt
].ti_Data
= (intptr_t)get_ptr_ro();
405 tags
[tagcnt
].ti_Tag
= KRN_DebugInfo
;
406 tags
[tagcnt
].ti_Data
= (intptr_t)debug_info
;
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
);
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
);