xref: /haiku/src/system/boot/platform/efi/start.cpp (revision 569564c02d75ecabeee1e413bff893691b2367d5)
1735f1daeSFredrik Holmqvist /*
2735f1daeSFredrik Holmqvist  * Copyright 2014-2016 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>
157b4d924fSAndrej Antunovikj #include <kernel.h>
167b4d924fSAndrej Antunovikj 
176e6efaecSJessica Hamilton #include <boot/kernel_args.h>
18e2e1558aSJessica Hamilton #include <boot/platform.h>
19e2e1558aSJessica Hamilton #include <boot/stage2.h>
20e2e1558aSJessica Hamilton #include <boot/stdio.h>
21735f1daeSFredrik Holmqvist 
2271680f7bSAlexander von Gluck IV #include "arch_mmu.h"
2304f1baa7SAlexander von Gluck IV #include "arch_start.h"
246e6efaecSJessica Hamilton #include "acpi.h"
25735f1daeSFredrik Holmqvist #include "console.h"
26d2986cb6SAlexander von Gluck IV #include "cpu.h"
27*569564c0SAlexander von Gluck IV #include "dtb.h"
28735f1daeSFredrik Holmqvist #include "efi_platform.h"
29b3215a62SHenry Harrington #include "mmu.h"
30d38ba84dSAlexander von Gluck IV #include "quirks.h"
319e487d8dSFredrik Holmqvist #include "serial.h"
32a99a0c00SNick Smallbone #include "smp.h"
33b482adb1SAlexander von Gluck IV #include "timer.h"
34735f1daeSFredrik Holmqvist 
35735f1daeSFredrik Holmqvist 
36735f1daeSFredrik Holmqvist extern void (*__ctor_list)(void);
37735f1daeSFredrik Holmqvist extern void (*__ctor_end)(void);
38735f1daeSFredrik Holmqvist 
39735f1daeSFredrik Holmqvist 
40485b5cf8SAlexander von Gluck IV const efi_system_table		*kSystemTable;
41485b5cf8SAlexander von Gluck IV const efi_boot_services		*kBootServices;
42485b5cf8SAlexander von Gluck IV const efi_runtime_services	*kRuntimeServices;
43485b5cf8SAlexander von Gluck IV efi_handle kImage;
44b3215a62SHenry Harrington 
45735f1daeSFredrik Holmqvist 
4696f4d68bSJessica Hamilton static uint32 sBootOptions;
47b3215a62SHenry Harrington 
48b3215a62SHenry Harrington extern "C" int main(stage2_args *args);
49b3215a62SHenry Harrington extern "C" void _start(void);
50b3215a62SHenry Harrington extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
5196f4d68bSJessica Hamilton 
52735f1daeSFredrik Holmqvist 
53735f1daeSFredrik Holmqvist static void
54735f1daeSFredrik Holmqvist call_ctors(void)
55735f1daeSFredrik Holmqvist {
56735f1daeSFredrik Holmqvist 	void (**f)(void);
57735f1daeSFredrik Holmqvist 
58735f1daeSFredrik Holmqvist 	for (f = &__ctor_list; f < &__ctor_end; f++)
59735f1daeSFredrik Holmqvist 		(**f)();
60735f1daeSFredrik Holmqvist }
61735f1daeSFredrik Holmqvist 
62735f1daeSFredrik Holmqvist 
63e2e1558aSJessica Hamilton extern "C" uint32
64e2e1558aSJessica Hamilton platform_boot_options()
65e2e1558aSJessica Hamilton {
6696f4d68bSJessica Hamilton 	return sBootOptions;
67e2e1558aSJessica Hamilton }
68e2e1558aSJessica Hamilton 
69e2e1558aSJessica Hamilton 
70b3215a62SHenry Harrington static void
71b3215a62SHenry Harrington convert_preloaded_image(preloaded_elf64_image* image)
72b3215a62SHenry Harrington {
73b3215a62SHenry Harrington 	fix_address(image->next);
74b3215a62SHenry Harrington 	fix_address(image->name);
75b3215a62SHenry Harrington 	fix_address(image->debug_string_table);
76b3215a62SHenry Harrington 	fix_address(image->syms);
77b3215a62SHenry Harrington 	fix_address(image->rel);
78b3215a62SHenry Harrington 	fix_address(image->rela);
79b3215a62SHenry Harrington 	fix_address(image->pltrel);
80b3215a62SHenry Harrington 	fix_address(image->debug_symbols);
81b3215a62SHenry Harrington }
82b3215a62SHenry Harrington 
83b3215a62SHenry Harrington 
84b3215a62SHenry Harrington /*!	Convert all addresses in kernel_args to 64-bit addresses. */
85b3215a62SHenry Harrington static void
86b3215a62SHenry Harrington convert_kernel_args()
87b3215a62SHenry Harrington {
88312ace56SAlexander von Gluck IV 	if (gKernelArgs.kernel_image->elf_class != ELFCLASS64)
89312ace56SAlexander von Gluck IV 		return;
90312ace56SAlexander von Gluck IV 
91b3215a62SHenry Harrington 	fix_address(gKernelArgs.boot_volume);
92b3215a62SHenry Harrington 	fix_address(gKernelArgs.vesa_modes);
93b3215a62SHenry Harrington 	fix_address(gKernelArgs.edid_info);
94b3215a62SHenry Harrington 	fix_address(gKernelArgs.debug_output);
95b3215a62SHenry Harrington 	fix_address(gKernelArgs.boot_splash);
96b482adb1SAlexander von Gluck IV 	#if defined(__x86_64__) || defined(__x86__)
9711f8b65aSJérôme Duval 	fix_address(gKernelArgs.ucode_data);
98b3215a62SHenry Harrington 	fix_address(gKernelArgs.arch_args.apic);
99b3215a62SHenry Harrington 	fix_address(gKernelArgs.arch_args.hpet);
100b482adb1SAlexander von Gluck IV 	#endif
101b3215a62SHenry Harrington 
102b3215a62SHenry Harrington 	convert_preloaded_image(static_cast<preloaded_elf64_image*>(
103b3215a62SHenry Harrington 		gKernelArgs.kernel_image.Pointer()));
104b3215a62SHenry Harrington 	fix_address(gKernelArgs.kernel_image);
105b3215a62SHenry Harrington 
106b3215a62SHenry Harrington 	// Iterate over the preloaded images. Must save the next address before
107b3215a62SHenry Harrington 	// converting, as the next pointer will be converted.
108b3215a62SHenry Harrington 	preloaded_image* image = gKernelArgs.preloaded_images;
109b3215a62SHenry Harrington 	fix_address(gKernelArgs.preloaded_images);
110b3215a62SHenry Harrington 	while (image != NULL) {
111b3215a62SHenry Harrington 		preloaded_image* next = image->next;
112b3215a62SHenry Harrington 		convert_preloaded_image(static_cast<preloaded_elf64_image*>(image));
113b3215a62SHenry Harrington 		image = next;
114b3215a62SHenry Harrington 	}
115b3215a62SHenry Harrington 
116b3215a62SHenry Harrington 	// Fix driver settings files.
117b3215a62SHenry Harrington 	driver_settings_file* file = gKernelArgs.driver_settings;
118b3215a62SHenry Harrington 	fix_address(gKernelArgs.driver_settings);
119b3215a62SHenry Harrington 	while (file != NULL) {
120b3215a62SHenry Harrington 		driver_settings_file* next = file->next;
121b3215a62SHenry Harrington 		fix_address(file->next);
122b3215a62SHenry Harrington 		fix_address(file->buffer);
123b3215a62SHenry Harrington 		file = next;
124b3215a62SHenry Harrington 	}
125b3215a62SHenry Harrington }
126b3215a62SHenry Harrington 
127b3215a62SHenry Harrington 
128312ace56SAlexander von Gluck IV static addr_t
129312ace56SAlexander von Gluck IV get_kernel_entry(void)
130312ace56SAlexander von Gluck IV {
131312ace56SAlexander von Gluck IV 	if (gKernelArgs.kernel_image->elf_class == ELFCLASS64) {
132312ace56SAlexander von Gluck IV 		preloaded_elf64_image *image = static_cast<preloaded_elf64_image *>(
133312ace56SAlexander von Gluck IV 			gKernelArgs.kernel_image.Pointer());
134312ace56SAlexander von Gluck IV 		return image->elf_header.e_entry;
135312ace56SAlexander von Gluck IV 	} else if (gKernelArgs.kernel_image->elf_class == ELFCLASS32) {
136312ace56SAlexander von Gluck IV 		preloaded_elf32_image *image = static_cast<preloaded_elf32_image *>(
137312ace56SAlexander von Gluck IV 			gKernelArgs.kernel_image.Pointer());
138312ace56SAlexander von Gluck IV 		return image->elf_header.e_entry;
139312ace56SAlexander von Gluck IV 	}
140312ace56SAlexander von Gluck IV 	panic("Unknown kernel format! Not 32-bit or 64-bit!");
141312ace56SAlexander von Gluck IV 	return 0;
142312ace56SAlexander von Gluck IV }
143312ace56SAlexander von Gluck IV 
144312ace56SAlexander von Gluck IV 
145e2e1558aSJessica Hamilton extern "C" void
146e2e1558aSJessica Hamilton platform_start_kernel(void)
147e2e1558aSJessica Hamilton {
148a99a0c00SNick Smallbone 	smp_init_other_cpus();
149ec239abcSJessica Hamilton 
150312ace56SAlexander von Gluck IV 	addr_t kernelEntry = get_kernel_entry();
151b3215a62SHenry Harrington 
1527c32619cSAlexander von Gluck IV 	arch_mmu_init();
153b3215a62SHenry Harrington 	convert_kernel_args();
154b3215a62SHenry Harrington 
155b3215a62SHenry Harrington 	// Save the kernel entry point address.
15604f1baa7SAlexander von Gluck IV 	dprintf("kernel entry at %#lx\n", kernelEntry);
157b3215a62SHenry Harrington 
158b3215a62SHenry Harrington 	// map in a kernel stack
159b3215a62SHenry Harrington 	void *stack_address = NULL;
160485b5cf8SAlexander von Gluck IV 	if (platform_allocate_region(&stack_address,
161485b5cf8SAlexander von Gluck IV 		KERNEL_STACK_SIZE + KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE, 0, false)
162485b5cf8SAlexander von Gluck IV 		!= B_OK) {
163b3215a62SHenry Harrington 		panic("Unabled to allocate a stack");
164b3215a62SHenry Harrington 	}
16505586741SAlexander von Gluck IV 	gKernelArgs.cpu_kstack[0].start = fix_address((addr_t)stack_address);
166485b5cf8SAlexander von Gluck IV 	gKernelArgs.cpu_kstack[0].size = KERNEL_STACK_SIZE
167485b5cf8SAlexander von Gluck IV 		+ KERNEL_STACK_GUARD_PAGES * B_PAGE_SIZE;
168b3215a62SHenry Harrington 	dprintf("Kernel stack at %#lx\n", gKernelArgs.cpu_kstack[0].start);
169b3215a62SHenry Harrington 
170d38ba84dSAlexander von Gluck IV 	// Apply any weird EFI quirks
171d38ba84dSAlexander von Gluck IV 	quirks_init();
172d38ba84dSAlexander von Gluck IV 
17304f1baa7SAlexander von Gluck IV 	// Begin architecture-centric kernel entry.
17404f1baa7SAlexander von Gluck IV 	arch_start_kernel(kernelEntry);
175b3215a62SHenry Harrington 
17604f1baa7SAlexander von Gluck IV 	panic("Shouldn't get here!");
177e2e1558aSJessica Hamilton }
178e2e1558aSJessica Hamilton 
179e2e1558aSJessica Hamilton 
180e2e1558aSJessica Hamilton extern "C" void
181e2e1558aSJessica Hamilton platform_exit(void)
182e2e1558aSJessica Hamilton {
183e2e1558aSJessica Hamilton 	return;
184e2e1558aSJessica Hamilton }
185e2e1558aSJessica Hamilton 
186e2e1558aSJessica Hamilton 
187735f1daeSFredrik Holmqvist /**
188735f1daeSFredrik Holmqvist  * efi_main - The entry point for the EFI application
189735f1daeSFredrik Holmqvist  * @image: firmware-allocated handle that identifies the image
190735f1daeSFredrik Holmqvist  * @systemTable: EFI system table
191735f1daeSFredrik Holmqvist  */
192485b5cf8SAlexander von Gluck IV extern "C" efi_status
193485b5cf8SAlexander von Gluck IV efi_main(efi_handle image, efi_system_table *systemTable)
194735f1daeSFredrik Holmqvist {
195e2e1558aSJessica Hamilton 	stage2_args args;
196e2e1558aSJessica Hamilton 
197b3215a62SHenry Harrington 	memset(&args, 0, sizeof(stage2_args));
198b3215a62SHenry Harrington 
199b3215a62SHenry Harrington 	kImage = image;
200735f1daeSFredrik Holmqvist 	kSystemTable = systemTable;
201735f1daeSFredrik Holmqvist 	kBootServices = systemTable->BootServices;
202735f1daeSFredrik Holmqvist 	kRuntimeServices = systemTable->RuntimeServices;
203735f1daeSFredrik Holmqvist 
204735f1daeSFredrik Holmqvist 	call_ctors();
205735f1daeSFredrik Holmqvist 
206735f1daeSFredrik Holmqvist 	console_init();
2079e487d8dSFredrik Holmqvist 	serial_init();
2089e487d8dSFredrik Holmqvist 	serial_enable();
209735f1daeSFredrik Holmqvist 
21096f4d68bSJessica Hamilton 	sBootOptions = console_check_boot_keys();
21196f4d68bSJessica Hamilton 
212b3215a62SHenry Harrington 	// disable apm in case we ever load a 32-bit kernel...
213b3215a62SHenry Harrington 	gKernelArgs.platform_args.apm.version = 0;
2146e6efaecSJessica Hamilton 
21586b12d85SJessica Hamilton 	cpu_init();
21686b12d85SJessica Hamilton 	acpi_init();
217*569564c0SAlexander von Gluck IV 	dtb_init();
218b482adb1SAlexander von Gluck IV 	timer_init();
21986b12d85SJessica Hamilton 	smp_init();
22086b12d85SJessica Hamilton 
221e2e1558aSJessica Hamilton 	main(&args);
222735f1daeSFredrik Holmqvist 
223735f1daeSFredrik Holmqvist 	return EFI_SUCCESS;
224735f1daeSFredrik Holmqvist }
225