1 /* 2 * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 */ 5 6 7 #include "serial.h" 8 #include "console.h" 9 #include "cpu.h" 10 #include "fdt_support.h" 11 #include "mmu.h" 12 #include "smp.h" 13 #include "uimage.h" 14 #include "keyboard.h" 15 16 #include <KernelExport.h> 17 #include <boot/platform.h> 18 #include <boot/heap.h> 19 #include <boot/stage2.h> 20 #include <arch/cpu.h> 21 #include <platform_arch.h> 22 #include <platform/openfirmware/openfirmware.h> 23 #include <board_config.h> 24 25 #include <string.h> 26 27 extern "C" { 28 #include <fdt.h> 29 #include <libfdt.h> 30 #include <libfdt_env.h> 31 }; 32 33 34 #define HEAP_SIZE (128 * 1024) 35 36 37 typedef struct uboot_gd { 38 // those are the only few members that we can trust 39 // others depend on compile-time config 40 struct board_data *bd; 41 uint32 flags; 42 uint32 baudrate; 43 // those are ARM-only 44 uint32 have_console; 45 uint32 reloc_off; 46 uint32 env_addr; 47 uint32 env_valid; 48 uint32 fb_base; 49 } uboot_gd; 50 51 52 // GCC defined globals 53 extern void (*__ctor_list)(void); 54 extern void (*__ctor_end)(void); 55 extern uint8 __bss_start, __bss_end; 56 extern uint8 _end; 57 58 extern "C" int main(stage2_args *args); 59 extern "C" void _start(void); 60 extern "C" int start_gen(int argc, const char **argv, 61 struct image_header *uimage=NULL, void *fdt=NULL); 62 extern "C" void dump_uimage(struct image_header *image); 63 #if defined(__ARM__) 64 extern "C" status_t arch_mailbox_init(); 65 #endif 66 67 68 // declared in shell.S 69 // those are initialized to NULL but not in the BSS 70 extern uboot_gd *gUBootGlobalData; 71 extern uint32 gUBootOS; 72 73 struct image_header *gUImage; 74 void *gFDT; 75 76 static uint32 sBootOptions; 77 78 79 static void 80 clear_bss(void) 81 { 82 memset(&__bss_start, 0, &__bss_end - &__bss_start); 83 } 84 85 86 static void 87 call_ctors(void) 88 { 89 void (**f)(void); 90 91 for (f = &__ctor_list; f < &__ctor_end; f++) { 92 (**f)(); 93 } 94 } 95 96 97 extern "C" void 98 platform_start_kernel(void) 99 { 100 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 101 gKernelArgs.kernel_image.Pointer()); 102 103 addr_t kernelEntry = image->elf_header.e_entry; 104 addr_t stackTop 105 = gKernelArgs.cpu_kstack[0].start + gKernelArgs.cpu_kstack[0].size; 106 107 // clone the Flattened Device Tree blob into the kernel args if we've got it 108 if (gFDT) { 109 size_t fdtSize = fdt_totalsize(gFDT); 110 gKernelArgs.platform_args.fdt = kernel_args_malloc(fdtSize); 111 memcpy(gKernelArgs.platform_args.fdt, gFDT, fdtSize); 112 } 113 114 // smp_init_other_cpus(); 115 serial_cleanup(); 116 mmu_init_for_kernel(); 117 // smp_boot_other_cpus(); 118 119 dprintf("kernel entry at %lx\n", kernelEntry); 120 121 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, 122 stackTop); 123 124 panic("kernel returned %lx!\n", error); 125 } 126 127 128 extern "C" void 129 platform_exit(void) 130 { 131 } 132 133 134 extern "C" int 135 start_netbsd(struct board_info *bd, struct image_header *image, 136 const char *consdev, const char *cmdline) 137 { 138 const char *argv[] = { "haiku", cmdline }; 139 int argc = 1; 140 if (cmdline && *cmdline) 141 argc++; 142 return start_gen(argc, argv, image); 143 } 144 145 146 extern "C" int 147 start_linux(int argc, int archnum, void *atags) 148 { 149 // newer U-Boot pass the FDT in atags 150 return start_gen(0, NULL, NULL, atags); 151 } 152 153 154 extern "C" int 155 start_linux_ppc_old(void */*board_info*/, 156 void */*initrd_start*/, void */*initrd_end*/, 157 const char */*cmdline_start*/, const char */*cmdline_end*/) 158 { 159 return 1; 160 } 161 162 163 extern "C" int 164 start_linux_ppc_fdt(void *fdt, long/*UNUSED*/, long/*UNUSED*/, 165 uint32 epapr_magic, uint32 initial_mem_size) 166 { 167 return start_gen(0, NULL, NULL, fdt); 168 } 169 170 171 extern "C" int 172 start_raw(int argc, const char **argv) 173 { 174 return start_gen(argc, argv); 175 } 176 177 178 extern "C" int 179 start_gen(int argc, const char **argv, struct image_header *uimage, void *fdt) 180 { 181 stage2_args args; 182 183 clear_bss(); 184 // call C++ constructors before doing anything else 185 call_ctors(); 186 args.heap_size = HEAP_SIZE; 187 args.arguments = NULL; 188 args.arguments_count = 0; 189 args.platform.boot_tgz_data = NULL; 190 args.platform.boot_tgz_size = 0; 191 args.platform.fdt_data = NULL; 192 args.platform.fdt_size = 0; 193 194 gUImage = uimage; 195 gFDT = fdt; //XXX: make a copy? 196 // TODO: check for atags instead and convert them 197 198 if (argv) { 199 // skip the kernel name 200 ++argv; 201 --argc; 202 } 203 // TODO: Ensure cmdline is mapped into memory by MMU before usage. 204 205 // if we get passed a uimage, try to find the third blob 206 // only if we do not have FDT data yet 207 if (gUImage != NULL 208 && !gFDT 209 && image_multi_getimg(gUImage, 2, 210 (uint32*)&args.platform.fdt_data, 211 &args.platform.fdt_size)) { 212 // found a blob, assume it is FDT data, when working on a platform 213 // which does not have an FDT enabled U-Boot 214 gFDT = args.platform.fdt_data; 215 } 216 217 // We have to cpu_init *before* calling FDT functions 218 cpu_init(); 219 220 serial_init(gFDT); 221 222 #if defined(__ARM__) 223 arch_mailbox_init(); 224 #endif 225 226 // initialize the OpenFirmware wrapper 227 of_init(NULL); 228 229 console_init(); 230 231 // if we get passed an FDT, check /chosen for initrd and bootargs 232 if (gFDT != NULL) { 233 int node = fdt_path_offset(gFDT, "/chosen"); 234 const void *prop; 235 int len; 236 phys_addr_t initrd_start = 0, initrd_end = 0; 237 238 if (node >= 0) { 239 prop = fdt_getprop(gFDT, node, "linux,initrd-start", &len); 240 if (prop && len == 4) 241 initrd_start = fdt32_to_cpu(*(uint32_t *)prop); 242 prop = fdt_getprop(gFDT, node, "linux,initrd-end", &len); 243 if (prop && len == 4) 244 initrd_end = fdt32_to_cpu(*(uint32_t *)prop); 245 if (initrd_end > initrd_start) { 246 args.platform.boot_tgz_data = (void *)initrd_start; 247 args.platform.boot_tgz_size = initrd_end - initrd_start; 248 dprintf("Found boot tgz from FDT @ %p, %" B_PRIu32 " bytes\n", 249 args.platform.boot_tgz_data, args.platform.boot_tgz_size); 250 } 251 // we check for bootargs after remapping the FDT 252 } 253 } 254 255 // if we get passed a uimage, try to find the second blob 256 if (gUImage != NULL 257 && image_multi_getimg(gUImage, 1, 258 (uint32*)&args.platform.boot_tgz_data, 259 &args.platform.boot_tgz_size)) { 260 dprintf("Found boot tgz from uimage @ %p, %" B_PRIu32 " bytes\n", 261 args.platform.boot_tgz_data, args.platform.boot_tgz_size); 262 } 263 264 { //DEBUG: 265 int i; 266 dprintf("argc = %d\n", argc); 267 for (i = 0; i < argc; i++) 268 dprintf("argv[%d] @%lx = '%s'\n", i, (uint32)argv[i], argv[i]); 269 dprintf("os: %d\n", (int)gUBootOS); 270 dprintf("gd @ %p\n", gUBootGlobalData); 271 if (gUBootGlobalData) { 272 dprintf("gd->bd @ %p\n", gUBootGlobalData->bd); 273 dprintf("gd->fb_base @ %p\n", (void*)gUBootGlobalData->fb_base); 274 } 275 if (gUImage) 276 dump_uimage(gUImage); 277 if (gFDT) 278 dump_fdt(gFDT); 279 } 280 281 if (args.platform.boot_tgz_size > 0) { 282 insert_physical_allocated_range((addr_t)args.platform.boot_tgz_data, 283 args.platform.boot_tgz_size); 284 } 285 286 // save the size of the FDT so we can map it easily after mmu_init 287 size_t fdtSize = gFDT ? fdt_totalsize(gFDT) : 0; 288 dprintf("fdtSize: 0x%" B_PRIxSIZE "\n", fdtSize); 289 290 mmu_init(); 291 292 // Handle our tarFS post-mmu 293 if (args.platform.boot_tgz_size > 0) { 294 args.platform.boot_tgz_data = (void*)mmu_map_physical_memory((addr_t) 295 args.platform.boot_tgz_data, args.platform.boot_tgz_size, 296 kDefaultPageFlags); 297 } 298 // .. and our FDT 299 if (gFDT != NULL) 300 gFDT = (void*)mmu_map_physical_memory((addr_t)gFDT, fdtSize, kDefaultPageFlags); 301 302 // if we get passed an FDT, check /chosen for bootargs now 303 // to avoid having to copy them. 304 if (gFDT != NULL) { 305 int node = fdt_path_offset(gFDT, "/chosen"); 306 const void *prop; 307 int len; 308 309 if (node >= 0) { 310 prop = fdt_getprop(gFDT, node, "bootargs", &len); 311 if (prop) { 312 dprintf("Found bootargs: %s\n", (const char *)prop); 313 static const char *sArgs[] = { NULL, NULL }; 314 sArgs[0] = (const char *)prop; 315 // override main() args 316 args.arguments = sArgs; 317 args.arguments_count = 1; 318 } 319 } 320 dprintf("args.arguments_count = %" B_PRId32 "\n", args.arguments_count); 321 for (int i = 0; i < args.arguments_count; i++) 322 dprintf("args.arguments[%d] @%lx = '%s'\n", i, 323 (uint32)args.arguments[i], args.arguments[i]); 324 } 325 326 // wait a bit to give the user the opportunity to press a key 327 // spin(750000); 328 329 // reading the keyboard doesn't seem to work in graphics mode 330 // (maybe a bochs problem) 331 // sBootOptions = check_for_boot_keys(); 332 //if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT) 333 serial_enable(); 334 335 main(&args); 336 return 0; 337 } 338 339 340 extern "C" uint32 341 platform_boot_options(void) 342 { 343 return sBootOptions; 344 } 345