From: Ard Biesheuvel Date: Tue, 9 Sep 2014 17:59:19 +0000 (+0000) Subject: EmbeddedPkg: Split off FDT loading functionality from FdtLib X-Git-Tag: edk2-stable201903~10915 X-Git-Url: https://git.proxmox.com/?p=mirror_edk2.git;a=commitdiff_plain;h=1e9b2bddff2217eb23bf9eb5d1052ecfebc39204 EmbeddedPkg: Split off FDT loading functionality from FdtLib Split off the recently added functionality to load device tree images and install them as configuration tables, as it introduces a dependency on UefiBootServicesTableLib, preventing FdtLib from being used during SEC and PEI phases. Contributed-under: TianoCore Contribution Agreement 1.0 Reviewed-by: Laszlo Ersek Signed-off-by: Ard Biesheuvel Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16080 6f19259b-4bc3-4df7-8a09-765794883524 --- diff --git a/EmbeddedPkg/EmbeddedPkg.dsc b/EmbeddedPkg/EmbeddedPkg.dsc index 9960d8fa6e..8844f8edf4 100644 --- a/EmbeddedPkg/EmbeddedPkg.dsc +++ b/EmbeddedPkg/EmbeddedPkg.dsc @@ -262,6 +262,9 @@ EmbeddedPkg/Universal/MmcDxe/MmcDxe.inf + # FDT Support + EmbeddedPkg/Library/FdtLoadLib/FdtLoadLib.inf + EmbeddedPkg/Application/AndroidFastboot/AndroidFastbootApp.inf EmbeddedPkg/Drivers/AndroidFastbootTransportUsbDxe/FastbootTransportUsbDxe.inf EmbeddedPkg/Drivers/AndroidFastbootTransportTcpDxe/FastbootTransportTcpDxe.inf diff --git a/EmbeddedPkg/Include/Library/FdtLoadLib.h b/EmbeddedPkg/Include/Library/FdtLoadLib.h new file mode 100644 index 0000000000..e08f499745 --- /dev/null +++ b/EmbeddedPkg/Include/Library/FdtLoadLib.h @@ -0,0 +1,48 @@ +/** @file +* +* Copyright (c) 2011-2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#ifndef _FDT_LOAD_LIB_H_ +#define _FDT_LOAD_LIB_H_ + +/** + Load and Install FDT from Semihosting + + @param Filename Name of the file to load from semihosting + + @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table + from semihosting + @return EFI_NOT_FOUND Fail to locate the file in semihosting + @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob +**/ +EFI_STATUS +InstallFdtFromSemihosting ( + IN CONST CHAR16* FileName + ); + +/** + Load and Install FDT from Firmware Volume + + @param Filename Guid of the FDT blob to load from firmware volume + + @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table + from firmware volume + @return EFI_NOT_FOUND Failed to locate the file in firmware volume + @return EFI_OUT_OF_RESOURCES Failed to allocate memory to contain the blob +**/ +EFI_STATUS +InstallFdtFromFv ( + IN CONST EFI_GUID *FileName + ); + +#endif diff --git a/EmbeddedPkg/Include/libfdt_env.h b/EmbeddedPkg/Include/libfdt_env.h index c4dc83c024..3e24db9409 100644 --- a/EmbeddedPkg/Include/libfdt_env.h +++ b/EmbeddedPkg/Include/libfdt_env.h @@ -15,7 +15,6 @@ #ifndef _LIBFDT_ENV_H #define _LIBFDT_ENV_H -#include #include #include @@ -79,34 +78,4 @@ static inline char *strchr(const char *s, int c) { return AsciiStrStr (s, pattern); } -/** - Load and Install FDT from Semihosting - - @param Filename Name of the file to load from semihosting - - @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table - from semihosting - @return EFI_NOT_FOUND Fail to locate the file in semihosting - @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob -**/ -EFI_STATUS -InstallFdtFromSemihosting ( - IN CONST CHAR16* FileName - ); - -/** - Load and Install FDT from Firmware Volume - - @param Filename Guid of the FDT blob to load from firmware volume - - @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table - from firmware volume - @return EFI_NOT_FOUND Failed to locate the file in firmware volume - @return EFI_OUT_OF_RESOURCES Failed to allocate memory to contain the blob -**/ -EFI_STATUS -InstallFdtFromFv ( - IN CONST EFI_GUID *FileName - ); - #endif /* _LIBFDT_ENV_H */ diff --git a/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c b/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c deleted file mode 100644 index aece1df1cc..0000000000 --- a/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c +++ /dev/null @@ -1,279 +0,0 @@ -/** @file -* -* Copyright (c) 2014, ARM Limited. All rights reserved. -* -* This program and the accompanying materials -* are licensed and made available under the terms and conditions of the BSD License -* which accompanies this distribution. The full text of the license may be found at -* http://opensource.org/licenses/bsd-license.php -* -* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, -* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. -* -**/ - -#include -#include -#include -#include - -#include -#include -#include - -#include -#include - -#include - -// -// Device path for SemiHosting -// -STATIC CONST struct { - VENDOR_DEVICE_PATH Guid; - EFI_DEVICE_PATH_PROTOCOL End; -} mSemihostingDevicePath = { - { - { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } }, - { 0xC5B9C74A, 0x6D72, 0x4719, { 0x99, 0xAB, 0xC5, 0x9F, 0x19, 0x90, 0x91, 0xEB } } - }, - { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } } -}; - - -/** - This function declares the passed FDT into the UEFI Configuration Table - - @param FdtBlob Base address of the Fdt Blob in System Memory - @param FdtSize Size of the Fdt Blob in System Memory - - @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table - @return !EFI_SUCCESS Error returned by BS.InstallConfigurationTable() - -**/ -STATIC -EFI_STATUS -InstallFdtIntoConfigurationTable ( - IN VOID* FdtBlob, - IN UINTN FdtSize - ) -{ - EFI_STATUS Status; - - // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on - // production device and this ASSERT() becomes not valid. - ASSERT (fdt_check_header (FdtBlob) == 0); - - // Ensure the Size of the Device Tree is smaller than the size of the read file - ASSERT ((UINTN)fdt_totalsize (FdtBlob) <= FdtSize); - - // Install the FDT into the Configuration Table - Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtBlob); - - return Status; -} - - -/** - Load and Install FDT from Semihosting - - @param Filename Name of the file to load from semihosting - - @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table - from semihosting - @return EFI_NOT_FOUND Fail to locate the file in semihosting - @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob -**/ -EFI_STATUS -InstallFdtFromSemihosting ( - IN CONST CHAR16* FileName - ) -{ - EFI_STATUS Status; - EFI_DEVICE_PATH* Remaining; - EFI_HANDLE Handle; - EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SemihostingFs; - EFI_FILE_PROTOCOL *Fs; - EFI_FILE_PROTOCOL *File; - EFI_PHYSICAL_ADDRESS FdtBase; - EFI_FILE_INFO *FileInfo; - UINTN FdtSize; - UINTN FileInfoSize; - - // Ensure the Semihosting driver is initialized - Remaining = (EFI_DEVICE_PATH*)&mSemihostingDevicePath; - // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns - // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified - // to point to the remaining part of the device path - Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, &Handle); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - // Recursive = FALSE: We do not want to start the whole device tree - Status = gBS->ConnectController (Handle, NULL, Remaining, FALSE); - if (EFI_ERROR (Status)) { - return Status; - } - - // Locate the FileSystem - Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&SemihostingFs); - if (EFI_ERROR (Status)) { - ASSERT_EFI_ERROR (Status); - return Status; - } - - // Try to Open the volume and get root directory - Status = SemihostingFs->OpenVolume (SemihostingFs, &Fs); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_WARN, "Warning: Fail to open semihosting filesystem that should contain FDT file.\n")); - return Status; - } - - File = NULL; - Status = Fs->Open (Fs, &File, (CHAR16*)FileName, EFI_FILE_MODE_READ, 0); - if (EFI_ERROR (Status)) { - DEBUG ((EFI_D_WARN, "Warning: Fail to load FDT file '%s'.\n", FileName)); - Fs->Close (Fs); - return Status; - } - - FileInfoSize = 0; - File->GetInfo (File, &gEfiFileInfoGuid, &FileInfoSize, NULL); - FileInfo = AllocatePool (FileInfoSize); - if (FileInfo == NULL) { - Status = EFI_OUT_OF_RESOURCES; - goto CLOSE_FILES; - } - Status = File->GetInfo (File, &gEfiFileInfoGuid, &FileInfoSize, FileInfo); - if (EFI_ERROR (Status)) { - FreePool (FileInfo); - goto CLOSE_FILES; - } - - // Get the file size - FdtSize = FileInfo->FileSize; - FreePool (FileInfo); - - // The FDT blob is attached to the Configuration Table. It is recommended to load it as Runtime Service Data - // to prevent the kernel to overwrite its data - Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (FdtSize), &FdtBase); - if (!EFI_ERROR (Status)) { - Status = File->Read (File, &FdtSize, (VOID*)(UINTN)(FdtBase)); - if (EFI_ERROR (Status)) { - gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); - } else { - // Install the FDT as part of the UEFI Configuration Table - Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)FdtBase, FdtSize); - if (EFI_ERROR (Status)) { - gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); - } - } - } - -CLOSE_FILES: - File->Close (File); - Fs->Close (Fs); - return Status; -} - -/** - Load and Install FDT from Firmware Volume - - @param Filename Guid of the FDT blob to load from firmware volume - - @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table - from firmware volume - @return EFI_NOT_FOUND Fail to locate the file in firmware volume - @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob -**/ -EFI_STATUS -InstallFdtFromFv ( - IN CONST EFI_GUID *FileName - ) -{ - EFI_STATUS Status; - EFI_HANDLE *HandleBuffer; - UINTN NumberOfHandles; - UINT32 FvStatus; - UINTN Index; - EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; - INTN SectionInstance; - UINTN FdtSize; - VOID* FdtBlob; - EFI_PHYSICAL_ADDRESS FdtBase; - - FvStatus = 0; - SectionInstance = 0; - - // Locate all the Firmware Volume protocols. - Status = gBS->LocateHandleBuffer ( - ByProtocol, - &gEfiFirmwareVolume2ProtocolGuid, - NULL, - &NumberOfHandles, - &HandleBuffer - ); - if (EFI_ERROR (Status)) { - return Status; - } - - // Looking for FV that contains the FDT blob - for (Index = 0; Index < NumberOfHandles; Index++) { - // - // Get the protocol on this handle - // This should not fail because of LocateHandleBuffer - // - Status = gBS->HandleProtocol ( - HandleBuffer[Index], - &gEfiFirmwareVolume2ProtocolGuid, - (VOID**) &FvInstance - ); - if (EFI_ERROR (Status)) { - goto FREE_HANDLE_BUFFER; - } - - while (Status == EFI_SUCCESS) { - // FdtBlob must be allocated by ReadSection - FdtBlob = NULL; - - // See if it contains the FDT file - Status = FvInstance->ReadSection ( - FvInstance, - FileName, - EFI_SECTION_RAW, - SectionInstance, - &FdtBlob, - &FdtSize, - &FvStatus - ); - if (!EFI_ERROR (Status)) { - // When the FDT blob is attached to the Configuration Table it is recommended to load it as Runtime Service Data - // to prevent the kernel to overwrite its data - Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (FdtSize), &FdtBase); - if (EFI_ERROR (Status)) { - goto FREE_HANDLE_BUFFER; - } - - // Copy the FDT to the Runtime memory - gBS->CopyMem ((VOID*)(UINTN)FdtBase, FdtBlob, FdtSize); - // Free the buffer allocated by FvInstance->ReadSection() - gBS->FreePool (FdtBlob); - - // Install the FDT as part of the UEFI Configuration Table - Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)FdtBase, FdtSize); - if (EFI_ERROR (Status)) { - gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); - } - break; - } - } - } - -FREE_HANDLE_BUFFER: - // Free any allocated buffers - gBS->FreePool (HandleBuffer); - - return Status; -} diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf index d18caa67ea..f3da231143 100644 --- a/EmbeddedPkg/Library/FdtLib/FdtLib.inf +++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf @@ -26,7 +26,6 @@ # [Sources] - FdtConfigurationTable.c fdt_ro.c fdt_rw.c fdt_strerror.c @@ -37,15 +36,3 @@ [Packages] MdePkg/MdePkg.dec EmbeddedPkg/EmbeddedPkg.dec - -[LibraryClasses] - UefiBootServicesTableLib - -[Protocols] - gEfiDevicePathProtocolGuid - gEfiSimpleFileSystemProtocolGuid - gEfiFirmwareVolume2ProtocolGuid - -[Guids] - gEfiFileInfoGuid - gFdtTableGuid diff --git a/EmbeddedPkg/Library/FdtLoadLib/FdtConfigurationTable.c b/EmbeddedPkg/Library/FdtLoadLib/FdtConfigurationTable.c new file mode 100644 index 0000000000..a95e24958b --- /dev/null +++ b/EmbeddedPkg/Library/FdtLoadLib/FdtConfigurationTable.c @@ -0,0 +1,280 @@ +/** @file +* +* Copyright (c) 2014, ARM Limited. All rights reserved. +* +* This program and the accompanying materials +* are licensed and made available under the terms and conditions of the BSD License +* which accompanies this distribution. The full text of the license may be found at +* http://opensource.org/licenses/bsd-license.php +* +* THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +* WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +* +**/ + +#include +#include +#include +#include +#include + +#include +#include +#include + +#include +#include + +#include + +// +// Device path for SemiHosting +// +STATIC CONST struct { + VENDOR_DEVICE_PATH Guid; + EFI_DEVICE_PATH_PROTOCOL End; +} mSemihostingDevicePath = { + { + { HARDWARE_DEVICE_PATH, HW_VENDOR_DP, { sizeof (VENDOR_DEVICE_PATH), 0 } }, + { 0xC5B9C74A, 0x6D72, 0x4719, { 0x99, 0xAB, 0xC5, 0x9F, 0x19, 0x90, 0x91, 0xEB } } + }, + { END_DEVICE_PATH_TYPE, END_ENTIRE_DEVICE_PATH_SUBTYPE, { sizeof (EFI_DEVICE_PATH_PROTOCOL), 0 } } +}; + + +/** + This function declares the passed FDT into the UEFI Configuration Table + + @param FdtBlob Base address of the Fdt Blob in System Memory + @param FdtSize Size of the Fdt Blob in System Memory + + @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table + @return !EFI_SUCCESS Error returned by BS.InstallConfigurationTable() + +**/ +STATIC +EFI_STATUS +InstallFdtIntoConfigurationTable ( + IN VOID* FdtBlob, + IN UINTN FdtSize + ) +{ + EFI_STATUS Status; + + // Check the FDT header is valid. We only make this check in DEBUG mode in case the FDT header change on + // production device and this ASSERT() becomes not valid. + ASSERT (fdt_check_header (FdtBlob) == 0); + + // Ensure the Size of the Device Tree is smaller than the size of the read file + ASSERT ((UINTN)fdt_totalsize (FdtBlob) <= FdtSize); + + // Install the FDT into the Configuration Table + Status = gBS->InstallConfigurationTable (&gFdtTableGuid, FdtBlob); + + return Status; +} + + +/** + Load and Install FDT from Semihosting + + @param Filename Name of the file to load from semihosting + + @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table + from semihosting + @return EFI_NOT_FOUND Fail to locate the file in semihosting + @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob +**/ +EFI_STATUS +InstallFdtFromSemihosting ( + IN CONST CHAR16* FileName + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH* Remaining; + EFI_HANDLE Handle; + EFI_SIMPLE_FILE_SYSTEM_PROTOCOL *SemihostingFs; + EFI_FILE_PROTOCOL *Fs; + EFI_FILE_PROTOCOL *File; + EFI_PHYSICAL_ADDRESS FdtBase; + EFI_FILE_INFO *FileInfo; + UINTN FdtSize; + UINTN FileInfoSize; + + // Ensure the Semihosting driver is initialized + Remaining = (EFI_DEVICE_PATH*)&mSemihostingDevicePath; + // The LocateDevicePath() function locates all devices on DevicePath that support Protocol and returns + // the handle to the device that is closest to DevicePath. On output, the device path pointer is modified + // to point to the remaining part of the device path + Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &Remaining, &Handle); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // Recursive = FALSE: We do not want to start the whole device tree + Status = gBS->ConnectController (Handle, NULL, Remaining, FALSE); + if (EFI_ERROR (Status)) { + return Status; + } + + // Locate the FileSystem + Status = gBS->HandleProtocol (Handle, &gEfiSimpleFileSystemProtocolGuid, (VOID **)&SemihostingFs); + if (EFI_ERROR (Status)) { + ASSERT_EFI_ERROR (Status); + return Status; + } + + // Try to Open the volume and get root directory + Status = SemihostingFs->OpenVolume (SemihostingFs, &Fs); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "Warning: Fail to open semihosting filesystem that should contain FDT file.\n")); + return Status; + } + + File = NULL; + Status = Fs->Open (Fs, &File, (CHAR16*)FileName, EFI_FILE_MODE_READ, 0); + if (EFI_ERROR (Status)) { + DEBUG ((EFI_D_WARN, "Warning: Fail to load FDT file '%s'.\n", FileName)); + Fs->Close (Fs); + return Status; + } + + FileInfoSize = 0; + File->GetInfo (File, &gEfiFileInfoGuid, &FileInfoSize, NULL); + FileInfo = AllocatePool (FileInfoSize); + if (FileInfo == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto CLOSE_FILES; + } + Status = File->GetInfo (File, &gEfiFileInfoGuid, &FileInfoSize, FileInfo); + if (EFI_ERROR (Status)) { + FreePool (FileInfo); + goto CLOSE_FILES; + } + + // Get the file size + FdtSize = FileInfo->FileSize; + FreePool (FileInfo); + + // The FDT blob is attached to the Configuration Table. It is recommended to load it as Runtime Service Data + // to prevent the kernel to overwrite its data + Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (FdtSize), &FdtBase); + if (!EFI_ERROR (Status)) { + Status = File->Read (File, &FdtSize, (VOID*)(UINTN)(FdtBase)); + if (EFI_ERROR (Status)) { + gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); + } else { + // Install the FDT as part of the UEFI Configuration Table + Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)FdtBase, FdtSize); + if (EFI_ERROR (Status)) { + gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); + } + } + } + +CLOSE_FILES: + File->Close (File); + Fs->Close (Fs); + return Status; +} + +/** + Load and Install FDT from Firmware Volume + + @param Filename Guid of the FDT blob to load from firmware volume + + @return EFI_SUCCESS Fdt Blob was successfully installed into the configuration table + from firmware volume + @return EFI_NOT_FOUND Fail to locate the file in firmware volume + @return EFI_OUT_OF_RESOURCES Fail to allocate memory to contain the blob +**/ +EFI_STATUS +InstallFdtFromFv ( + IN CONST EFI_GUID *FileName + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN NumberOfHandles; + UINT32 FvStatus; + UINTN Index; + EFI_FIRMWARE_VOLUME2_PROTOCOL *FvInstance; + INTN SectionInstance; + UINTN FdtSize; + VOID* FdtBlob; + EFI_PHYSICAL_ADDRESS FdtBase; + + FvStatus = 0; + SectionInstance = 0; + + // Locate all the Firmware Volume protocols. + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &NumberOfHandles, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // Looking for FV that contains the FDT blob + for (Index = 0; Index < NumberOfHandles; Index++) { + // + // Get the protocol on this handle + // This should not fail because of LocateHandleBuffer + // + Status = gBS->HandleProtocol ( + HandleBuffer[Index], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID**) &FvInstance + ); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } + + while (Status == EFI_SUCCESS) { + // FdtBlob must be allocated by ReadSection + FdtBlob = NULL; + + // See if it contains the FDT file + Status = FvInstance->ReadSection ( + FvInstance, + FileName, + EFI_SECTION_RAW, + SectionInstance, + &FdtBlob, + &FdtSize, + &FvStatus + ); + if (!EFI_ERROR (Status)) { + // When the FDT blob is attached to the Configuration Table it is recommended to load it as Runtime Service Data + // to prevent the kernel to overwrite its data + Status = gBS->AllocatePages (AllocateAnyPages, EfiRuntimeServicesData, EFI_SIZE_TO_PAGES (FdtSize), &FdtBase); + if (EFI_ERROR (Status)) { + goto FREE_HANDLE_BUFFER; + } + + // Copy the FDT to the Runtime memory + gBS->CopyMem ((VOID*)(UINTN)FdtBase, FdtBlob, FdtSize); + // Free the buffer allocated by FvInstance->ReadSection() + gBS->FreePool (FdtBlob); + + // Install the FDT as part of the UEFI Configuration Table + Status = InstallFdtIntoConfigurationTable ((VOID*)(UINTN)FdtBase, FdtSize); + if (EFI_ERROR (Status)) { + gBS->FreePages (FdtBase, EFI_SIZE_TO_PAGES (FdtSize)); + } + break; + } + } + } + +FREE_HANDLE_BUFFER: + // Free any allocated buffers + gBS->FreePool (HandleBuffer); + + return Status; +} diff --git a/EmbeddedPkg/Library/FdtLoadLib/FdtLoadLib.inf b/EmbeddedPkg/Library/FdtLoadLib/FdtLoadLib.inf new file mode 100644 index 0000000000..a50aa3607a --- /dev/null +++ b/EmbeddedPkg/Library/FdtLoadLib/FdtLoadLib.inf @@ -0,0 +1,45 @@ +#/* @file +# Copyright (c) 2014, Linaro Limited. All rights reserved. +# +# This program and the accompanying materials +# are licensed and made available under the terms and conditions of the BSD License +# which accompanies this distribution. The full text of the license may be found at +# http://opensource.org/licenses/bsd-license.php +# +# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, +# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. +# +#*/ + +[Defines] + INF_VERSION = 0x00010005 + BASE_NAME = FdtLoadLib + FILE_GUID = F00298C1-BBC3-445F-8906-AAEAFE7729A4 + MODULE_TYPE = BASE + VERSION_STRING = 1.0 + LIBRARY_CLASS = FdtLoadLib + +# +# The following information is for reference only and not required by the build tools. +# +# VALID_ARCHITECTURES = ARM AARCH64 +# + +[Sources] + FdtConfigurationTable.c + +[Packages] + MdePkg/MdePkg.dec + EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + FdtLib + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiSimpleFileSystemProtocolGuid + gEfiFirmwareVolume2ProtocolGuid + +[Guids] + gEfiFileInfoGuid + gFdtTableGuid