1 /* 2 * Copyright 2003-2010, Axel Dörfler, axeld@pinc-software.de. 3 * Copyright 2011, Alexander von Gluck, kallisti5@unixzen.com 4 * Copyright 2019, Adrien Destugues, pulkomandy@pulkomandy.tk 5 * Distributed under the terms of the MIT License. 6 */ 7 8 9 #include "start.h" 10 11 #include <string.h> 12 13 #include <OS.h> 14 15 #include <boot/platform.h> 16 #include <boot/stage2.h> 17 #include <boot/heap.h> 18 #include <platform/openfirmware/openfirmware.h> 19 #include <platform_arch.h> 20 21 #include "console.h" 22 #include "machine.h" 23 #include "real_time_clock.h" 24 25 26 #define HEAP_SIZE (512 * 1024) 27 28 29 // GCC defined globals 30 extern void (*__ctor_list)(void); 31 extern void (*__ctor_end)(void); 32 33 uint32 gMachine; 34 static uint32 sBootOptions; 35 36 37 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 addr_t 49 get_kernel_entry(void) 50 { 51 if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) { 52 preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>( 53 gKernelArgs.kernel_image.Pointer()); 54 return image->elf_header.e_entry; 55 } else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) { 56 preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>( 57 gKernelArgs.kernel_image.Pointer()); 58 return image->elf_header.e_entry; 59 } 60 panic("Unknown kernel format! Not 32-bit or 64-bit!"); 61 return 0; 62 } 63 64 65 extern "C" void 66 platform_start_kernel(void) 67 { 68 addr_t kernelEntry = get_kernel_entry(); 69 addr_t stackTop = gKernelArgs.cpu_kstack[0].start 70 + gKernelArgs.cpu_kstack[0].size; 71 72 printf("kernel entry at %p\n", (void*)kernelEntry); 73 printf("kernel stack top: %p\n", (void*)stackTop); 74 75 /* TODO: ? 76 mmu_init_for_kernel(); 77 smp_boot_other_cpus(); 78 */ 79 80 status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop); 81 82 panic("Kernel returned! Return value: %" B_PRId32 "\n", error); 83 } 84 85 86 extern "C" void 87 platform_exit(void) 88 { 89 of_interpret("reset-all", 0, 0); 90 } 91 92 93 extern "C" uint32 94 platform_boot_options(void) 95 { 96 return sBootOptions; 97 } 98 99 100 extern "C" void 101 start(void *openFirmwareEntry) 102 { 103 static char bootargs[512]; 104 105 // stage2 args - might be set via the command line one day 106 stage2_args args; 107 args.heap_size = HEAP_SIZE; 108 args.arguments = NULL; 109 110 if (of_init((intptr_t (*)(void*))openFirmwareEntry) != B_OK) 111 return; 112 113 // check for arguments 114 if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs)) 115 != OF_FAILED) { 116 static const char *sArgs[] = { NULL, NULL }; 117 sArgs[0] = (const char *)bootargs; 118 args.arguments = sArgs; 119 args.arguments_count = 1; 120 } 121 122 determine_machine(); 123 if (console_init() != B_OK) 124 return; 125 126 #ifdef __powerpc__ 127 if ((gMachine & MACHINE_QEMU) != 0) 128 dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n"); 129 else if ((gMachine & MACHINE_PEGASOS) != 0) 130 dprintf("Pegasos PowerPC machine detected\n"); 131 else 132 dprintf("Apple PowerPC machine assumed\n"); 133 #endif 134 135 // Initialize and take over MMU and set the OpenFirmware callbacks - it 136 // will ask us for memory after that instead of maintaining it itself 137 // (the kernel will need to adjust the callback later on as well) 138 arch_mmu_init(); 139 140 if (boot_arch_cpu_init() != B_OK) 141 of_exit(); 142 143 init_real_time_clock(); 144 145 // check for key presses once 146 sBootOptions = 0; 147 int key = console_check_for_key(); 148 if (key == 32) { 149 // space bar: option menu 150 sBootOptions |= BOOT_OPTION_MENU; 151 } else if (key == 27) { 152 // ESC: debug output 153 sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT; 154 } 155 156 gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry; 157 158 main(&args); 159 // if everything goes fine, main() never returns 160 161 of_exit(); 162 } 163