xref: /haiku/src/system/boot/platform/efi/start.cpp (revision 10bba152b3d5d0f55621871ab7660aab0877cdfc)
1735f1daeSFredrik Holmqvist /*
2af90bfd3SDavid Karoly  * Copyright 2014-2021 Haiku, Inc. All rights reserved.
3b3215a62SHenry Harrington  * Copyright 2013-2014, Fredrik Holmqvist, fredrik.holmqvist@gmail.com.
4b3215a62SHenry Harrington  * Copyright 2014, Henry Harrington, henry.harrington@gmail.com.
5b3215a62SHenry Harrington  * All rights reserved.
647a21c5cSAugustin Cavalier  * Distributed under the terms of the MIT License.
7735f1daeSFredrik Holmqvist  */
8735f1daeSFredrik Holmqvist 
9735f1daeSFredrik Holmqvist 
10b3215a62SHenry Harrington #include <string.h>
11b3215a62SHenry Harrington 
12b3215a62SHenry Harrington #include <KernelExport.h>
13b3215a62SHenry Harrington 
14b3215a62SHenry Harrington #include <arch/cpu.h>
15f1fa58bfSX512 #include <arch_cpu_defs.h>
167b4d924fSAndrej Antunovikj #include <kernel.h>
177b4d924fSAndrej Antunovikj 
186e6efaecSJessica Hamilton #include <boot/kernel_args.h>
19e2e1558aSJessica Hamilton #include <boot/platform.h>
20e2e1558aSJessica Hamilton #include <boot/stage2.h>
21e2e1558aSJessica Hamilton #include <boot/stdio.h>
22735f1daeSFredrik Holmqvist 
2371680f7bSAlexander von Gluck IV #include "arch_mmu.h"
2404f1baa7SAlexander von Gluck IV #include "arch_start.h"
256e6efaecSJessica Hamilton #include "acpi.h"
26735f1daeSFredrik Holmqvist #include "console.h"
27d2986cb6SAlexander von Gluck IV #include "cpu.h"
284d1c5907SAugustin Cavalier #include "debug.h"
29f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
30569564c0SAlexander von Gluck IV #include "dtb.h"
31f1fa58bfSX512 #endif
32735f1daeSFredrik Holmqvist #include "efi_platform.h"
33b3215a62SHenry Harrington #include "mmu.h"
34d38ba84dSAlexander von Gluck IV #include "quirks.h"
359e487d8dSFredrik Holmqvist #include "serial.h"
36a99a0c00SNick Smallbone #include "smp.h"
37b482adb1SAlexander von Gluck IV #include "timer.h"
38735f1daeSFredrik Holmqvist 
39735f1daeSFredrik Holmqvist 
40735f1daeSFredrik Holmqvist extern void (*__ctor_list)(void);
41735f1daeSFredrik Holmqvist extern void (*__ctor_end)(void);
42735f1daeSFredrik Holmqvist 
43735f1daeSFredrik Holmqvist 
44485b5cf8SAlexander von Gluck IV const efi_system_table		*kSystemTable;
45485b5cf8SAlexander von Gluck IV const efi_boot_services		*kBootServices;
46485b5cf8SAlexander von Gluck IV const efi_runtime_services	*kRuntimeServices;
47485b5cf8SAlexander von Gluck IV efi_handle kImage;
48b3215a62SHenry Harrington 
49735f1daeSFredrik Holmqvist 
5096f4d68bSJessica Hamilton static uint32 sBootOptions;
51b3215a62SHenry Harrington 
52b3215a62SHenry Harrington extern "C" int main(stage2_args *args);
53b3215a62SHenry Harrington extern "C" void _start(void);
54b3215a62SHenry Harrington extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
5596f4d68bSJessica Hamilton 
56735f1daeSFredrik Holmqvist 
57735f1daeSFredrik Holmqvist static void
call_ctors(void)58735f1daeSFredrik Holmqvist call_ctors(void)
59735f1daeSFredrik Holmqvist {
60735f1daeSFredrik Holmqvist 	void (**f)(void);
61735f1daeSFredrik Holmqvist 
62735f1daeSFredrik Holmqvist 	for (f = &__ctor_list; f < &__ctor_end; f++)
63735f1daeSFredrik Holmqvist 		(**f)();
64735f1daeSFredrik Holmqvist }
65735f1daeSFredrik Holmqvist 
66735f1daeSFredrik Holmqvist 
67e2e1558aSJessica Hamilton extern "C" uint32
platform_boot_options()68e2e1558aSJessica Hamilton platform_boot_options()
69e2e1558aSJessica Hamilton {
7096f4d68bSJessica Hamilton 	return sBootOptions;
71e2e1558aSJessica Hamilton }
72e2e1558aSJessica Hamilton 
73e2e1558aSJessica Hamilton 
74*18e885dbSDavid Karoly template<class T> static void
convert_preloaded_image(preloaded_image * _image)75*18e885dbSDavid Karoly convert_preloaded_image(preloaded_image* _image)
76b3215a62SHenry Harrington {
77*18e885dbSDavid Karoly 	T* image = static_cast<T*>(_image);
78b3215a62SHenry Harrington 	fix_address(image->next);
79b3215a62SHenry Harrington 	fix_address(image->name);
80b3215a62SHenry Harrington 	fix_address(image->debug_string_table);
81b3215a62SHenry Harrington 	fix_address(image->syms);
82b3215a62SHenry Harrington 	fix_address(image->rel);
83b3215a62SHenry Harrington 	fix_address(image->rela);
84b3215a62SHenry Harrington 	fix_address(image->pltrel);
85b3215a62SHenry Harrington 	fix_address(image->debug_symbols);
86b3215a62SHenry Harrington }
87b3215a62SHenry Harrington 
88b3215a62SHenry Harrington 
89*18e885dbSDavid Karoly /*!	Convert all addresses in kernel_args to virtual addresses. */
90b3215a62SHenry Harrington static void
convert_kernel_args()91b3215a62SHenry Harrington convert_kernel_args()
92b3215a62SHenry Harrington {
93b3215a62SHenry Harrington 	fix_address(gKernelArgs.boot_volume);
94b3215a62SHenry Harrington 	fix_address(gKernelArgs.vesa_modes);
95b3215a62SHenry Harrington 	fix_address(gKernelArgs.edid_info);
96b3215a62SHenry Harrington 	fix_address(gKernelArgs.debug_output);
97b3215a62SHenry Harrington 	fix_address(gKernelArgs.boot_splash);
98af90bfd3SDavid Karoly 
99af90bfd3SDavid Karoly 	arch_convert_kernel_args();
100b3215a62SHenry Harrington 
101*18e885dbSDavid Karoly 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
102*18e885dbSDavid Karoly 		convert_preloaded_image<preloaded_elf64_image>(gKernelArgs.kernel_image);
103*18e885dbSDavid Karoly 	} else {
104*18e885dbSDavid Karoly 		convert_preloaded_image<preloaded_elf32_image>(gKernelArgs.kernel_image);
105*18e885dbSDavid Karoly 	}
106b3215a62SHenry Harrington 	fix_address(gKernelArgs.kernel_image);
107b3215a62SHenry Harrington 
108b3215a62SHenry Harrington 	// Iterate over the preloaded images. Must save the next address before
109b3215a62SHenry Harrington 	// converting, as the next pointer will be converted.
110b3215a62SHenry Harrington 	preloaded_image* image = gKernelArgs.preloaded_images;
111b3215a62SHenry Harrington 	fix_address(gKernelArgs.preloaded_images);
112b3215a62SHenry Harrington 	while (image != NULL) {
113b3215a62SHenry Harrington 		preloaded_image* next = image->next;
114*18e885dbSDavid Karoly 		if (image->elf_class == ELFCLASS64) {
115*18e885dbSDavid Karoly 			convert_preloaded_image<preloaded_elf64_image>(image);
116*18e885dbSDavid Karoly 		} else {
117*18e885dbSDavid Karoly 			convert_preloaded_image<preloaded_elf32_image>(image);
118*18e885dbSDavid Karoly 		}
119b3215a62SHenry Harrington 		image = next;
120b3215a62SHenry Harrington 	}
121b3215a62SHenry Harrington 
122b3215a62SHenry Harrington 	// Fix driver settings files.
123b3215a62SHenry Harrington 	driver_settings_file* file = gKernelArgs.driver_settings;
124b3215a62SHenry Harrington 	fix_address(gKernelArgs.driver_settings);
125b3215a62SHenry Harrington 	while (file != NULL) {
126b3215a62SHenry Harrington 		driver_settings_file* next = file->next;
127b3215a62SHenry Harrington 		fix_address(file->next);
128b3215a62SHenry Harrington 		fix_address(file->buffer);
129b3215a62SHenry Harrington 		file = next;
130b3215a62SHenry Harrington 	}
131b3215a62SHenry Harrington }
132b3215a62SHenry Harrington 
133b3215a62SHenry Harrington 
134312ace56SAlexander von Gluck IV static addr_t
get_kernel_entry(void)135312ace56SAlexander von Gluck IV get_kernel_entry(void)
136312ace56SAlexander von Gluck IV {
137312ace56SAlexander von Gluck IV 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
138312ace56SAlexander von Gluck IV 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
139312ace56SAlexander von Gluck IV 			gKernelArgs.kernel_image.Pointer());
140312ace56SAlexander von Gluck IV 		return image->elf_header.e_entry;
141312ace56SAlexander von Gluck IV 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
142312ace56SAlexander von Gluck IV 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
143312ace56SAlexander von Gluck IV 			gKernelArgs.kernel_image.Pointer());
144312ace56SAlexander von Gluck IV 		return image->elf_header.e_entry;
145312ace56SAlexander von Gluck IV 	}
146312ace56SAlexander von Gluck IV 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
147312ace56SAlexander von Gluck IV 	return 0;
148312ace56SAlexander von Gluck IV }
149312ace56SAlexander von Gluck IV 
150312ace56SAlexander von Gluck IV 
151f1fa58bfSX512 static void
get_kernel_regions(addr_range & text,addr_range & data)152f1fa58bfSX512 get_kernel_regions(addr_range& text, addr_range& data)
153f1fa58bfSX512 {
154f1fa58bfSX512 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
155f1fa58bfSX512 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
156f1fa58bfSX512 			gKernelArgs.kernel_image.Pointer());
157f1fa58bfSX512 		text.start = image->text_region.start;
158f1fa58bfSX512 		text.size = image->text_region.size;
159f1fa58bfSX512 		data.start = image->data_region.start;
160f1fa58bfSX512 		data.size = image->data_region.size;
161f1fa58bfSX512 		return;
162f1fa58bfSX512 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
163f1fa58bfSX512 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
164f1fa58bfSX512 			gKernelArgs.kernel_image.Pointer());
165f1fa58bfSX512 		text.start = image->text_region.start;
166f1fa58bfSX512 		text.size = image->text_region.size;
167f1fa58bfSX512 		data.start = image->data_region.start;
168f1fa58bfSX512 		data.size = image->data_region.size;
169f1fa58bfSX512 		return;
170f1fa58bfSX512 	}
171f1fa58bfSX512 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
172f1fa58bfSX512 }
173f1fa58bfSX512 
174f1fa58bfSX512 
175e2e1558aSJessica Hamilton extern "C" void
platform_start_kernel(void)176e2e1558aSJessica Hamilton platform_start_kernel(void)
177e2e1558aSJessica Hamilton {
178a99a0c00SNick Smallbone 	smp_init_other_cpus();
179f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
180cd9b0eedSHan Pengfei 	dtb_set_kernel_args();
181f1fa58bfSX512 #endif
182ec239abcSJessica Hamilton 
183312ace56SAlexander von Gluck IV 	addr_t kernelEntry = get_kernel_entry();
184b3215a62SHenry Harrington 
185f1fa58bfSX512 	addr_range textRegion = {.start = 0, .size = 0}, dataRegion = {.start = 0, .size = 0};
186f1fa58bfSX512 	get_kernel_regions(textRegion, dataRegion);
187f1fa58bfSX512 	dprintf("kernel:\n");
188f1fa58bfSX512 	dprintf("  text: %#" B_PRIx64 ", %#" B_PRIx64 "\n", textRegion.start, textRegion.size);
189f1fa58bfSX512 	dprintf("  data: %#" B_PRIx64 ", %#" B_PRIx64 "\n", dataRegion.start, dataRegion.size);
190f1fa58bfSX512 	dprintf("  entry: %#lx\n", kernelEntry);
191f1fa58bfSX512 
1924d1c5907SAugustin Cavalier 	debug_cleanup();
1934d1c5907SAugustin Cavalier 
1947c32619cSAlexander von Gluck IV 	arch_mmu_init();
195b3215a62SHenry Harrington 	convert_kernel_args();
196b3215a62SHenry Harrington 
197b3215a62SHenry Harrington 	// map in a kernel stack
198b3215a62SHenry Harrington 	void *stack_address = NULL;
199485b5cf8SAlexander von Gluck IV 	if (platform_allocate_region(&stack_address,
200485b5cf8SAlexander von Gluck IV 		KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
201485b5cf8SAlexander von Gluck IV 		!= B_OK) {
202b3215a62SHenry Harrington 		panic("Unabled to allocate a stack");
203b3215a62SHenry Harrington 	}
20405586741SAlexander von Gluck IV 	gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
205485b5cf8SAlexander von Gluck IV 	gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
206485b5cf8SAlexander von Gluck IV 		+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
207f1fa58bfSX512 	dprintf("Kernel stack at %#" B_PRIx64 "\n", gKernelArgs.cpu_kstack[0].start);
208b3215a62SHenry Harrington 
209d38ba84dSAlexander von Gluck IV 	// Apply any weird EFI quirks
210d38ba84dSAlexander von Gluck IV 	quirks_init();
211d38ba84dSAlexander von Gluck IV 
21204f1baa7SAlexander von Gluck IV 	// Begin architecture-centric kernel entry.
21304f1baa7SAlexander von Gluck IV 	arch_start_kernel(kernelEntry);
214b3215a62SHenry Harrington 
21504f1baa7SAlexander von Gluck IV 	panic("Shouldn't get here!");
216e2e1558aSJessica Hamilton }
217e2e1558aSJessica Hamilton 
218e2e1558aSJessica Hamilton 
219e2e1558aSJessica Hamilton extern "C" void
platform_exit(void)220e2e1558aSJessica Hamilton platform_exit(void)
221e2e1558aSJessica Hamilton {
2226df09499Sbeaglejoe 	kRuntimeServices->ResetSystem(EfiResetCold, EFI_SUCCESS, 0, NULL);
223e2e1558aSJessica Hamilton 	return;
224e2e1558aSJessica Hamilton }
225e2e1558aSJessica Hamilton 
226e2e1558aSJessica Hamilton 
227735f1daeSFredrik Holmqvist /**
228735f1daeSFredrik Holmqvist  * efi_main - The entry point for the EFI application
229735f1daeSFredrik Holmqvist  * @image: firmware-allocated handle that identifies the image
230735f1daeSFredrik Holmqvist  * @systemTable: EFI system table
231735f1daeSFredrik Holmqvist  */
232485b5cf8SAlexander von Gluck IV extern "C" efi_status
efi_main(efi_handle image,efi_system_table * systemTable)233485b5cf8SAlexander von Gluck IV efi_main(efi_handle image, efi_system_table *systemTable)
234735f1daeSFredrik Holmqvist {
235e2e1558aSJessica Hamilton 	stage2_args args;
236b3215a62SHenry Harrington 	memset(&args, 0, sizeof(stage2_args));
237b3215a62SHenry Harrington 
238b3215a62SHenry Harrington 	kImage = image;
239735f1daeSFredrik Holmqvist 	kSystemTable = systemTable;
240735f1daeSFredrik Holmqvist 	kBootServices = systemTable->BootServices;
241735f1daeSFredrik Holmqvist 	kRuntimeServices = systemTable->RuntimeServices;
242735f1daeSFredrik Holmqvist 
243735f1daeSFredrik Holmqvist 	call_ctors();
244735f1daeSFredrik Holmqvist 
245735f1daeSFredrik Holmqvist 	console_init();
2469e487d8dSFredrik Holmqvist 	serial_init();
2479e487d8dSFredrik Holmqvist 	serial_enable();
248735f1daeSFredrik Holmqvist 
24996f4d68bSJessica Hamilton 	sBootOptions = console_check_boot_keys();
25096f4d68bSJessica Hamilton 
251b3215a62SHenry Harrington 	// disable apm in case we ever load a 32-bit kernel...
252b3215a62SHenry Harrington 	gKernelArgs.platform_args.apm.version = 0;
2536e6efaecSJessica Hamilton 
25486b12d85SJessica Hamilton 	cpu_init();
25586b12d85SJessica Hamilton 	acpi_init();
256f1fa58bfSX512 #ifdef _BOOT_FDT_SUPPORT
257569564c0SAlexander von Gluck IV 	dtb_init();
258f1fa58bfSX512 #endif
259b482adb1SAlexander von Gluck IV 	timer_init();
26086b12d85SJessica Hamilton 	smp_init();
26186b12d85SJessica Hamilton 
262e2e1558aSJessica Hamilton 	main(&args);
263735f1daeSFredrik Holmqvist 
264735f1daeSFredrik Holmqvist 	return EFI_SUCCESS;
265735f1daeSFredrik Holmqvist }
266