From 682cee4c06ed1b7961a966135a8be1f92d6c5c89 Mon Sep 17 00:00:00 2001 From: lgao4 Date: Wed, 5 May 2010 01:56:41 +0000 Subject: [PATCH] Add new API GetSectionFromAnyFvByFileType() into MdePkg DxeServicesLib. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@10456 6f19259b-4bc3-4df7-8a09-765794883524 --- MdePkg/Include/Library/DxeServicesLib.h | 50 +++++++ .../Library/DxeServicesLib/DxeServicesLib.c | 134 ++++++++++++++++++ .../Library/DxeServicesLib/DxeServicesLib.inf | 2 +- 3 files changed, 185 insertions(+), 1 deletion(-) diff --git a/MdePkg/Include/Library/DxeServicesLib.h b/MdePkg/Include/Library/DxeServicesLib.h index e3536687e1..596487da57 100644 --- a/MdePkg/Include/Library/DxeServicesLib.h +++ b/MdePkg/Include/Library/DxeServicesLib.h @@ -16,6 +16,56 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #ifndef __DXE_SERVICES_LIB_H__ #define __DXE_SERVICES_LIB_H__ +/** + Searches all the available firmware volumes and returns the first matching FFS section. + + This function searches all the firmware volumes for FFS files with FV file type specified by FileType + The order that the firmware volumes is searched is not deterministic. For each available FV a search + is made for FFS file of type FileType. If the FV contains more than one FFS file with the same FileType, + the FileInstance instance will be the matched FFS file. For each FFS file found a search + is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances + of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocated buffer. + See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections + are retrieved from an FFS file based on SectionType and SectionInstance. + + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + @param FileType Indicates the FV file type to search for within all available FVs. + @param FileInstance Indicates which file instance within all available FVs specified by FileType. + FileInstance starts from zero. + @param SectionType Indicates the FFS section type to search for within the FFS file + specified by FileType with FileInstance. + @param SectionInstance Indicates which section instance within the FFS file + specified by FileType with FileInstance to retrieve. SectionInstance starts from zero. + @param Buffer On output, a pointer to a callee allocated buffer containing the FFS file section that was found. + Is it the caller's responsibility to free this buffer using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the firmware volume that + contains the matching FFS section does not allow reads. +**/ +EFI_STATUS +EFIAPI +GetSectionFromAnyFvByFileType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN FileInstance, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ); + /** Searches all the available firmware volumes and returns the first matching FFS section. diff --git a/MdePkg/Library/DxeServicesLib/DxeServicesLib.c b/MdePkg/Library/DxeServicesLib/DxeServicesLib.c index 49c9ad492e..9588008cdc 100644 --- a/MdePkg/Library/DxeServicesLib/DxeServicesLib.c +++ b/MdePkg/Library/DxeServicesLib/DxeServicesLib.c @@ -166,7 +166,141 @@ InternalGetSectionFromFv ( return Status; } +/** + Searches all the available firmware volumes and returns the first matching FFS section. + This function searches all the firmware volumes for FFS files with FV file type specified by FileType + The order that the firmware volumes is searched is not deterministic. For each available FV a search + is made for FFS file of type FileType. If the FV contains more than one FFS file with the same FileType, + the FileInstance instance will be the matched FFS file. For each FFS file found a search + is made for FFS sections of type SectionType. If the FFS file contains at least SectionInstance instances + of the FFS section specified by SectionType, then the SectionInstance instance is returned in Buffer. + Buffer is allocated using AllocatePool(), and the size of the allocated buffer is returned in Size. + It is the caller's responsibility to use FreePool() to free the allocated buffer. + See EFI_FIRMWARE_VOLUME2_PROTOCOL.ReadSection() for details on how sections + are retrieved from an FFS file based on SectionType and SectionInstance. + + If SectionType is EFI_SECTION_TE, and the search with an FFS file fails, + the search will be retried with a section type of EFI_SECTION_PE32. + This function must be called with a TPL <= TPL_NOTIFY. + + If Buffer is NULL, then ASSERT(). + If Size is NULL, then ASSERT(). + + @param FileType Indicates the FV file type to search for within all available FVs. + @param FileInstance Indicates which file instance within all available FVs specified by FileType. + FileInstance starts from zero. + @param SectionType Indicates the FFS section type to search for within the FFS file + specified by FileType with FileInstance. + @param SectionInstance Indicates which section instance within the FFS file + specified by FileType with FileInstance to retrieve. SectionInstance starts from zero. + @param Buffer On output, a pointer to a callee allocated buffer containing the FFS file section that was found. + Is it the caller's responsibility to free this buffer using FreePool(). + @param Size On output, a pointer to the size, in bytes, of Buffer. + + @retval EFI_SUCCESS The specified FFS section was returned. + @retval EFI_NOT_FOUND The specified FFS section could not be found. + @retval EFI_OUT_OF_RESOURCES There are not enough resources available to retrieve the matching FFS section. + @retval EFI_DEVICE_ERROR The FFS section could not be retrieves due to a device error. + @retval EFI_ACCESS_DENIED The FFS section could not be retrieves because the firmware volume that + contains the matching FFS section does not allow reads. +**/ +EFI_STATUS +EFIAPI +GetSectionFromAnyFvByFileType ( + IN EFI_FV_FILETYPE FileType, + IN UINTN FileInstance, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT VOID **Buffer, + OUT UINTN *Size + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN IndexFv; + UINTN IndexFile; + UINTN Key; + EFI_GUID NameGuid; + EFI_FV_FILE_ATTRIBUTES Attributes; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + + // + // Locate all available FVs. + // + HandleBuffer = NULL; + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // Go through FVs one by one to find the required section data. + // + for (IndexFv = 0; IndexFv < HandleCount; IndexFv++) { + Status = gBS->HandleProtocol ( + HandleBuffer[IndexFv], + &gEfiFirmwareVolume2ProtocolGuid, + (VOID **)&Fv + ); + if (EFI_ERROR (Status)) { + continue; + } + + // + // Use Firmware Volume 2 Protocol to search for a file of type FileType in all FVs. + // + IndexFile = FileInstance + 1; + Key = 0; + do { + Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, Size); + if (EFI_ERROR (Status)) { + break; + } + IndexFile --; + } while (IndexFile > 0); + + // + // Fv File with the required FV file type is found. + // Search the section file in the found FV file. + // + if (IndexFile == 0) { + Status = InternalGetSectionFromFv ( + HandleBuffer[IndexFv], + &NameGuid, + SectionType, + SectionInstance, + Buffer, + Size + ); + + if (!EFI_ERROR (Status)) { + goto Done; + } + } + } + + // + // The required FFS section file is not found. + // + if (IndexFv == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + if (HandleBuffer != NULL) { + FreePool(HandleBuffer); + } + + return Status; +} /** Searches all the availables firmware volumes and returns the first matching FFS section. diff --git a/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf b/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf index 2941816fb5..4db553b54a 100644 --- a/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf +++ b/MdePkg/Library/DxeServicesLib/DxeServicesLib.inf @@ -21,7 +21,7 @@ FILE_GUID = EE680C58-FFC0-4a5d-858F-66FF9C84BC9F MODULE_TYPE = DXE_DRIVER VERSION_STRING = 1.0 - LIBRARY_CLASS = DxeServicesLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER UEFI_APPLICATION UEFI_DRIVER + LIBRARY_CLASS = DxeServicesLib|DXE_CORE DXE_DRIVER DXE_RUNTIME_DRIVER DXE_SAL_DRIVER DXE_SMM_DRIVER SMM_CORE UEFI_APPLICATION UEFI_DRIVER # # VALID_ARCHITECTURES = IA32 X64 IPF EBC