xref: /haiku/src/system/boot/platform/efi/start.cpp (revision 9e25244c5e9051f6cd333820d6332397361abd6c)
1 /*
2  * Copyright 2014-2021 Haiku, Inc. All rights reserved.
3  * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
4  * Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
5  * All rights reserved.
6  * Distributed under the terms of the MIT License.
7  */
8 
9 
10 #include <string.h>
11 
12 #include <KernelExport.h>
13 
14 #include <arch/cpu.h>
15 #include <arch_cpu_defs.h>
16 #include <kernel.h>
17 
18 #include <boot/kernel_args.h>
19 #include <boot/platform.h>
20 #include <boot/stage2.h>
21 #include <boot/stdio.h>
22 
23 #include "arch_mmu.h"
24 #include "arch_start.h"
25 #include "acpi.h"
26 #include "console.h"
27 #include "cpu.h"
28 #include "debug.h"
29 #ifdef _BOOT_FDT_SUPPORT
30 #include "dtb.h"
31 #endif
32 #include "efi_platform.h"
33 #include "mmu.h"
34 #include "quirks.h"
35 #include "serial.h"
36 #include "smp.h"
37 #include "timer.h"
38 
39 
40 extern void (*__ctor_list)(void);
41 extern void (*__ctor_end)(void);
42 
43 
44 const efi_system_table		*kSystemTable;
45 const efi_boot_services		*kBootServices;
46 const efi_runtime_services	*kRuntimeServices;
47 efi_handle kImage;
48 
49 
50 static uint32 sBootOptions;
51 
52 extern "C" int main(stage2_args *args);
53 extern "C" void _start(void);
54 extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
55 
56 
57 static void
58 call_ctors(void)
59 {
60 	void (**f)(void);
61 
62 	for (f = &__ctor_list; f < &__ctor_end; f++)
63 		(**f)();
64 }
65 
66 
67 extern "C" uint32
68 platform_boot_options()
69 {
70 	return sBootOptions;
71 }
72 
73 
74 template<class T> static void
75 convert_preloaded_image(preloaded_image* _image)
76 {
77 	T* image = static_cast<T*>(_image);
78 	fix_address(image->next);
79 	fix_address(image->name);
80 	fix_address(image->debug_string_table);
81 	fix_address(image->syms);
82 	fix_address(image->rel);
83 	fix_address(image->rela);
84 	fix_address(image->pltrel);
85 	fix_address(image->debug_symbols);
86 }
87 
88 
89 /*!	Convert all addresses in kernel_args to virtual addresses. */
90 static void
91 convert_kernel_args()
92 {
93 	fix_address(gKernelArgs.boot_volume);
94 	fix_address(gKernelArgs.vesa_modes);
95 	fix_address(gKernelArgs.edid_info);
96 	fix_address(gKernelArgs.debug_output);
97 	fix_address(gKernelArgs.boot_splash);
98 
99 	arch_convert_kernel_args();
100 
101 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
102 		convert_preloaded_image<preloaded_elf64_image>(gKernelArgs.kernel_image);
103 	} else {
104 		convert_preloaded_image<preloaded_elf32_image>(gKernelArgs.kernel_image);
105 	}
106 	fix_address(gKernelArgs.kernel_image);
107 
108 	// Iterate over the preloaded images. Must save the next address before
109 	// converting, as the next pointer will be converted.
110 	preloaded_image* image = gKernelArgs.preloaded_images;
111 	fix_address(gKernelArgs.preloaded_images);
112 	while (image != NULL) {
113 		preloaded_image* next = image->next;
114 		if (image->elf_class == ELFCLASS64) {
115 			convert_preloaded_image<preloaded_elf64_image>(image);
116 		} else {
117 			convert_preloaded_image<preloaded_elf32_image>(image);
118 		}
119 		image = next;
120 	}
121 
122 	// Fix driver settings files.
123 	driver_settings_file* file = gKernelArgs.driver_settings;
124 	fix_address(gKernelArgs.driver_settings);
125 	while (file != NULL) {
126 		driver_settings_file* next = file->next;
127 		fix_address(file->next);
128 		fix_address(file->buffer);
129 		file = next;
130 	}
131 }
132 
133 
134 static addr_t
135 get_kernel_entry(void)
136 {
137 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
138 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
139 			gKernelArgs.kernel_image.Pointer());
140 		return image->elf_header.e_entry;
141 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
142 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
143 			gKernelArgs.kernel_image.Pointer());
144 		return image->elf_header.e_entry;
145 	}
146 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
147 	return 0;
148 }
149 
150 
151 static void
152 get_kernel_regions(addr_range& text, addr_range& data)
153 {
154 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
155 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
156 			gKernelArgs.kernel_image.Pointer());
157 		text.start = image->text_region.start;
158 		text.size = image->text_region.size;
159 		data.start = image->data_region.start;
160 		data.size = image->data_region.size;
161 		return;
162 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
163 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
164 			gKernelArgs.kernel_image.Pointer());
165 		text.start = image->text_region.start;
166 		text.size = image->text_region.size;
167 		data.start = image->data_region.start;
168 		data.size = image->data_region.size;
169 		return;
170 	}
171 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
172 }
173 
174 
175 extern "C" void
176 platform_start_kernel(void)
177 {
178 	smp_init_other_cpus();
179 #ifdef _BOOT_FDT_SUPPORT
180 	dtb_set_kernel_args();
181 #endif
182 
183 	addr_t kernelEntry = get_kernel_entry();
184 
185 	addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0};
186 	get_kernel_regions(textRegion, dataRegion);
187 	dprintf("kernel:\n");
188 	dprintf("  text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size);
189 	dprintf("  data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size);
190 	dprintf("  entry: %#lx\n", kernelEntry);
191 
192 	debug_cleanup();
193 
194 	arch_mmu_init();
195 	convert_kernel_args();
196 
197 	// map in a kernel stack
198 	void *stack_address = NULL;
199 	if (platform_allocate_region(&stack_address,
200 		KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
201 		!= B_OK) {
202 		panic("Unabled to allocate a stack");
203 	}
204 	gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
205 	gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
206 		+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
207 	dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start);
208 
209 	// Apply any weird EFI quirks
210 	quirks_init();
211 
212 	// Begin architecture-centric kernel entry.
213 	arch_start_kernel(kernelEntry);
214 
215 	panic("Shouldn't get here!");
216 }
217 
218 
219 extern "C" void
220 platform_exit(void)
221 {
222 	kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
223 	return;
224 }
225 
226 
227 /**
228  * efi_main - The entry point for the EFI application
229  * @image: firmware-allocated handle that identifies the image
230  * @systemTable: EFI system table
231  */
232 extern "C" efi_status
233 efi_main(efi_handle image, efi_system_table *systemTable)
234 {
235 	stage2_args args;
236 
237 	memset(&args, 0, sizeof(stage2_args));
238 
239 	kImage = image;
240 	kSystemTable = systemTable;
241 	kBootServices = systemTable->BootServices;
242 	kRuntimeServices = systemTable->RuntimeServices;
243 
244 	call_ctors();
245 
246 	console_init();
247 	serial_init();
248 	serial_enable();
249 
250 	sBootOptions = console_check_boot_keys();
251 
252 	// disable apm in case we ever load a 32-bit kernel...
253 	gKernelArgs.platform_args.apm.version = 0;
254 
255 	cpu_init();
256 	acpi_init();
257 #ifdef _BOOT_FDT_SUPPORT
258 	dtb_init();
259 #endif
260 	timer_init();
261 	smp_init();
262 
263 	main(&args);
264 
265 	return EFI_SUCCESS;
266 }
267