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