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