1 /* 2 * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2011, Alexander von Gluck, kallisti5@unixzen.com 4 * Distributed under the terms of the MIT License. 5 */ 6 7 8 #include <string.h> 9 10 #include <OS.h> 11 12 #include <boot/platform.h> 13 #include <boot/stage2.h> 14 #include <boot/heap.h> 15 #include <platform/openfirmware/openfirmware.h> 16 #include <platform_arch.h> 17 18 #include "console.h" 19 #include "machine.h" 20 #include "real_time_clock.h" 21 22 23 #define HEAP_SIZE 65536 24 25 26 extern "C" void _start(uint32 _unused1, uint32 _unused2, 27 void *openFirmwareEntry); 28 extern "C" void start(void *openFirmwareEntry); 29 30 // GCC defined globals 31 extern void (*__ctor_list)(void); 32 extern void (*__ctor_end)(void); 33 extern uint8 __bss_start; 34 extern uint8 _end; 35 36 uint32 gMachine; 37 static uint32 sBootOptions; 38 39 40 static void 41 call_ctors(void) 42 { 43 void (**f)(void); 44 45 for (f = &__ctor_list; f < &__ctor_end; f++) { 46 (**f)(); 47 } 48 } 49 50 51 static void 52 clear_bss(void) 53 { 54 memset(&__bss_start, 0, &_end - &__bss_start); 55 } 56 57 58 static void 59 determine_machine(void) 60 { 61 gMachine = MACHINE_UNKNOWN; 62 63 int root = of_finddevice("/"); 64 char buffer[64]; 65 int length; 66 67 // TODO : Probe other OpenFirmware platforms and set gMachine as needed 68 69 if ((length = of_getprop(root, "device_type", buffer, sizeof(buffer) - 1)) 70 != OF_FAILED) { 71 buffer[length] = '\0'; 72 if (!strcasecmp("chrp", buffer)) 73 gMachine = MACHINE_CHRP; 74 else if (!strcasecmp("bootrom", buffer)) 75 gMachine = MACHINE_MAC; 76 } else 77 gMachine = MACHINE_MAC; 78 79 if ((length = of_getprop(root, "model", buffer, sizeof(buffer) - 1)) 80 != OF_FAILED) { 81 buffer[length] = '\0'; 82 if (!strcasecmp("pegasos", buffer)) 83 gMachine |= MACHINE_PEGASOS; 84 } 85 86 if ((length = of_getprop(root, "name", buffer, sizeof(buffer) - 1)) 87 != OF_FAILED) { 88 buffer[length] = '\0'; 89 if (!strcasecmp("openbiosteam,openbios", buffer)) 90 gMachine |= MACHINE_QEMU; 91 } 92 } 93 94 95 extern "C" void 96 platform_start_kernel(void) 97 { 98 addr_t kernelEntry = gKernelArgs.kernel_image.elf_header.e_entry; 99 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 100 + gKernelArgs.cpu_kstack[0].size; 101 102 printf("kernel entry at %p\n", (void*)kernelEntry); 103 printf("kernel stack top: %p\n", (void*)stackTop); 104 105 /* TODO: ? 106 mmu_init_for_kernel(); 107 smp_boot_other_cpus(); 108 */ 109 110 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 111 112 panic("Kernel returned! Return value: %ld\n", error); 113 } 114 115 116 extern "C" void 117 platform_exit(void) 118 { 119 of_interpret("reset-all", 0, 0); 120 } 121 122 123 extern "C" uint32 124 platform_boot_options(void) 125 { 126 return sBootOptions; 127 } 128 129 130 extern "C" void 131 _start(uint32 _unused1, uint32 _unused3, void *openFirmwareEntry) 132 { 133 // According to the PowerPC bindings, OpenFirmware should have created 134 // a stack of 32kB or higher for us at this point 135 136 clear_bss(); 137 call_ctors(); 138 // call C++ constructors before doing anything else 139 140 start(openFirmwareEntry); 141 } 142 143 144 extern "C" void 145 start(void *openFirmwareEntry) 146 { 147 char bootargs[512]; 148 149 // stage2 args - might be set via the command line one day 150 stage2_args args; 151 args.heap_size = HEAP_SIZE; 152 args.arguments = NULL; 153 154 of_init((int (*)(void*))openFirmwareEntry); 155 156 // check for arguments 157 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) 158 != OF_FAILED) { 159 static const char *sArgs[] = { NULL, NULL }; 160 sArgs[0] = (const char *)bootargs; 161 args.arguments = sArgs; 162 } 163 164 determine_machine(); 165 console_init(); 166 167 if ((gMachine & MACHINE_QEMU) != 0) 168 dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); 169 else if ((gMachine & MACHINE_PEGASOS) != 0) 170 dprintf("Pegasos PowerPC machine detected\n"); 171 else 172 dprintf("Apple PowerPC machine assumed\n"); 173 174 // Initialize and take over MMU and set the OpenFirmware callbacks - it 175 // will ask us for memory after that instead of maintaining it itself 176 // (the kernel will need to adjust the callback later on as well) 177 arch_mmu_init(); 178 179 if (boot_arch_cpu_init() != B_OK) 180 of_exit(); 181 182 if (init_real_time_clock() != B_OK) 183 of_exit(); 184 185 // check for key presses once 186 sBootOptions = 0; 187 int key = console_check_for_key(); 188 if (key == 32) { 189 // space bar: option menu 190 sBootOptions |= BOOT_OPTION_MENU; 191 } else if (key == 27) { 192 // ESC: debug output 193 sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; 194 } 195 196 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 197 198 main(&args); 199 // if everything goes fine, main() never returns 200 201 of_exit(); 202 } 203