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
40extern void (*__ctor_list)(void);
41extern void (*__ctor_end)(void);
42
43
44const efi_system_table		*kSystemTable;
45const efi_boot_services		*kBootServices;
46const efi_runtime_services	*kRuntimeServices;
47efi_handle kImage;
48
49
50static uint32 sBootOptions;
51
52extern "C" int main(stage2_args *args);
53extern "C" void _start(void);
54extern "C" void efi_enter_kernel(uint64 pml4, uint64 entry_point, uint64 stack);
55
56
57static void
58call_ctors(void)
59{
60	void (**f)(void);
61
62	for (f = &__ctor_list; f < &__ctor_end; f++)
63		(**f)();
64}
65
66
67extern "C" uint32
68platform_boot_options()
69{
70	return sBootOptions;
71}
72
73
74template<class T> static void
75convert_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. */
90static void
91convert_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
134static addr_t
135get_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
151static void
152get_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
175extern "C" void
176platform_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
219extern "C" void
220platform_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 */
232extern "C" efi_status
233efi_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