From af16798ef77da84487ed8e64bc955fbd12ac9b1f Mon Sep 17 00:00:00 2001 From: Olivier Martin Date: Tue, 26 Aug 2014 10:18:28 +0000 Subject: [PATCH] EmbeddedPkg/FdtLib: Added support to load Fdt from Semihosting The FDT is also installed into the UEFI configuration table to be used by the OS loader. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Olivier Martin git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@15905 6f19259b-4bc3-4df7-8a09-765794883524 --- EmbeddedPkg/Include/libfdt_env.h | 16 ++ .../Library/FdtLib/FdtConfigurationTable.c | 178 ++++++++++++++++++ EmbeddedPkg/Library/FdtLib/FdtLib.inf | 16 +- 3 files changed, 208 insertions(+), 2 deletions(-) create mode 100644 EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c diff --git a/EmbeddedPkg/Include/libfdt_env.h b/EmbeddedPkg/Include/libfdt_env.h index 3e24db9409..18a8450b92 100644 --- a/EmbeddedPkg/Include/libfdt_env.h +++ b/EmbeddedPkg/Include/libfdt_env.h @@ -15,6 +15,7 @@ #ifndef _LIBFDT_ENV_H #define _LIBFDT_ENV_H +#include #include #include @@ -78,4 +79,19 @@ 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 + ); + #endif /* _LIBFDT_ENV_H */ diff --git a/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c b/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c new file mode 100644 index 0000000000..42c5d44ea9 --- /dev/null +++ b/EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c @@ -0,0 +1,178 @@ +/** @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 + +// +// 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; +} diff --git a/EmbeddedPkg/Library/FdtLib/FdtLib.inf b/EmbeddedPkg/Library/FdtLib/FdtLib.inf index 51b13f4af7..0d8d629b7b 100644 --- a/EmbeddedPkg/Library/FdtLib/FdtLib.inf +++ b/EmbeddedPkg/Library/FdtLib/FdtLib.inf @@ -1,5 +1,5 @@ #/* @file -# Copyright (c) 2011-2012, ARM Limited. All rights reserved. +# 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 @@ -22,10 +22,11 @@ # # The following information is for reference only and not required by the build tools. # -# VALID_ARCHITECTURES = ARM +# VALID_ARCHITECTURES = ARM AARCH64 # [Sources] + FdtConfigurationTable.c fdt_ro.c fdt_rw.c fdt_strerror.c @@ -36,3 +37,14 @@ [Packages] MdePkg/MdePkg.dec EmbeddedPkg/EmbeddedPkg.dec + +[LibraryClasses] + UefiBootServicesTableLib + +[Protocols] + gEfiDevicePathProtocolGuid + gEfiSimpleFileSystemProtocolGuid + +[Guids] + gEfiFileInfoGuid + gFdtTableGuid -- 2.39.2