diff options
Diffstat (limited to 'MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c')
| -rw-r--r-- | MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c | 852 |
1 files changed, 426 insertions, 426 deletions
diff --git a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c index 9f898e38e4..9817a3a0a1 100644 --- a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c +++ b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c @@ -1,426 +1,426 @@ -/** @file
- Produce Load File Protocol for UEFI Applications in Firmware Volumes
-
- Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>
- SPDX-License-Identifier: BSD-2-Clause-Patent
-
-**/
-
-#include <PiDxe.h>
-
-#include <Guid/LzmaDecompress.h>
-#include <Protocol/LoadFile.h>
-#include <Protocol/DevicePath.h>
-#include <Protocol/FirmwareVolume2.h>
-#include <Protocol/FirmwareVolumeBlock.h>
-
-#include <Library/DebugLib.h>
-#include <Library/UefiLib.h>
-#include <Library/BaseMemoryLib.h>
-#include <Library/UefiDriverEntryPoint.h>
-#include <Library/UefiBootServicesTableLib.h>
-#include <Library/MemoryAllocationLib.h>
-#include <Library/DevicePathLib.h>
-
-#define LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('l', 'f', 'f', 'v')
-
-typedef struct {
- UINTN Signature;
- EFI_LOAD_FILE_PROTOCOL LoadFile;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
- EFI_GUID NameGuid;
- LIST_ENTRY Link;
-} LOAD_FILE_ON_FV2_PRIVATE_DATA;
-
-#define LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_THIS(a) CR (a, LOAD_FILE_ON_FV2_PRIVATE_DATA, LoadFile, LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE)
-#define LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_LINK(a) CR (a, LOAD_FILE_ON_FV2_PRIVATE_DATA, Link, LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE)
-
-VOID *mFvRegistration;
-LIST_ENTRY mPrivateDataList;
-
-/**
- Causes the driver to load a specified file from firmware volume.
-
- @param[in] This Protocol instance pointer.
- @param[in] FilePath The device specific path of the file to load.
- @param[in] BootPolicy If TRUE, indicates that the request originates from the
- boot manager is attempting to load FilePath as a boot
- selection. If FALSE, then FilePath must match an exact file
- to be loaded.
- @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return
- code of EFI_SUCCESS, the amount of data transferred to
- Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL,
- the size of Buffer required to retrieve the requested file.
- @param[in] Buffer The memory buffer to transfer the file to. IF Buffer is NULL,
- then no the size of the requested file is returned in
- BufferSize.
-
- @retval EFI_SUCCESS The file was loaded.
- @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy.
- @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or
- BufferSize is NULL.
- @retval EFI_DEVICE_ERROR The file was not loaded due to a device error.
- @retval EFI_NOT_FOUND The file was not found.
- @retval EFI_OUT_OF_RESOURCES An allocation failure occurred.
- @retval EFI_ACCESS_DENIED The firmware volume is configured to
- disallow reads.
-**/
-EFI_STATUS
-EFIAPI
-LoadFileOnFv2LoadFile (
- IN EFI_LOAD_FILE_PROTOCOL *This,
- IN EFI_DEVICE_PATH_PROTOCOL *FilePath,
- IN BOOLEAN BootPolicy,
- IN OUT UINTN *BufferSize,
- IN VOID *Buffer OPTIONAL
- )
-{
- EFI_STATUS Status;
- LOAD_FILE_ON_FV2_PRIVATE_DATA *Private;
- VOID *Pe32Buffer;
- UINTN Pe32BufferSize;
- UINT32 AuthenticationStatus;
-
- if ((This == NULL) || (BufferSize == NULL)) {
- return EFI_INVALID_PARAMETER;
- }
-
- //
- // Only support BootPolicy
- //
- if (!BootPolicy) {
- return EFI_UNSUPPORTED;
- }
-
- //
- // Get private context data
- //
- Private = LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_THIS (This);
-
- //
- // Determine the size of the PE32 section
- //
- Pe32Buffer = NULL;
- Pe32BufferSize = 0;
- Status = Private->Fv->ReadSection (
- Private->Fv,
- &Private->NameGuid,
- EFI_SECTION_PE32,
- 0,
- &Pe32Buffer,
- &Pe32BufferSize,
- &AuthenticationStatus
- );
- if (EFI_ERROR (Status)) {
- return Status;
- }
-
- //
- // If the buffer passed in is not large enough, return the size of the required
- // buffer in BufferSize and return EFI_BUFFER_TOO_SMALL
- //
- if ((*BufferSize < Pe32BufferSize) || (Buffer == NULL)) {
- *BufferSize = Pe32BufferSize;
- return EFI_BUFFER_TOO_SMALL;
- }
-
- //
- // The buffer passed in is large enough, so read the PE32 section directly into
- // the buffer, update BufferSize with the actual size read, and return the status
- // from ReadSection()
- //
- return Private->Fv->ReadSection (
- Private->Fv,
- &Private->NameGuid,
- EFI_SECTION_PE32,
- 0,
- &Buffer,
- BufferSize,
- &AuthenticationStatus
- );
-}
-
-LOAD_FILE_ON_FV2_PRIVATE_DATA mLoadFileOnFv2PrivateDataTemplate = {
- LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE,
- {
- LoadFileOnFv2LoadFile
- }
-};
-
-/**
- Check if the FFS has been installed LoadFileProtocol for it.
-
- @param[in] NameGuid Point to FFS File GUID to be checked.
-
- @retval TRUE The FFS's FileLoadProtocol is in list.
- @retval FALSE The FFS's FileLoadProtocol is not in list.
-
-**/
-BOOLEAN
-EFIAPI
-IsInPrivateList (
- IN EFI_GUID *NameGuid
- )
-{
- LIST_ENTRY *Entry;
- LOAD_FILE_ON_FV2_PRIVATE_DATA *PrivateData;
-
- if (IsListEmpty (&mPrivateDataList)) {
- return FALSE;
- }
-
- for (Entry = (&mPrivateDataList)->ForwardLink; Entry != (&mPrivateDataList); Entry = Entry->ForwardLink) {
- PrivateData = LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_LINK (Entry);
- if (CompareGuid (NameGuid, &PrivateData->NameGuid)) {
- DEBUG ((DEBUG_INFO, "LoadFileOnFv2:FileLoadProtocol has been installed in:%g\n", NameGuid));
- return TRUE;
- }
- }
-
- return FALSE;
-}
-
-/**
- Create file device path based on FFS file GUID and UI name.
-
- @param Device Handle to Firmware Volume.
- @param NameGuid Point to FFS file GUID.
- @param FileName Point to FFS UI section name.
-
- @return the combined device path
-**/
-EFI_DEVICE_PATH_PROTOCOL *
-EFIAPI
-CreateFileDevicePath (
- IN EFI_HANDLE Device,
- IN EFI_GUID *NameGuid,
- IN CONST CHAR16 *FileName
- )
-{
- UINTN Size;
- FILEPATH_DEVICE_PATH *FilePath;
- EFI_DEVICE_PATH_PROTOCOL *DevicePath;
- EFI_DEVICE_PATH_PROTOCOL *FileDevicePath;
- MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode;
-
- EfiInitializeFwVolDevicepathNode (&FileNode, NameGuid);
- DevicePath = AppendDevicePathNode (
- DevicePathFromHandle (Device),
- (EFI_DEVICE_PATH_PROTOCOL *)&FileNode
- );
-
- Size = StrSize (FileName);
- FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH);
- if (FileDevicePath != NULL) {
- FilePath = (FILEPATH_DEVICE_PATH *)FileDevicePath;
- FilePath->Header.Type = MEDIA_DEVICE_PATH;
- FilePath->Header.SubType = MEDIA_FILEPATH_DP;
- CopyMem (&FilePath->PathName, FileName, Size);
- SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH);
- SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header));
-
- DevicePath = AppendDevicePath (DevicePath, FileDevicePath);
- FreePool (FileDevicePath);
- }
-
- return DevicePath;
-}
-
-/**
- Install LoadFile Protocol for Application FFS.
-
- @param Handle FV Handle.
-
-**/
-VOID
-EFIAPI
-InstallFileLoadProtocol (
- EFI_HANDLE Handle
- )
-{
- EFI_STATUS Status;
- LOAD_FILE_ON_FV2_PRIVATE_DATA *Private;
- EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv;
- EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb;
- EFI_PHYSICAL_ADDRESS Address;
- EFI_FV_FILETYPE FileType;
- UINTN Key;
- EFI_GUID NameGuid;
- EFI_FV_FILE_ATTRIBUTES Attributes;
- UINTN Size;
- EFI_HANDLE LoadFileHandle;
- UINT32 AuthenticationStatus;
- CHAR16 *UiName;
- UINTN UiNameSize;
-
- DEBUG ((DEBUG_INFO, "LoadFileOnFv2:Find a FV!\n"));
- Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv);
- ASSERT_EFI_ERROR (Status);
- Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb);
- Fvb->GetPhysicalAddress (Fvb, &Address);
- DEBUG ((DEBUG_INFO, "LoadFileOnFv2:Fvb->Address=%x \n", Address));
-
- //
- // Use Firmware Volume 2 Protocol to search for a FFS files of type
- // EFI_FV_FILETYPE_APPLICATION and produce a LoadFile protocol for
- // each one found.
- //
- FileType = EFI_FV_FILETYPE_APPLICATION;
- Key = 0;
- while (TRUE) {
- Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, &Size);
- if (EFI_ERROR (Status)) {
- break;
- }
-
- UiName = NULL;
- Status = Fv->ReadSection (
- Fv,
- &NameGuid,
- EFI_SECTION_USER_INTERFACE,
- 0,
- (VOID **)&UiName,
- &UiNameSize,
- &AuthenticationStatus
- );
- if (EFI_ERROR (Status)) {
- continue;
- }
-
- if (!IsInPrivateList (&NameGuid)) {
- Private = (LOAD_FILE_ON_FV2_PRIVATE_DATA *)AllocateCopyPool (sizeof (mLoadFileOnFv2PrivateDataTemplate), &mLoadFileOnFv2PrivateDataTemplate);
- ASSERT (Private != NULL);
- Private->Fv = Fv;
- Private->DevicePath = CreateFileDevicePath (Handle, &NameGuid, UiName);
- CopyGuid (&Private->NameGuid, &NameGuid);
- LoadFileHandle = NULL;
- DEBUG ((DEBUG_INFO, "Find a APPLICATION in this FV!\n"));
- Status = gBS->InstallMultipleProtocolInterfaces (
- &LoadFileHandle,
- &gEfiDevicePathProtocolGuid,
- Private->DevicePath,
- &gEfiLoadFileProtocolGuid,
- &Private->LoadFile,
- NULL
- );
- if (!EFI_ERROR (Status)) {
- InsertTailList (&mPrivateDataList, &Private->Link);
- } else {
- DEBUG ((DEBUG_ERROR, "Application with the same name %s has been installed.!\n", UiName));
- FreePool (Private->DevicePath);
- FreePool (Private);
- }
- }
- }
-}
-
-/**
- This notification function is invoked when an instance of the
- LzmaCustomDecompressGuid is produced. It installs another instance of the
- EFI_FIRMWARE_VOLUME_PROTOCOL on the handle of the FFS. This notification function
- also handles the situation when LZMA decoder driver loaded later than FirmwareVolume driver.
-
- @param Event The event that occurred
- @param Context Context of event. Not used in this nofication function.
-
-**/
-VOID
-EFIAPI
-FvNotificationEvent (
- IN EFI_EVENT Event,
- IN VOID *Context
- )
-{
- EFI_STATUS Status;
- UINTN BufferSize;
- EFI_HANDLE *Handle;
- UINTN Index;
- EFI_HANDLE *CurHandle;
-
- Handle = NULL;
- Index = 0;
- BufferSize = sizeof (EFI_HANDLE);
- Handle = AllocateZeroPool (BufferSize);
- if (Handle == NULL) {
- return;
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- &BufferSize,
- Handle
- );
- if (EFI_BUFFER_TOO_SMALL == Status) {
- FreePool (Handle);
- Handle = AllocateZeroPool (BufferSize);
- if (Handle == NULL) {
- return;
- }
-
- Status = gBS->LocateHandle (
- ByProtocol,
- &gEfiFirmwareVolume2ProtocolGuid,
- NULL,
- &BufferSize,
- Handle
- );
- if (EFI_ERROR (Status)) {
- return;
- }
- } else if (EFI_ERROR (Status)) {
- return;
- }
-
- CurHandle = Handle;
- for (Index = 0; Index < BufferSize/sizeof (EFI_HANDLE); Index++) {
- CurHandle = Handle + Index;
- //
- // Install LoadFile Protocol
- //
- InstallFileLoadProtocol (*CurHandle);
- }
-
- if (Handle != NULL) {
- FreePool (Handle);
- }
-}
-
-/**
- Entry point function initializes global variables and installs notifications.
-
- @param[in] ImageHandle The firmware allocated handle for the EFI image.
- @param[in] SystemTable A pointer to the EFI System Table.
-
- @retval EFI_SUCCESS The entry point is executed successfully.
- @retval other Some error occurs when executing this entry point.
-**/
-EFI_STATUS
-EFIAPI
-LoadFileOnFv2Intialize (
- IN EFI_HANDLE ImageHandle,
- IN EFI_SYSTEM_TABLE *SystemTable
- )
-{
- InitializeListHead (&mPrivateDataList);
-
- EfiCreateProtocolNotifyEvent (
- &gEfiFirmwareVolume2ProtocolGuid,
- TPL_CALLBACK,
- FvNotificationEvent,
- NULL,
- &mFvRegistration
- );
-
- EfiCreateProtocolNotifyEvent (
- &gLzmaCustomDecompressGuid,
- TPL_CALLBACK,
- FvNotificationEvent,
- NULL,
- &mFvRegistration
- );
-
- return EFI_SUCCESS;
-}
+/** @file + Produce Load File Protocol for UEFI Applications in Firmware Volumes + + Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR> + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include <PiDxe.h> + +#include <Guid/LzmaDecompress.h> +#include <Protocol/LoadFile.h> +#include <Protocol/DevicePath.h> +#include <Protocol/FirmwareVolume2.h> +#include <Protocol/FirmwareVolumeBlock.h> + +#include <Library/DebugLib.h> +#include <Library/UefiLib.h> +#include <Library/BaseMemoryLib.h> +#include <Library/UefiDriverEntryPoint.h> +#include <Library/UefiBootServicesTableLib.h> +#include <Library/MemoryAllocationLib.h> +#include <Library/DevicePathLib.h> + +#define LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('l', 'f', 'f', 'v') + +typedef struct { + UINTN Signature; + EFI_LOAD_FILE_PROTOCOL LoadFile; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + EFI_GUID NameGuid; + LIST_ENTRY Link; +} LOAD_FILE_ON_FV2_PRIVATE_DATA; + +#define LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_THIS(a) CR (a, LOAD_FILE_ON_FV2_PRIVATE_DATA, LoadFile, LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE) +#define LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_LINK(a) CR (a, LOAD_FILE_ON_FV2_PRIVATE_DATA, Link, LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE) + +VOID *mFvRegistration; +LIST_ENTRY mPrivateDataList; + +/** + Causes the driver to load a specified file from firmware volume. + + @param[in] This Protocol instance pointer. + @param[in] FilePath The device specific path of the file to load. + @param[in] BootPolicy If TRUE, indicates that the request originates from the + boot manager is attempting to load FilePath as a boot + selection. If FALSE, then FilePath must match an exact file + to be loaded. + @param[in, out] BufferSize On input the size of Buffer in bytes. On output with a return + code of EFI_SUCCESS, the amount of data transferred to + Buffer. On output with a return code of EFI_BUFFER_TOO_SMALL, + the size of Buffer required to retrieve the requested file. + @param[in] Buffer The memory buffer to transfer the file to. IF Buffer is NULL, + then no the size of the requested file is returned in + BufferSize. + + @retval EFI_SUCCESS The file was loaded. + @retval EFI_UNSUPPORTED The device does not support the provided BootPolicy. + @retval EFI_INVALID_PARAMETER FilePath is not a valid device path, or + BufferSize is NULL. + @retval EFI_DEVICE_ERROR The file was not loaded due to a device error. + @retval EFI_NOT_FOUND The file was not found. + @retval EFI_OUT_OF_RESOURCES An allocation failure occurred. + @retval EFI_ACCESS_DENIED The firmware volume is configured to + disallow reads. +**/ +EFI_STATUS +EFIAPI +LoadFileOnFv2LoadFile ( + IN EFI_LOAD_FILE_PROTOCOL *This, + IN EFI_DEVICE_PATH_PROTOCOL *FilePath, + IN BOOLEAN BootPolicy, + IN OUT UINTN *BufferSize, + IN VOID *Buffer OPTIONAL + ) +{ + EFI_STATUS Status; + LOAD_FILE_ON_FV2_PRIVATE_DATA *Private; + VOID *Pe32Buffer; + UINTN Pe32BufferSize; + UINT32 AuthenticationStatus; + + if ((This == NULL) || (BufferSize == NULL)) { + return EFI_INVALID_PARAMETER; + } + + // + // Only support BootPolicy + // + if (!BootPolicy) { + return EFI_UNSUPPORTED; + } + + // + // Get private context data + // + Private = LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_THIS (This); + + // + // Determine the size of the PE32 section + // + Pe32Buffer = NULL; + Pe32BufferSize = 0; + Status = Private->Fv->ReadSection ( + Private->Fv, + &Private->NameGuid, + EFI_SECTION_PE32, + 0, + &Pe32Buffer, + &Pe32BufferSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + return Status; + } + + // + // If the buffer passed in is not large enough, return the size of the required + // buffer in BufferSize and return EFI_BUFFER_TOO_SMALL + // + if ((*BufferSize < Pe32BufferSize) || (Buffer == NULL)) { + *BufferSize = Pe32BufferSize; + return EFI_BUFFER_TOO_SMALL; + } + + // + // The buffer passed in is large enough, so read the PE32 section directly into + // the buffer, update BufferSize with the actual size read, and return the status + // from ReadSection() + // + return Private->Fv->ReadSection ( + Private->Fv, + &Private->NameGuid, + EFI_SECTION_PE32, + 0, + &Buffer, + BufferSize, + &AuthenticationStatus + ); +} + +LOAD_FILE_ON_FV2_PRIVATE_DATA mLoadFileOnFv2PrivateDataTemplate = { + LOAD_FILE_ON_FV2_PRIVATE_DATA_SIGNATURE, + { + LoadFileOnFv2LoadFile + } +}; + +/** + Check if the FFS has been installed LoadFileProtocol for it. + + @param[in] NameGuid Point to FFS File GUID to be checked. + + @retval TRUE The FFS's FileLoadProtocol is in list. + @retval FALSE The FFS's FileLoadProtocol is not in list. + +**/ +BOOLEAN +EFIAPI +IsInPrivateList ( + IN EFI_GUID *NameGuid + ) +{ + LIST_ENTRY *Entry; + LOAD_FILE_ON_FV2_PRIVATE_DATA *PrivateData; + + if (IsListEmpty (&mPrivateDataList)) { + return FALSE; + } + + for (Entry = (&mPrivateDataList)->ForwardLink; Entry != (&mPrivateDataList); Entry = Entry->ForwardLink) { + PrivateData = LOAD_FILE_ON_FV2_PRIVATE_DATA_FROM_LINK (Entry); + if (CompareGuid (NameGuid, &PrivateData->NameGuid)) { + DEBUG ((DEBUG_INFO, "LoadFileOnFv2:FileLoadProtocol has been installed in:%g\n", NameGuid)); + return TRUE; + } + } + + return FALSE; +} + +/** + Create file device path based on FFS file GUID and UI name. + + @param Device Handle to Firmware Volume. + @param NameGuid Point to FFS file GUID. + @param FileName Point to FFS UI section name. + + @return the combined device path +**/ +EFI_DEVICE_PATH_PROTOCOL * +EFIAPI +CreateFileDevicePath ( + IN EFI_HANDLE Device, + IN EFI_GUID *NameGuid, + IN CONST CHAR16 *FileName + ) +{ + UINTN Size; + FILEPATH_DEVICE_PATH *FilePath; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + EFI_DEVICE_PATH_PROTOCOL *FileDevicePath; + MEDIA_FW_VOL_FILEPATH_DEVICE_PATH FileNode; + + EfiInitializeFwVolDevicepathNode (&FileNode, NameGuid); + DevicePath = AppendDevicePathNode ( + DevicePathFromHandle (Device), + (EFI_DEVICE_PATH_PROTOCOL *)&FileNode + ); + + Size = StrSize (FileName); + FileDevicePath = AllocatePool (Size + SIZE_OF_FILEPATH_DEVICE_PATH + END_DEVICE_PATH_LENGTH); + if (FileDevicePath != NULL) { + FilePath = (FILEPATH_DEVICE_PATH *)FileDevicePath; + FilePath->Header.Type = MEDIA_DEVICE_PATH; + FilePath->Header.SubType = MEDIA_FILEPATH_DP; + CopyMem (&FilePath->PathName, FileName, Size); + SetDevicePathNodeLength (&FilePath->Header, Size + SIZE_OF_FILEPATH_DEVICE_PATH); + SetDevicePathEndNode (NextDevicePathNode (&FilePath->Header)); + + DevicePath = AppendDevicePath (DevicePath, FileDevicePath); + FreePool (FileDevicePath); + } + + return DevicePath; +} + +/** + Install LoadFile Protocol for Application FFS. + + @param Handle FV Handle. + +**/ +VOID +EFIAPI +InstallFileLoadProtocol ( + EFI_HANDLE Handle + ) +{ + EFI_STATUS Status; + LOAD_FILE_ON_FV2_PRIVATE_DATA *Private; + EFI_FIRMWARE_VOLUME2_PROTOCOL *Fv; + EFI_FIRMWARE_VOLUME_BLOCK_PROTOCOL *Fvb; + EFI_PHYSICAL_ADDRESS Address; + EFI_FV_FILETYPE FileType; + UINTN Key; + EFI_GUID NameGuid; + EFI_FV_FILE_ATTRIBUTES Attributes; + UINTN Size; + EFI_HANDLE LoadFileHandle; + UINT32 AuthenticationStatus; + CHAR16 *UiName; + UINTN UiNameSize; + + DEBUG ((DEBUG_INFO, "LoadFileOnFv2:Find a FV!\n")); + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolume2ProtocolGuid, (VOID **)&Fv); + ASSERT_EFI_ERROR (Status); + Status = gBS->HandleProtocol (Handle, &gEfiFirmwareVolumeBlockProtocolGuid, (VOID **)&Fvb); + Fvb->GetPhysicalAddress (Fvb, &Address); + DEBUG ((DEBUG_INFO, "LoadFileOnFv2:Fvb->Address=%x \n", Address)); + + // + // Use Firmware Volume 2 Protocol to search for a FFS files of type + // EFI_FV_FILETYPE_APPLICATION and produce a LoadFile protocol for + // each one found. + // + FileType = EFI_FV_FILETYPE_APPLICATION; + Key = 0; + while (TRUE) { + Status = Fv->GetNextFile (Fv, &Key, &FileType, &NameGuid, &Attributes, &Size); + if (EFI_ERROR (Status)) { + break; + } + + UiName = NULL; + Status = Fv->ReadSection ( + Fv, + &NameGuid, + EFI_SECTION_USER_INTERFACE, + 0, + (VOID **)&UiName, + &UiNameSize, + &AuthenticationStatus + ); + if (EFI_ERROR (Status)) { + continue; + } + + if (!IsInPrivateList (&NameGuid)) { + Private = (LOAD_FILE_ON_FV2_PRIVATE_DATA *)AllocateCopyPool (sizeof (mLoadFileOnFv2PrivateDataTemplate), &mLoadFileOnFv2PrivateDataTemplate); + ASSERT (Private != NULL); + Private->Fv = Fv; + Private->DevicePath = CreateFileDevicePath (Handle, &NameGuid, UiName); + CopyGuid (&Private->NameGuid, &NameGuid); + LoadFileHandle = NULL; + DEBUG ((DEBUG_INFO, "Find a APPLICATION in this FV!\n")); + Status = gBS->InstallMultipleProtocolInterfaces ( + &LoadFileHandle, + &gEfiDevicePathProtocolGuid, + Private->DevicePath, + &gEfiLoadFileProtocolGuid, + &Private->LoadFile, + NULL + ); + if (!EFI_ERROR (Status)) { + InsertTailList (&mPrivateDataList, &Private->Link); + } else { + DEBUG ((DEBUG_ERROR, "Application with the same name %s has been installed.!\n", UiName)); + FreePool (Private->DevicePath); + FreePool (Private); + } + } + } +} + +/** + This notification function is invoked when an instance of the + LzmaCustomDecompressGuid is produced. It installs another instance of the + EFI_FIRMWARE_VOLUME_PROTOCOL on the handle of the FFS. This notification function + also handles the situation when LZMA decoder driver loaded later than FirmwareVolume driver. + + @param Event The event that occurred + @param Context Context of event. Not used in this nofication function. + +**/ +VOID +EFIAPI +FvNotificationEvent ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + EFI_STATUS Status; + UINTN BufferSize; + EFI_HANDLE *Handle; + UINTN Index; + EFI_HANDLE *CurHandle; + + Handle = NULL; + Index = 0; + BufferSize = sizeof (EFI_HANDLE); + Handle = AllocateZeroPool (BufferSize); + if (Handle == NULL) { + return; + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &BufferSize, + Handle + ); + if (EFI_BUFFER_TOO_SMALL == Status) { + FreePool (Handle); + Handle = AllocateZeroPool (BufferSize); + if (Handle == NULL) { + return; + } + + Status = gBS->LocateHandle ( + ByProtocol, + &gEfiFirmwareVolume2ProtocolGuid, + NULL, + &BufferSize, + Handle + ); + if (EFI_ERROR (Status)) { + return; + } + } else if (EFI_ERROR (Status)) { + return; + } + + CurHandle = Handle; + for (Index = 0; Index < BufferSize/sizeof (EFI_HANDLE); Index++) { + CurHandle = Handle + Index; + // + // Install LoadFile Protocol + // + InstallFileLoadProtocol (*CurHandle); + } + + if (Handle != NULL) { + FreePool (Handle); + } +} + +/** + Entry point function initializes global variables and installs notifications. + + @param[in] ImageHandle The firmware allocated handle for the EFI image. + @param[in] SystemTable A pointer to the EFI System Table. + + @retval EFI_SUCCESS The entry point is executed successfully. + @retval other Some error occurs when executing this entry point. +**/ +EFI_STATUS +EFIAPI +LoadFileOnFv2Intialize ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + InitializeListHead (&mPrivateDataList); + + EfiCreateProtocolNotifyEvent ( + &gEfiFirmwareVolume2ProtocolGuid, + TPL_CALLBACK, + FvNotificationEvent, + NULL, + &mFvRegistration + ); + + EfiCreateProtocolNotifyEvent ( + &gLzmaCustomDecompressGuid, + TPL_CALLBACK, + FvNotificationEvent, + NULL, + &mFvRegistration + ); + + return EFI_SUCCESS; +} |
