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