EmbeddedPkg: Split off FDT loading functionality from FdtLib
authorArd Biesheuvel <ard.biesheuvel@linaro.org>
Tue, 9 Sep 2014 17:59:19 +0000 (17:59 +0000)
committeroliviermartin <oliviermartin@6f19259b-4bc3-4df7-8a09-765794883524>
Tue, 9 Sep 2014 17:59:19 +0000 (17:59 +0000)
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 <lersek@redhat.com>
Signed-off-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Signed-off-by: Olivier Martin <olivier.martin@arm.com>
git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@16080 6f19259b-4bc3-4df7-8a09-765794883524

EmbeddedPkg/EmbeddedPkg.dsc
EmbeddedPkg/Include/Library/FdtLoadLib.h [new file with mode: 0644]
EmbeddedPkg/Include/libfdt_env.h
EmbeddedPkg/Library/FdtLib/FdtConfigurationTable.c [deleted file]
EmbeddedPkg/Library/FdtLib/FdtLib.inf
EmbeddedPkg/Library/FdtLoadLib/FdtConfigurationTable.c [new file with mode: 0644]
EmbeddedPkg/Library/FdtLoadLib/FdtLoadLib.inf [new file with mode: 0644]

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