xref: /haiku/src/system/boot/platform/efi/dtb.cpp (revision 99f2b968946b4a0f391e62a417c370c7e9b942de)
1 /*
2  * Copyright 2019-2020 Haiku, Inc. All rights reserved.
3  * Distributed under the terms of the MIT License.
4  *
5  * Authors:
6  *   Alexander von Gluck IV <kallisti5@unixzen.com>
7  */
8 
9 
10 #include <boot/addr_range.h>
11 #include <boot/platform.h>
12 #include <boot/stage2.h>
13 #include <kernel/kernel.h>
14 
15 #include <ByteOrder.h>
16 
17 #include "efi_platform.h"
18 
19 
20 #define INFO(x...) dprintf("efi/fdt: " x)
21 #define ERROR(x...) dprintf("efi/fdt: " x)
22 
23 
24 static bool
25 fdt_valid(void* fdt, uint32* size)
26 {
27 	if (fdt == NULL)
28 		return false;
29 	uint32* words = (uint32*)fdt;
30 	if (B_BENDIAN_TO_HOST_INT32(words[0]) != 0xd00dfeed)
31 		return false;
32 	*size = B_BENDIAN_TO_HOST_INT32(words[1]);
33 	if (size == 0)
34 		return false;
35 
36 	return true;
37 }
38 
39 
40 void
41 dtb_init()
42 {
43 	efi_configuration_table *table = kSystemTable->ConfigurationTable;
44 	size_t entries = kSystemTable->NumberOfTableEntries;
45 
46 	INFO("Probing for device trees from UEFI...\n");
47 
48 	// Try to find an FDT
49 	for (uint32 i = 0; i < entries; i++) {
50 		if (!table[i].VendorGuid.equals(DEVICE_TREE_GUID))
51 			continue;
52 
53 		void* dtbPtr = (void*)(table[i].VendorTable);
54 
55 		uint32 fdtSize = 0;
56 		if (!fdt_valid(dtbPtr, &fdtSize)) {
57 			ERROR("Invalid FDT from UEFI table %d\n", i);
58 			break;
59 		}
60 
61 		INFO("Valid FDT from UEFI table %d (%d)\n", i, fdtSize);
62 
63 		// pack into proper location if the architecture cares
64 		#ifdef __ARM__
65 		gKernelArgs.arch_args.fdt = kernel_args_malloc(fdtSize);
66 		if (gKernelArgs.arch_args.fdt != NULL) {
67 			memcpy(gKernelArgs.arch_args.fdt, dtbPtr, fdtSize);
68 		} else
69 			ERROR("unable to malloc for fdt!\n");
70 		#endif
71 	}
72 }
73