*\r
**/\r
\r
-#include <Uefi.h>\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
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