summaryrefslogtreecommitdiff
path: root/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c')
-rw-r--r--MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c852
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;
+}