diff --git a/headers/private/kernel/arch/arm/arch_kernel_args.h b/headers/private/kernel/arch/arm/arch_kernel_args.h index e19183db9b..9758ea7035 100644 --- a/headers/private/kernel/arch/arm/arch_kernel_args.h +++ b/headers/private/kernel/arch/arm/arch_kernel_args.h @@ -30,6 +30,7 @@ typedef struct { // needed for UEFI, otherwise kernel acpi support can't find ACPI root FixedWidthPointer acpi_root; + FixedWidthPointer fdt; } _PACKED arch_kernel_args; #endif /* KERNEL_ARCH_ARM_KERNEL_ARGS_H */ diff --git a/headers/private/kernel/platform/efi/types.h b/headers/private/kernel/platform/efi/types.h index 2c1df000c9..2349256a74 100644 --- a/headers/private/kernel/platform/efi/types.h +++ b/headers/private/kernel/platform/efi/types.h @@ -68,6 +68,9 @@ {0xeb9d2d31, 0x2d88, 0x11d3, {0x9a, 0x16, 0x00, 0x90, 0x27, 0x3f, 0xc1, 0x4d}} #define SMBIOS3_TABLE_GUID \ {0xf2fd1544, 0x9794, 0x4a2c, {0x99, 0x2e, 0xe5, 0xbb, 0xcf, 0x20, 0xe3, 0x94}} +#define DEVICE_TREE_GUID \ + {0xb1b621d5, 0xf19c, 0x41a5, {0x83, 0x0b, 0xd9, 0x15, 0x2c, 0x69, 0xaa, 0xe0}} + typedef struct { uint64_t Signature; diff --git a/src/system/boot/platform/efi/Jamfile b/src/system/boot/platform/efi/Jamfile index 671d3e52a6..b9581b9c4c 100644 --- a/src/system/boot/platform/efi/Jamfile +++ b/src/system/boot/platform/efi/Jamfile @@ -23,6 +23,7 @@ local platform_src = mmu.cpp heap.cpp acpi.cpp + dtb.cpp timer.cpp menu.cpp devices.cpp diff --git a/src/system/boot/platform/efi/dtb.cpp b/src/system/boot/platform/efi/dtb.cpp new file mode 100644 index 0000000000..d1a1674cde --- /dev/null +++ b/src/system/boot/platform/efi/dtb.cpp @@ -0,0 +1,72 @@ +/* + * Copyright 2019-2020 Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + * + * Authors: + * Alexander von Gluck IV + */ + + +#include +#include +#include +#include + +#include + +#include "efi_platform.h" + + +#define INFO(x...) dprintf("efi/fdt: " x) +#define ERROR(x...) dprintf("efi/fdt: " x) + + +static bool +fdt_valid(void* fdt, uint32* size) +{ + if (fdt == NULL) + return false; + uint32* words = (uint32*)fdt; + if (B_BENDIAN_TO_HOST_INT32(words[0]) != 0xd00dfeed) + return false; + *size = B_BENDIAN_TO_HOST_INT32(words[1]); + if (size == 0) + return false; + + return true; +} + + +void +dtb_init() +{ + efi_configuration_table *table = kSystemTable->ConfigurationTable; + size_t entries = kSystemTable->NumberOfTableEntries; + + INFO("Probing for device trees from UEFI...\n"); + + // Try to find an FDT + for (uint32 i = 0; i < entries; i++) { + if (!table[i].VendorGuid.equals(DEVICE_TREE_GUID)) + continue; + + void* dtbPtr = (void*)(table[i].VendorTable); + + uint32 fdtSize = 0; + if (!fdt_valid(dtbPtr, &fdtSize)) { + ERROR("Invalid FDT from UEFI table %d\n", i); + break; + } + + INFO("Valid FDT from UEFI table %d (%d)\n", i, fdtSize); + + // pack into proper location if the architecture cares + #ifdef __ARM__ + gKernelArgs.arch_args.fdt = kernel_args_malloc(fdtSize); + if (gKernelArgs.arch_args.fdt != NULL) { + memcpy(gKernelArgs.arch_args.fdt, dtbPtr, fdtSize); + } else + ERROR("unable to malloc for fdt!\n"); + #endif + } +} diff --git a/src/system/boot/platform/efi/dtb.h b/src/system/boot/platform/efi/dtb.h new file mode 100644 index 0000000000..c6e09acc75 --- /dev/null +++ b/src/system/boot/platform/efi/dtb.h @@ -0,0 +1,20 @@ +/* + * Copyright 2019-2020, Haiku, Inc. All rights reserved. + * Distributed under the terms of the MIT License. + */ +#ifndef DTB_H +#define DTB_H + +#ifndef _ASSEMBLER + +#include "efi_platform.h" + +#include + + +extern void dtb_init(); + + +#endif /* !_ASSEMBLER */ + +#endif /* DTB_H */ diff --git a/src/system/boot/platform/efi/start.cpp b/src/system/boot/platform/efi/start.cpp index 4fd5f5b31f..9e3a88950d 100644 --- a/src/system/boot/platform/efi/start.cpp +++ b/src/system/boot/platform/efi/start.cpp @@ -24,6 +24,7 @@ #include "acpi.h" #include "console.h" #include "cpu.h" +#include "dtb.h" #include "efi_platform.h" #include "mmu.h" #include "quirks.h" @@ -213,6 +214,7 @@ efi_main(efi_handle image, efi_system_table *systemTable) cpu_init(); acpi_init(); + dtb_init(); timer_init(); smp_init();