xref: /haiku/src/system/boot/platform/efi/start.cpp (revision 87f4776937505e3014251c9c3434be78ae29d7d0)
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 <kernel.h>
16 
17 #include <boot/kernel_args.h>
18 #include <boot/platform.h>
19 #include <boot/stage2.h>
20 #include <boot/stdio.h>
21 
22 #include "arch_mmu.h"
23 #include "arch_start.h"
24 #include "acpi.h"
25 #include "console.h"
26 #include "cpu.h"
27 #include "dtb.h"
28 #include "efi_platform.h"
29 #include "mmu.h"
30 #include "quirks.h"
31 #include "serial.h"
32 #include "smp.h"
33 #include "timer.h"
34 
35 
36 extern void (*__ctor_list)(void);
37 extern void (*__ctor_end)(void);
38 
39 
40 const efi_system_table		*kSystemTable;
41 const efi_boot_services		*kBootServices;
42 const efi_runtime_services	*kRuntimeServices;
43 efi_handle kImage;
44 
45 
46 static uint32 sBootOptions;
47 
48 extern "C" int main(stage2_args *args);
49 extern "C" void _start(void);
50 extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
51 
52 
53 static void
54 call_ctors(void)
55 {
56 	void (**f)(void);
57 
58 	for (f = &__ctor_list; f < &__ctor_end; f++)
59 		(**f)();
60 }
61 
62 
63 extern "C" uint32
64 platform_boot_options()
65 {
66 	return sBootOptions;
67 }
68 
69 
70 static void
71 convert_preloaded_image(preloaded_elf64_image* image)
72 {
73 	fix_address(image->next);
74 	fix_address(image->name);
75 	fix_address(image->debug_string_table);
76 	fix_address(image->syms);
77 	fix_address(image->rel);
78 	fix_address(image->rela);
79 	fix_address(image->pltrel);
80 	fix_address(image->debug_symbols);
81 }
82 
83 
84 /*!	Convert all addresses in kernel_args to 64-bit addresses. */
85 static void
86 convert_kernel_args()
87 {
88 	if (gKernelArgs.kernel_image->elf_class != ELFCLASS64)
89 		return;
90 
91 	fix_address(gKernelArgs.boot_volume);
92 	fix_address(gKernelArgs.vesa_modes);
93 	fix_address(gKernelArgs.edid_info);
94 	fix_address(gKernelArgs.debug_output);
95 	fix_address(gKernelArgs.boot_splash);
96 	#if defined(__x86_64__) || defined(__x86__)
97 	fix_address(gKernelArgs.ucode_data);
98 	fix_address(gKernelArgs.arch_args.apic);
99 	fix_address(gKernelArgs.arch_args.hpet);
100 	#endif
101 
102 	convert_preloaded_image(static_cast<preloaded_elf64_image*>(
103 		gKernelArgs.kernel_image.Pointer()));
104 	fix_address(gKernelArgs.kernel_image);
105 
106 	// Iterate over the preloaded images. Must save the next address before
107 	// converting, as the next pointer will be converted.
108 	preloaded_image* image = gKernelArgs.preloaded_images;
109 	fix_address(gKernelArgs.preloaded_images);
110 	while (image != NULL) {
111 		preloaded_image* next = image->next;
112 		convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
113 		image = next;
114 	}
115 
116 	// Fix driver settings files.
117 	driver_settings_file* file = gKernelArgs.driver_settings;
118 	fix_address(gKernelArgs.driver_settings);
119 	while (file != NULL) {
120 		driver_settings_file* next = file->next;
121 		fix_address(file->next);
122 		fix_address(file->buffer);
123 		file = next;
124 	}
125 }
126 
127 
128 static addr_t
129 get_kernel_entry(void)
130 {
131 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
132 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
133 			gKernelArgs.kernel_image.Pointer());
134 		return image->elf_header.e_entry;
135 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
136 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
137 			gKernelArgs.kernel_image.Pointer());
138 		return image->elf_header.e_entry;
139 	}
140 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
141 	return 0;
142 }
143 
144 
145 extern "C" void
146 platform_start_kernel(void)
147 {
148 	smp_init_other_cpus();
149 
150 	addr_t kernelEntry = get_kernel_entry();
151 
152 	arch_mmu_init();
153 	convert_kernel_args();
154 
155 	// Save the kernel entry point address.
156 	dprintf("kernel entry at %#lx\n", kernelEntry);
157 
158 	// map in a kernel stack
159 	void *stack_address = NULL;
160 	if (platform_allocate_region(&stack_address,
161 		KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
162 		!= B_OK) {
163 		panic("Unabled to allocate a stack");
164 	}
165 	gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
166 	gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
167 		+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
168 	dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start);
169 
170 	// Apply any weird EFI quirks
171 	quirks_init();
172 
173 	// Begin architecture-centric kernel entry.
174 	arch_start_kernel(kernelEntry);
175 
176 	panic("Shouldn't get here!");
177 }
178 
179 
180 extern "C" void
181 platform_exit(void)
182 {
183 	kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
184 	return;
185 }
186 
187 
188 /**
189  * efi_main - The entry point for the EFI application
190  * @image: firmware-allocated handle that identifies the image
191  * @systemTable: EFI system table
192  */
193 extern "C" efi_status
194 efi_main(efi_handle image, efi_system_table *systemTable)
195 {
196 	stage2_args args;
197 
198 	memset(&args, 0, sizeof(stage2_args));
199 
200 	kImage = image;
201 	kSystemTable = systemTable;
202 	kBootServices = systemTable->BootServices;
203 	kRuntimeServices = systemTable->RuntimeServices;
204 
205 	call_ctors();
206 
207 	console_init();
208 	serial_init();
209 	serial_enable();
210 
211 	sBootOptions = console_check_boot_keys();
212 
213 	// disable apm in case we ever load a 32-bit kernel...
214 	gKernelArgs.platform_args.apm.version = 0;
215 
216 	cpu_init();
217 	acpi_init();
218 	dtb_init();
219 	timer_init();
220 	smp_init();
221 
222 	main(&args);
223 
224 	return EFI_SUCCESS;
225 }
226