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