Dear MdeModulePkg maintainers, Please see attached patch. I follow the suggestions from previous email thread and update the patch.
MdeModulePkg : Add a new DxeServicesLib GetFileDevicePathFromAnyFv () function Contributed-under: TianoCore Contribution Agreement 1.0 From: Shia Cinnamon <cinnamon.s...@hpe.com> Signed-off-by: Wang Nickle <nickle.w...@hpe.com> -- MdePkg/Include/Library/DxeServicesLib.h | 43 +++++++ MdePkg/Library/DxeServicesLib/DxeServicesLib.c | 156 +++++++++++++++++++++++++ 2 files changed, 199 insertions(+) diff --git a/MdePkg/Include/Library/DxeServicesLib.h b/MdePkg/Include/Library/DxeServicesLib.h index e01dd49..79d880d 100644 --- a/MdePkg/Include/Library/DxeServicesLib.h +++ b/MdePkg/Include/Library/DxeServicesLib.h @@ -3,6 +3,7 @@ These functions help access data from sections of FFS files or from file path. Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> This program and the accompanying materials are licensed and made available under the terms and conditions of the BSD License that accompanies this distribution. The full text of the license may be found at @@ -262,5 +263,47 @@ GetFileBufferByFilePath ( OUT UINT32 *AuthenticationStatus ); +/** + Searches all the available firmware volumes and returns the file device path of first matching + FFS section. + + This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid. + The order that the firmware volumes is searched is not deterministic. For each FFS file found a search + is made for FFS sections of type SectionType. + + 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 NameGuid is NULL, then ASSERT(). + + @param NameGuid A pointer to to the FFS filename GUID to search for + within any of the firmware volumes in the platform. + @param SectionType Indicates the FFS section type to search for within + the FFS file specified by NameGuid. + @param SectionInstance Indicates which section instance within the FFS file + specified by NameGuid to retrieve. + @param FvFileDevicePath Device path for the target FFS + file. + + @retval EFI_SUCCESS The specified file device path of FFS section was returned. + @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found. + @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. + @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL. + +**/ +EFI_STATUS +EFIAPI +GetFileDevicePathFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath + ); + #endif diff --git a/MdePkg/Library/DxeServicesLib/DxeServicesLib.c b/MdePkg/Library/DxeServicesLib/DxeServicesLib.c index c8f0014..10f6042 100644 --- a/MdePkg/Library/DxeServicesLib/DxeServicesLib.c +++ b/MdePkg/Library/DxeServicesLib/DxeServicesLib.c @@ -3,6 +3,7 @@ These functions help access data from sections of FFS files or from file path. Copyright (c) 2007 - 2015, Intel Corporation. All rights reserved.<BR> +(C) Copyright 2015 Hewlett Packard Enterprise Development LP<BR> 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 @@ -927,3 +928,158 @@ Finish: return ImageBuffer; } + +/** + Searches all the available firmware volumes and returns the file device path of first matching + FFS section. + + This function searches all the firmware volumes for FFS files with an FFS filename specified by NameGuid. + The order that the firmware volumes is searched is not deterministic. For each FFS file found a search + is made for FFS sections of type SectionType. + + 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 NameGuid is NULL, then ASSERT(). + + @param NameGuid A pointer to to the FFS filename GUID to search for + within any of the firmware volumes in the platform. + @param SectionType Indicates the FFS section type to search for within + the FFS file specified by NameGuid. + @param SectionInstance Indicates which section instance within the FFS file + specified by NameGuid to retrieve. + @param FvFileDevicePath Device path for the target FFS + file. + + @retval EFI_SUCCESS The specified file device path of FFS section was returned. + @retval EFI_NOT_FOUND The specified file device path of FFS section could not be found. + @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. + @retval EFI_INVALID_PARAMETER FvFileDevicePath is NULL. + +**/ +EFI_STATUS +EFIAPI +GetFileDevicePathFromAnyFv ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, + OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath + ) +{ + EFI_STATUS Status; + EFI_HANDLE *HandleBuffer; + UINTN HandleCount; + UINTN Index; + EFI_HANDLE FvHandle; + EFI_DEVICE_PATH_PROTOCOL *FvDevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *TempFvFileDevicePath; + VOID *Buffer; + UINTN Size; + + if (FvFileDevicePath == NULL) { + return EFI_INVALID_PARAMETER; + } + + HandleBuffer = NULL; + FvDevicePath = NULL; + TempFvFileDevicePath = NULL; + Buffer = NULL; + Size = 0; + + // + // Search the FV that contain the caller's FFS first. + // FV builder can choose to build FFS into the this FV + // so that this implementation of GetSectionFromAnyFv + // will locate the FFS faster. + // + FvHandle = InternalImageHandleToFvHandle (gImageHandle); + Status = InternalGetSectionFromFv ( + FvHandle, + NameGuid, + SectionType, + SectionInstance, + &Buffer, + &Size + ); + if (!EFI_ERROR (Status)) { + goto Done; + } + + Status = gBS->LocateHandleBuffer ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &HandleCount, + &HandleBuffer + ); + if (EFI_ERROR (Status)) { + goto Done; + } + + for (Index = 0; Index < HandleCount; Index++) { + // + // Skip the FV that contain the caller's FFS + // + if (HandleBuffer[Index] != FvHandle) { + Status = InternalGetSectionFromFv ( + HandleBuffer[Index], + NameGuid, + SectionType, + SectionInstance, + &Buffer, + &Size + ); + + if (!EFI_ERROR (Status)) { + // + // Update FvHandle to the current handle. + // + FvHandle = HandleBuffer[Index]; + goto Done; + } + } + } + + if (Index == HandleCount) { + Status = EFI_NOT_FOUND; + } + +Done: + if (Status == EFI_SUCCESS) { + // + // Build a device path to the file in the FV to pass into gBS->LoadImage + // + Status = gBS->HandleProtocol (FvHandle, &gEfiDevicePathProtocolGuid, (VOID **)&FvDevicePath); + if (EFI_ERROR (Status)) { + *FvFileDevicePath = NULL; + } else { + TempFvFileDevicePath = AllocateZeroPool (sizeof (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH) + END_DEVICE_PATH_LENGTH); + if (TempFvFileDevicePath == NULL) { + *FvFileDevicePath = NULL; + return EFI_OUT_OF_RESOURCES; + } + EfiInitializeFwVolDevicepathNode ((MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)TempFvFileDevicePath, NameGuid); + SetDevicePathEndNode (NextDevicePathNode (TempFvFileDevicePath)); + *FvFileDevicePath = AppendDevicePath ( + FvDevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)TempFvFileDevicePath + ); + FreePool (TempFvFileDevicePath); + } + } + + if (Buffer != NULL) { + FreePool (Buffer); + } + + if (HandleBuffer != NULL) { + FreePool (HandleBuffer); + } + + return Status; +} -- 2.5.1.windows.1 From: Shia, Cinnamon Sent: Friday, December 12, 2014 11:01 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hello Feng and Mike, After rethinking about the your proposal, it looks great and make sense to me. Will submit a new patch later. Thanks! Thanks, Cinnamon Shia From: Kinney, Michael D [mailto:michael.d.kin...@intel.com] Sent: Friday, December 12, 2014 2:03 AM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Cinnamon Shia, I think the original proposal would read the FFS file contents twice. Since the new API being proposed returns the Device Path to the FFS file in a specific FV, LoadImage() will not search. It knows from the Device Patch exactly where to load the FFS file from. Mike From: Shia, Cinnamon [mailto:cinnamon.s...@hp.com] Sent: Thursday, December 11, 2014 6:55 AM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hello Feng, After checking the usage of LoadImage(), your new proposal makes sense to me. If SourceBuffer is NULL, the function is a file copy operation that uses the EFI_SIMPLE_FILE_SYSTEM_PROTOCOL. My concern is that searching all the firmware volumes for FFS files will be done twice. (One is from GetSectionFromAnyFvEx() and the other one is from LoadImage().) Thanks, Cinnamon Shia From: Shia, Cinnamon Sent: Thursday, December 11, 2014 9:18 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hello Feng, If I understand your proposal correctly, for loading and starting an image from FVs, we have to call GetSectionFromAnyFv to load the section to memory, and then call GetSectionFromAnyFvEx to get the device path, right? If so, it means searching all the firmware volumes for FFS files will be done twice. The thought for the original proposal is that It doesn't affect the existing code: For the case of loading/starting an image from FVs, we can use GetSectionFromAnyFvEx. In other cases, we can call GetSectionFromAnyFv(). Your feedback is appreciated. Thanks, Cinnamon Shia From: Tian, Feng [mailto:feng.t...@intel.com] Sent: Wednesday, December 10, 2014 10:32 AM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hi, Samer and Cinnamon, After internal discussion on your usage model, we suggest to only return FvFileDevicePath and not return Buffer and Size at new API, that's +EFI_STATUS +EFIAPI +GetSectionFromAnyFvEx ( + IN CONST EFI_GUID *NameGuid, + IN EFI_SECTION_TYPE SectionType, + IN UINTN SectionInstance, - OUT VOID **Buffer, - OUT UINTN *Size, + OUT EFI_DEVICE_PATH_PROTOCOL **FvFileDevicePath + ); Of course you can propose a new func name for this new API:) Thanks Feng From: Tian, Feng Sent: Monday, December 08, 2014 09:43 To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Cc: Tian, Feng Subject: RE: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Samer and Cinnamon, I am not sure if it's valuable for being a library service. Look like you can put the constructing of the device patch outside the GetSectionFromAnyFvEx() also. Anyway I have known your usage model now. Let me raise it to internal for more discussions. PS: Why do other APIs in DxeSerivceLib have no such Ex() extensions? Thanks Feng From: El-Haj-Mahmoud, Samer [mailto:samer.el-haj-mahm...@hp.com] Sent: Saturday, December 06, 2014 03:25 To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Feng, In addition to Secure Boot, there are other use cases where an application would like to identify where it was loaded from (by examining the device path of the image). Without this change, an application embedded in an FV does not get its device path passed to it using the Image Load service. From: Shia, Cinnamon Sent: Wednesday, December 03, 2014 9:41 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATHCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hello Feng, Thanks for your reply. The problem is that if secure boot is enabled, the loadImage() needs device paths to determine where the image is. If a NULL device path is passed, it would be treated as an invalid image by DxeImageVerificationHandler(), which is called in LoadImage(). Thanks, Cinnamon Shia From: Tian, Feng [mailto:feng.t...@intel.com] Sent: Tuesday, December 02, 2014 1:18 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hi, Samer If it's such usage case, why you don't use the below logic? Status = GetSectionFromAnyFv ( &AppGuid, EFI_SECTION_PE32, 0, &AppImageBase, &AppImageSize ); Status = gBS->LoadImage ( TRUE, gImageHandle, NULL, AppImageBase, AppImageSize, &ImageHandle ); Status = gBS->StartImage (ImageHandle, NULL, NULL); It doesn't need construct device path at all. Thanks Feng From: El-Haj-Mahmoud, Samer [mailto:samer.el-haj-mahm...@hp.com] Sent: Tuesday, December 02, 2014 03:22 To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function One possible usage is to be able to load an application from a FV. * Need to search for the EFI application in all FVs using GetSectionFromAnyFvEx() * Once found, the file is loaded from FV to memory (in Buffer and Size outputs of GetSectionFromAnyFvEx() * We then need to load and start the image using gBS->LoadImage() and gBS->StartImage() * Load image has a DevicePath input parameter of where the image is loaded from The original GetSectionFromAnyFv() did not return the device path and was not suitable for this use case. Thanks, --Samer From: Tian, Feng [mailto:feng.t...@intel.com] Sent: Tuesday, November 25, 2014 6:24 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Hi, Samer As your proposed patch involves interface change, we need review it carefully and the response may be slow. Could you let me know at which case/usage model you need to get this FV file's device path? Thanks Feng From: El-Haj-Mahmoud, Samer [mailto:samer.el-haj-mahm...@hp.com] Sent: Wednesday, November 26, 2014 06:28 To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: Re: [edk2] [PATCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Resending with actual patch file Thanks, --Samer From: El-Haj-Mahmoud, Samer Sent: Tuesday, November 25, 2014 4:24 PM To: edk2-de...@lists.sourceforge.net<mailto:edk2-de...@lists.sourceforge.net> Subject: [PATCH] MdeModulePkg : Add a new DxeServicesLib GetSectionFromAnyFvEx() function Dear MdeModulePkg maintainers, Please see attached patch Add a new DxeServicesLib function GetSectionFromAnyFvEx() to search all firmware volumes for A specified FFS file, and return the first matching FFS section. The function is identical to GetSectionFromAnyFv(), but it also returns a pointer to the FV file device path. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Samer El-Haj-Mahmoud el...@hp.com<mailto:el...@hp.com> Thanks, Samer El-Haj-Mahmoud System Firmware Architect HP Servers el...@hp.com<mailto:el...@hp.com> T +1.281.514.5973 C +1.512.659.1523 Hewlett-Packard Company hp.com/go/proliant/uefi<http://hp.com/go/proliant/uefi> [Description: Description: C:\Users\elhajmah\HpLogo.png] _______________________________________________ edk2-devel mailing list edk2-devel@lists.01.org https://lists.01.org/mailman/listinfo/edk2-devel