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 preloaded_elf32_image* image = static_cast<preloaded_elf32_image*>( 99 gKernelArgs.kernel_image.Pointer()); 100 101 addr_t kernelEntry = image->elf_header.e_entry; 102 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 103 + gKernelArgs.cpu_kstack[0].size; 104 105 printf("kernel entry at %p\n", (void*)kernelEntry); 106 printf("kernel stack top: %p\n", (void*)stackTop); 107 108 /* TODO: ? 109 mmu_init_for_kernel(); 110 smp_boot_other_cpus(); 111 */ 112 113 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 114 115 panic("Kernel returned! Return value: %ld\n", error); 116 } 117 118 119 extern "C" void 120 platform_exit(void) 121 { 122 of_interpret("reset-all", 0, 0); 123 } 124 125 126 extern "C" uint32 127 platform_boot_options(void) 128 { 129 return sBootOptions; 130 } 131 132 133 extern "C" void 134 _start(uint32 _unused1, uint32 _unused3, void *openFirmwareEntry) 135 { 136 // According to the PowerPC bindings, OpenFirmware should have created 137 // a stack of 32kB or higher for us at this point 138 139 clear_bss(); 140 call_ctors(); 141 // call C++ constructors before doing anything else 142 143 start(openFirmwareEntry); 144 } 145 146 147 extern "C" void 148 start(void *openFirmwareEntry) 149 { 150 char bootargs[512]; 151 152 // stage2 args - might be set via the command line one day 153 stage2_args args; 154 args.heap_size = HEAP_SIZE; 155 args.arguments = NULL; 156 157 of_init((int (*)(void*))openFirmwareEntry); 158 159 // check for arguments 160 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) 161 != OF_FAILED) { 162 static const char *sArgs[] = { NULL, NULL }; 163 sArgs[0] = (const char *)bootargs; 164 args.arguments = sArgs; 165 args.arguments_count = 1; 166 } 167 168 determine_machine(); 169 console_init(); 170 171 if ((gMachine & MACHINE_QEMU) != 0) 172 dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); 173 else if ((gMachine & MACHINE_PEGASOS) != 0) 174 dprintf("Pegasos PowerPC machine detected\n"); 175 else 176 dprintf("Apple PowerPC machine assumed\n"); 177 178 // Initialize and take over MMU and set the OpenFirmware callbacks - it 179 // will ask us for memory after that instead of maintaining it itself 180 // (the kernel will need to adjust the callback later on as well) 181 arch_mmu_init(); 182 183 if (boot_arch_cpu_init() != B_OK) 184 of_exit(); 185 186 if (init_real_time_clock() != B_OK) 187 of_exit(); 188 189 // check for key presses once 190 sBootOptions = 0; 191 int key = console_check_for_key(); 192 if (key == 32) { 193 // space bar: option menu 194 sBootOptions |= BOOT_OPTION_MENU; 195 } else if (key == 27) { 196 // ESC: debug output 197 sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; 198 } 199 200 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 201 202 main(&args); 203 // if everything goes fine, main() never returns 204 205 of_exit(); 206 } 207