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 <OS.h> 8 #include <boot/platform.h> 9 #include <boot/stage2.h> 10 #include <boot/heap.h> 11 #include <platform/openfirmware/openfirmware.h> 12 #include <platform_arch.h> 13 14 #include <string.h> 15 16 #include "console.h" 17 #include "machine.h" 18 #include "real_time_clock.h" 19 20 21 #define HEAP_SIZE 65536 22 23 24 extern "C" void _start(uint32 _unused1, uint32 _unused2, 25 void *openFirmwareEntry); 26 extern "C" void start(void *openFirmwareEntry); 27 28 // GCC defined globals 29 extern void (*__ctor_list)(void); 30 extern void (*__ctor_end)(void); 31 extern uint8 __bss_start; 32 extern uint8 _end; 33 34 uint32 gMachine; 35 36 37 static void 38 call_ctors(void) 39 { 40 void (**f)(void); 41 42 for (f = &__ctor_list; f < &__ctor_end; f++) { 43 (**f)(); 44 } 45 } 46 47 48 static void 49 clear_bss(void) 50 { 51 memset(&__bss_start, 0, &_end - &__bss_start); 52 } 53 54 55 static void 56 determine_machine(void) 57 { 58 gMachine = MACHINE_UNKNOWN; 59 60 int root = of_finddevice("/"); 61 char buffer[64]; 62 int length; 63 if ((length = of_getprop(root, "device_type", buffer, sizeof(buffer) - 1)) == OF_FAILED) 64 return; 65 buffer[length] = '\0'; 66 67 // ToDo: add more, and be as generic as possible 68 69 if (!strcasecmp("chrp", buffer)) 70 gMachine = MACHINE_CHRP; 71 else if (!strcasecmp("bootrom", buffer)) 72 gMachine = MACHINE_MAC; 73 74 if ((length = of_getprop(root, "model", buffer, sizeof(buffer) - 1)) == OF_FAILED) 75 return; 76 buffer[length] = '\0'; 77 78 if (!strcasecmp("pegasos", buffer)) 79 gMachine |= MACHINE_PEGASOS; 80 } 81 82 83 extern "C" void 84 platform_start_kernel(void) 85 { 86 addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry; 87 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 88 + gKernelArgs.cpu_kstack[0].size; 89 90 printf("kernel entry at %p\n", (void*)kernelEntry); 91 printf("kernel stack top: %p\n", (void*)stackTop); 92 93 /* TODO: ? 94 mmu_init_for_kernel(); 95 smp_boot_other_cpus(); 96 */ 97 98 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 99 100 panic("Kernel returned! Return value: %ld\n", error); 101 } 102 103 104 extern "C" void 105 platform_exit(void) 106 { 107 of_interpret("reset-all", 0, 0); 108 } 109 110 111 extern "C" uint32 112 platform_boot_options(void) 113 { 114 // ToDo: implement me! 115 return 0; 116 } 117 118 119 extern "C" void 120 _start(uint32 _unused1, uint32 _unused3, void *openFirmwareEntry) 121 { 122 // According to the PowerPC bindings, OpenFirmware should have created 123 // a stack of 32kB or higher for us at this point 124 125 clear_bss(); 126 call_ctors(); 127 // call C++ constructors before doing anything else 128 129 start(openFirmwareEntry); 130 } 131 132 133 extern "C" void 134 start(void *openFirmwareEntry) 135 { 136 char bootargs[512]; 137 138 // stage2 args - might be set via the command line one day 139 stage2_args args; 140 args.heap_size = HEAP_SIZE; 141 args.arguments = NULL; 142 143 of_init((int (*)(void*))openFirmwareEntry); 144 145 // check for arguments 146 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) != OF_FAILED) { 147 static const char *sArgs[] = { NULL, NULL }; 148 sArgs[0] = (const char *)bootargs; 149 args.arguments = sArgs; 150 } 151 152 determine_machine(); 153 console_init(); 154 155 // Initialize and take over MMU and set the OpenFirmware callbacks - it 156 // will ask us for memory after that instead of maintaining it itself 157 // (the kernel will need to adjust the callback later on as well) 158 arch_mmu_init(); 159 160 if (boot_arch_cpu_init() != B_OK) 161 of_exit(); 162 163 if (init_real_time_clock() != B_OK) 164 of_exit(); 165 166 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 167 168 main(&args); 169 // if everything goes fine, main() never returns 170 171 of_exit(); 172 } 173