xref: /haiku/src/system/boot/platform/openfirmware/start.cpp (revision fc7456e9b1ec38c941134ed6d01c438cf289381e)
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 // GCC defined globals
27 extern void (*__ctor_list)(void);
28 extern void (*__ctor_end)(void);
29 
30 uint32 gMachine;
31 static uint32 sBootOptions;
32 
33 
34 void
35 call_ctors(void)
36 {
37 	void (**f)(void);
38 
39 	for (f = &__ctor_list; f < &__ctor_end; f++) {
40 		(**f)();
41 	}
42 }
43 
44 
45 static addr_t
46 get_kernel_entry(void)
47 {
48 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
49 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
50 			gKernelArgs.kernel_image.Pointer());
51 		return image->elf_header.e_entry;
52 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
53 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
54 			gKernelArgs.kernel_image.Pointer());
55 		return image->elf_header.e_entry;
56 	}
57 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
58 	return 0;
59 }
60 
61 
62 extern "C" void
63 platform_start_kernel(void)
64 {
65 	addr_t kernelEntry = get_kernel_entry();
66 	addr_t stackTop = gKernelArgs.cpu_kstack[0].start
67 		+ gKernelArgs.cpu_kstack[0].size;
68 
69 	printf("kernel entry at %p\n", (void*)kernelEntry);
70 	printf("kernel stack top: %p\n", (void*)stackTop);
71 
72 	/* TODO: ?
73 	mmu_init_for_kernel();
74 	smp_boot_other_cpus();
75 	*/
76 
77 	status_t error = arch_start_kernel(&gKernelArgs, kernelEntry, stackTop);
78 
79 	panic("Kernel returned! Return value: %" B_PRId32 "\n", error);
80 }
81 
82 
83 extern "C" void
84 platform_exit(void)
85 {
86 	of_interpret("reset-all", 0, 0);
87 }
88 
89 
90 extern "C" uint32
91 platform_boot_options(void)
92 {
93 	return sBootOptions;
94 }
95 
96 
97 extern "C" void
98 start(void *openFirmwareEntry)
99 {
100 	static char bootargs[512];
101 
102 	// stage2 args - might be set via the command line one day
103 	stage2_args args;
104 	args.heap_size = 0;
105 	args.arguments = NULL;
106 
107 	if (of_init((intptr_t (*)(void*))openFirmwareEntry) != B_OK)
108 		return;
109 
110 	// check for arguments
111 	if (of_getprop(gChosen, "bootargs", bootargs, sizeof(bootargs))
112 			!= OF_FAILED) {
113 		static const char *sArgs[] = { NULL, NULL };
114 		sArgs[0] = (const char *)bootargs;
115 		args.arguments = sArgs;
116 		args.arguments_count = 1;
117 	}
118 
119 	determine_machine();
120 	if (console_init() != B_OK)
121 		return;
122 
123 #ifdef __powerpc__
124 	if ((gMachine & MACHINE_QEMU) != 0)
125 		dprintf("OpenBIOS (QEMU?) OpenFirmware machine detected\n");
126 	else if ((gMachine & MACHINE_PEGASOS) != 0)
127 		dprintf("Pegasos PowerPC machine detected\n");
128 	else
129 		dprintf("Apple PowerPC machine assumed\n");
130 #endif
131 
132 	// Initialize and take over MMU and set the OpenFirmware callbacks - it
133 	// will ask us for memory after that instead of maintaining it itself
134 	// (the kernel will need to adjust the callback later on as well)
135 	arch_mmu_init();
136 
137 	if (boot_arch_cpu_init() != B_OK)
138 		of_exit();
139 
140 	init_real_time_clock();
141 
142 	// check for key presses once
143 	sBootOptions = 0;
144 	int key = console_check_for_key();
145 	if (key == 32) {
146 		// space bar: option menu
147 		sBootOptions |= BOOT_OPTION_MENU;
148 	} else if (key == 27) {
149 		// ESC: debug output
150 		sBootOptions |= BOOT_OPTION_DEBUG_OUTPUT;
151 	}
152 
153 	gKernelArgs.platform_args.openfirmware_entry = openFirmwareEntry;
154 
155 	main(&args);
156 		// if everything goes fine, main() never returns
157 
158 	of_exit();
159 }
160