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 22 #include <string.h> 23 24 extern "C" { 25 #include <fdt.h> 26 #include <libfdt.h> 27 #include <libfdt_env.h> 28 }; 29 30 31 #define HEAP_SIZE (128 * 1024) 32 33 34 typedef struct uboot_gd { 35 // those are the only few members that we can trust 36 // others depend on compile-time config 37 struct board_data *bd; 38 uint32 flags; 39 uint32 baudrate; 40 // those are ARM-only 41 uint32 have_console; 42 uint32 reloc_off; 43 uint32 env_addr; 44 uint32 env_valid; 45 uint32 fb_base; 46 } uboot_gd; 47 48 49 // GCC defined globals 50 extern void (*__ctor_list)(void); 51 extern void (*__ctor_end)(void); 52 extern uint8 __bss_start; 53 extern uint8 _end; 54 55 extern "C" int main(stage2_args *args); 56 extern "C" void _start(void); 57 extern "C" int start_raw(int argc, const char **argv); 58 extern "C" void dump_uimage(struct image_header *image); 59 extern "C" void dump_fdt(const void *fdt); 60 61 // declared in shell.S 62 // those are initialized to NULL but not in the BSS 63 extern struct image_header *gUImage; 64 extern uboot_gd *gUBootGlobalData; 65 extern uint32 gUBootOS; 66 extern void *gFDT; 67 68 static uint32 sBootOptions; 69 70 71 static void 72 clear_bss(void) 73 { 74 memset(&__bss_start, 0, &_end - &__bss_start); 75 } 76 77 78 static void 79 call_ctors(void) 80 { 81 void (**f)(void); 82 83 for (f = &__ctor_list; f < &__ctor_end; f++) { 84 (**f)(); 85 } 86 } 87 88 89 /* needed for libgcc unwind XXX */ 90 extern "C" void 91 abort(void) 92 { 93 panic("abort"); 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 // smp_init_other_cpus(); 108 serial_cleanup(); 109 mmu_init_for_kernel(); 110 // smp_boot_other_cpus(); 111 112 dprintf("kernel entry at %lx\n", kernelEntry); 113 114 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, 115 stackTop); 116 117 panic("kernel returned!\n"); 118 } 119 120 121 extern "C" void 122 platform_exit(void) 123 { 124 } 125 126 127 extern "C" int 128 start_netbsd(struct board_info *bd, struct image_header *image, 129 const char *consdev, const char *cmdline) 130 { 131 const char *argv[] = { "haiku", cmdline }; 132 int argc = 1; 133 if (cmdline) 134 argc++; 135 gUImage = image; 136 return start_raw(argc, argv); 137 } 138 139 140 extern "C" int 141 start_linux(int argc, int archnum, void *atags) 142 { 143 return 1; 144 } 145 146 147 extern "C" int 148 start_linux_ppc_old(void */*board_info*/, 149 void */*initrd_start*/, void */*initrd_end*/, 150 const char */*cmdline_start*/, const char */*cmdline_end*/) 151 { 152 return 1; 153 } 154 155 156 extern "C" int 157 start_linux_ppc_fdt(void *fdt, long/*UNUSED*/, long/*UNUSED*/, 158 uint32 epapr_magic, uint32 initial_mem_size) 159 { 160 gFDT = fdt; //XXX: make a copy? 161 return start_raw(0, NULL); 162 } 163 164 165 extern "C" int 166 start_raw(int argc, const char **argv) 167 { 168 stage2_args args; 169 170 clear_bss(); 171 // call C++ constructors before doing anything else 172 call_ctors(); 173 args.heap_size = HEAP_SIZE; 174 args.arguments = NULL; 175 args.platform.boot_tgz_data = NULL; 176 args.platform.boot_tgz_size = 0; 177 args.platform.fdt_data = NULL; 178 args.platform.fdt_size = 0; 179 180 // if we get passed a uimage, try to find the third blob only if we do not have FDT data yet 181 if (gUImage != NULL 182 && !gFDT 183 && image_multi_getimg(gUImage, 2, 184 (uint32*)&args.platform.fdt_data, 185 &args.platform.fdt_size)) { 186 // found a blob, assume it is FDT data, when working on a platform 187 // which does not have an FDT enabled U-Boot 188 gFDT = args.platform.fdt_data; 189 } 190 191 serial_init(gFDT); 192 console_init(); 193 cpu_init(); 194 195 if (args.platform.fdt_data) { 196 dprintf("Found FDT from uimage @ %p, %" B_PRIu32 " bytes\n", 197 args.platform.fdt_data, args.platform.fdt_size); 198 } else if (gFDT) { 199 /* Fixup args so we can pass the gFDT on to the kernel */ 200 args.platform.fdt_data = gFDT; 201 args.platform.fdt_size = fdt_totalsize(gFDT); 202 } 203 204 // if we get passed an FDT, check /chosen for initrd 205 if (gFDT != NULL) { 206 int node = fdt_path_offset(gFDT, "/chosen"); 207 const void *prop; 208 int len; 209 phys_addr_t initrd_start = 0, initrd_end = 0; 210 211 if (node >= 0) { 212 prop = fdt_getprop(gFDT, node, "linux,initrd-start", &len); 213 if (prop && len == 4) 214 initrd_start = fdt32_to_cpu(*(uint32_t *)prop); 215 prop = fdt_getprop(gFDT, node, "linux,initrd-end", &len); 216 if (prop && len == 4) 217 initrd_end = fdt32_to_cpu(*(uint32_t *)prop); 218 if (initrd_end > initrd_start) { 219 args.platform.boot_tgz_data = (void *)initrd_start; 220 args.platform.boot_tgz_size = initrd_end - initrd_start; 221 dprintf("Found boot tgz from FDT @ %p, %" B_PRIu32 " bytes\n", 222 args.platform.boot_tgz_data, args.platform.boot_tgz_size); 223 } 224 } 225 } 226 227 // if we get passed a uimage, try to find the second blob 228 if (gUImage != NULL 229 && image_multi_getimg(gUImage, 1, 230 (uint32*)&args.platform.boot_tgz_data, 231 &args.platform.boot_tgz_size)) { 232 dprintf("Found boot tgz from uimage @ %p, %" B_PRIu32 " bytes\n", 233 args.platform.boot_tgz_data, args.platform.boot_tgz_size); 234 } 235 236 { //DEBUG: 237 int i; 238 dprintf("argc = %d\n", argc); 239 for (i = 0; i < argc; i++) 240 dprintf("argv[%d] @%lx = '%s'\n", i, (uint32)argv[i], argv[i]); 241 dprintf("os: %d\n", (int)gUBootOS); 242 dprintf("gd @ %p\n", gUBootGlobalData); 243 if (gUBootGlobalData) 244 dprintf("gd->bd @ %p\n", gUBootGlobalData->bd); 245 //dprintf("fb_base %p\n", (void*)gUBootGlobalData->fb_base); 246 if (gUImage) 247 dump_uimage(gUImage); 248 if (gFDT) 249 dump_fdt(gFDT); 250 } 251 252 mmu_init(); 253 254 // wait a bit to give the user the opportunity to press a key 255 // spin(750000); 256 257 // reading the keyboard doesn't seem to work in graphics mode 258 // (maybe a bochs problem) 259 // sBootOptions = check_for_boot_keys(); 260 //if (sBootOptions & BOOT_OPTION_DEBUG_OUTPUT) 261 serial_enable(); 262 263 main(&args); 264 return 0; 265 } 266 267 268 extern "C" uint32 269 platform_boot_options(void) 270 { 271 return sBootOptions; 272 } 273