+\r
+/**\r
+ Searches all the available firmware volumes and returns the file device path of first matching\r
+ FFS section.\r
+\r
+ This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid.\r
+ The order that the firmware volumes is searched is not deterministic. For each FFS file found a search\r
+ is made for FFS sections of type SectionType.\r
+\r
+ If SectionType is EFI_SECTION_TE, and the search with an FFS file fails,\r
+ the search will be retried with a section type of EFI_SECTION_PE32.\r
+ This function must be called with a TPL <= TPL_NOTIFY.\r
+\r
+ If NameGuid is NULL, then ASSERT().\r
+\r
+ @param NameGuid A pointer to to the FFS filename GUID to search for\r
+ within any of the firmware volumes in the platform.\r
+ @param SectionType Indicates the FFS section type to search for within\r
+ the FFS file specified by NameGuid.\r
+ @param SectionInstance Indicates which section instance within the FFS file\r
+ specified by NameGuid to retrieve.\r
+ @param FvFileDevicePath Device path for the target FFS\r
+ file.\r
+\r
+ @retval EFI_SUCCESS The specified file device path of FFS section was returned.\r
+ @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found.\r
+ @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a\r
+ device error.\r
+ @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the\r
+ firmware volume that contains the matching FFS section does not\r
+ allow reads.\r
+ @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GetFileDevicePathFromAnyFv (\r
+ IN CONST EFI_GUID *NameGuid,\r
+ IN EFI_SECTION_TYPE SectionType,\r
+ IN UINTN SectionInstance,\r
+ OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath\r
+ )\r
+{\r
+ EFI_STATUS Status;\r
+ EFI_HANDLE *HandleBuffer;\r
+ UINTN HandleCount;\r
+ UINTN Index;\r
+ EFI_HANDLE FvHandle;\r
+ EFI_DEVICE_PATH_PROTOCOL *FvDevicePath;\r
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *TempFvFileDevicePath;\r
+ VOID *Buffer;\r
+ UINTN Size;\r
+\r
+ if (FvFileDevicePath == NULL) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ HandleBuffer = NULL;\r
+ FvDevicePath = NULL;\r
+ TempFvFileDevicePath = NULL;\r
+ Buffer = NULL;\r
+ Size = 0;\r
+\r
+ //\r
+ // Search the FV that contain the caller's FFS first.\r
+ // FV builder can choose to build FFS into the this FV\r
+ // so that this implementation of GetSectionFromAnyFv\r
+ // will locate the FFS faster.\r
+ //\r
+ FvHandle = InternalImageHandleToFvHandle (gImageHandle);\r
+ Status = InternalGetSectionFromFv (\r
+ FvHandle,\r
+ NameGuid,\r
+ SectionType,\r
+ SectionInstance,\r
+ &Buffer,\r
+ &Size\r
+ );\r
+ if (!EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ Status = gBS->LocateHandleBuffer (\r
+ ByProtocol,\r
+ &gEfiFirmwareVolume2ProtocolGuid,\r
+ NULL,\r
+ &HandleCount,\r
+ &HandleBuffer\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto Done;\r
+ }\r
+\r
+ for (Index = 0; Index < HandleCount; Index++) {\r
+ //\r
+ // Skip the FV that contain the caller's FFS\r
+ //\r
+ if (HandleBuffer[Index] != FvHandle) {\r
+ Status = InternalGetSectionFromFv (\r
+ HandleBuffer[Index],\r
+ NameGuid,\r
+ SectionType,\r
+ SectionInstance,\r
+ &Buffer,\r
+ &Size\r
+ );\r
+\r
+ if (!EFI_ERROR (Status)) {\r
+ //\r
+ // Update FvHandle to the current handle.\r
+ //\r
+ FvHandle = HandleBuffer[Index];\r
+ goto Done;\r
+ }\r
+ }\r
+ }\r
+\r
+ if (Index == HandleCount) {\r
+ Status = EFI_NOT_FOUND;\r
+ }\r
+\r
+Done:\r
+ if (Status == EFI_SUCCESS) {\r
+ //\r
+ // Build a device path to the file in the FV to pass into gBS->LoadImage\r
+ //\r
+ Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath);\r
+ if (EFI_ERROR (Status)) {\r
+ *FvFileDevicePath = NULL;\r
+ } else {\r
+ TempFvFileDevicePath = AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + END_DEVICE_PATH_LENGTH);\r
+ if (TempFvFileDevicePath == NULL) {\r
+ *FvFileDevicePath = NULL;\r
+ return EFI_OUT_OF_RESOURCES;\r
+ }\r
+\r
+ EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempFvFileDevicePath, NameGuid);\r
+ SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath));\r
+ *FvFileDevicePath = AppendDevicePath (\r
+ FvDevicePath,\r
+ (EFI_DEVICE_PATH_PROTOCOL *)TempFvFileDevicePath\r
+ );\r
+ FreePool (TempFvFileDevicePath);\r
+ }\r
+ }\r
+\r
+ if (Buffer != NULL) {\r
+ FreePool (Buffer);\r
+ }\r
+\r
+ if (HandleBuffer != NULL) {\r
+ FreePool (HandleBuffer);\r
+ }\r
+\r
+ return Status;\r
+}\r