xref: /haiku/src/system/boot/platform/efi/start.cpp (revision 02354704729d38c3b078c696adc1bbbd33cbcf72)
1 /*
2  * Copyright 2014-2016 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 static void
75 convert_preloaded_image(preloaded_elf64_image* image)
76 {
77 	fix_address(image->next);
78 	fix_address(image->name);
79 	fix_address(image->debug_string_table);
80 	fix_address(image->syms);
81 	fix_address(image->rel);
82 	fix_address(image->rela);
83 	fix_address(image->pltrel);
84 	fix_address(image->debug_symbols);
85 }
86 
87 
88 /*!	Convert all addresses in kernel_args to 64-bit addresses. */
89 static void
90 convert_kernel_args()
91 {
92 	if (gKernelArgs.kernel_image->elf_class != ELFCLASS64)
93 		return;
94 
95 	fix_address(gKernelArgs.boot_volume);
96 	fix_address(gKernelArgs.vesa_modes);
97 	fix_address(gKernelArgs.edid_info);
98 	fix_address(gKernelArgs.debug_output);
99 	fix_address(gKernelArgs.boot_splash);
100 	#if defined(__x86_64__) || defined(__x86__)
101 	fix_address(gKernelArgs.ucode_data);
102 	fix_address(gKernelArgs.arch_args.apic);
103 	fix_address(gKernelArgs.arch_args.hpet);
104 	#endif
105 
106 	convert_preloaded_image(static_cast<preloaded_elf64_image*>(
107 		gKernelArgs.kernel_image.Pointer()));
108 	fix_address(gKernelArgs.kernel_image);
109 
110 	// Iterate over the preloaded images. Must save the next address before
111 	// converting, as the next pointer will be converted.
112 	preloaded_image* image = gKernelArgs.preloaded_images;
113 	fix_address(gKernelArgs.preloaded_images);
114 	while (image != NULL) {
115 		preloaded_image* next = image->next;
116 		convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
117 		image = next;
118 	}
119 
120 	// Fix driver settings files.
121 	driver_settings_file* file = gKernelArgs.driver_settings;
122 	fix_address(gKernelArgs.driver_settings);
123 	while (file != NULL) {
124 		driver_settings_file* next = file->next;
125 		fix_address(file->next);
126 		fix_address(file->buffer);
127 		file = next;
128 	}
129 }
130 
131 
132 static addr_t
133 get_kernel_entry(void)
134 {
135 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
136 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
137 			gKernelArgs.kernel_image.Pointer());
138 		return image->elf_header.e_entry;
139 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
140 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
141 			gKernelArgs.kernel_image.Pointer());
142 		return image->elf_header.e_entry;
143 	}
144 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
145 	return 0;
146 }
147 
148 
149 static void
150 get_kernel_regions(addr_range& text, addr_range& data)
151 {
152 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
153 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
154 			gKernelArgs.kernel_image.Pointer());
155 		text.start = image->text_region.start;
156 		text.size = image->text_region.size;
157 		data.start = image->data_region.start;
158 		data.size = image->data_region.size;
159 		return;
160 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
161 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
162 			gKernelArgs.kernel_image.Pointer());
163 		text.start = image->text_region.start;
164 		text.size = image->text_region.size;
165 		data.start = image->data_region.start;
166 		data.size = image->data_region.size;
167 		return;
168 	}
169 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
170 }
171 
172 
173 extern "C" void
174 platform_start_kernel(void)
175 {
176 	smp_init_other_cpus();
177 #ifdef _BOOT_FDT_SUPPORT
178 	dtb_set_kernel_args();
179 #endif
180 
181 	addr_t kernelEntry = get_kernel_entry();
182 
183 	addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0};
184 	get_kernel_regions(textRegion, dataRegion);
185 	dprintf("kernel:\n");
186 	dprintf("  text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size);
187 	dprintf("  data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size);
188 	dprintf("  entry: %#lx\n", kernelEntry);
189 
190 	debug_cleanup();
191 
192 	arch_mmu_init();
193 	convert_kernel_args();
194 
195 	// map in a kernel stack
196 	void *stack_address = NULL;
197 	if (platform_allocate_region(&stack_address,
198 		KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
199 		!= B_OK) {
200 		panic("Unabled to allocate a stack");
201 	}
202 	gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
203 	gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
204 		+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
205 	dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start);
206 
207 	// Apply any weird EFI quirks
208 	quirks_init();
209 
210 	// Begin architecture-centric kernel entry.
211 	arch_start_kernel(kernelEntry);
212 
213 	panic("Shouldn't get here!");
214 }
215 
216 
217 extern "C" void
218 platform_exit(void)
219 {
220 	kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
221 	return;
222 }
223 
224 
225 /**
226  * efi_main - The entry point for the EFI application
227  * @image: firmware-allocated handle that identifies the image
228  * @systemTable: EFI system table
229  */
230 extern "C" efi_status
231 efi_main(efi_handle image, efi_system_table *systemTable)
232 {
233 	stage2_args args;
234 
235 	memset(&args, 0, sizeof(stage2_args));
236 
237 	kImage = image;
238 	kSystemTable = systemTable;
239 	kBootServices = systemTable->BootServices;
240 	kRuntimeServices = systemTable->RuntimeServices;
241 
242 	call_ctors();
243 
244 	console_init();
245 	serial_init();
246 	serial_enable();
247 
248 	sBootOptions = console_check_boot_keys();
249 
250 	// disable apm in case we ever load a 32-bit kernel...
251 	gKernelArgs.platform_args.apm.version = 0;
252 
253 	cpu_init();
254 	acpi_init();
255 #ifdef _BOOT_FDT_SUPPORT
256 	dtb_init();
257 #endif
258 	timer_init();
259 	smp_init();
260 
261 	main(&args);
262 
263 	return EFI_SUCCESS;
264 }
265