xref: /haiku/src/system/boot/platform/openfirmware/start.cpp (revision 4c8e85b316c35a9161f5a1c50ad70bc91c83a76f)
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