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 void* sDtbTable = NULL; 25 static uint32 sDtbSize = 0; 26 27 28 static bool 29 fdt_valid(void* fdt, uint32* size) 30 { 31 if (fdt == NULL) 32 return false; 33 uint32* words = (uint32*)fdt; 34 if (B_BENDIAN_TO_HOST_INT32(words[0]) != 0xd00dfeed) 35 return false; 36 *size = B_BENDIAN_TO_HOST_INT32(words[1]); 37 if (size == 0) 38 return false; 39 40 return true; 41 } 42 43 44 void 45 dtb_init() 46 { 47 efi_configuration_table *table = kSystemTable->ConfigurationTable; 48 size_t entries = kSystemTable->NumberOfTableEntries; 49 50 INFO("Probing for device trees from UEFI...\n"); 51 52 // Try to find an FDT 53 for (uint32 i = 0; i < entries; i++) { 54 if (!table[i].VendorGuid.equals(DEVICE_TREE_GUID)) 55 continue; 56 57 void* dtbPtr = (void*)(table[i].VendorTable); 58 59 uint32 fdtSize = 0; 60 if (!fdt_valid(dtbPtr, &fdtSize)) { 61 ERROR("Invalid FDT from UEFI table %d\n", i); 62 break; 63 } else { 64 INFO("Valid FDT from UEFI table %d (%d)\n", i, fdtSize); 65 66 sDtbTable = dtbPtr; 67 sDtbSize = fdtSize; 68 break; 69 } 70 } 71 } 72 73 74 void 75 dtb_set_kernel_args() 76 { 77 // pack into proper location if the architecture cares 78 if (sDtbTable != NULL) { 79 #ifdef __ARM__ 80 gKernelArgs.arch_args.fdt = kernel_args_malloc(sDtbSize); 81 if (gKernelArgs.arch_args.fdt != NULL) 82 memcpy(gKernelArgs.arch_args.fdt, sDtbTable, sDtbSize); 83 else 84 ERROR("unable to malloc for fdt!\n"); 85 #endif 86 } 87 } 88