From af1a266670d040d2f4083ff309d732d648afba2a Mon Sep 17 00:00:00 2001
From: Angelos Mouzakitis <a.mouzakitis@virtualopensystems.com>
Date: Tue, 10 Oct 2023 14:33:42 +0000
Subject: Add submodule dependency files

Change-Id: Iaf8d18082d3991dec7c0ebbea540f092188eb4ec
---
 .../Universal/LoadFileOnFv2/LoadFileOnFv2.c        | 421 +++++++++++++++++++++
 1 file changed, 421 insertions(+)
 create mode 100644 roms/edk2/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c

(limited to 'roms/edk2/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c')

diff --git a/roms/edk2/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c b/roms/edk2/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
new file mode 100644
index 000000000..58e658ee0
--- /dev/null
+++ b/roms/edk2/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
@@ -0,0 +1,421 @@
+/** @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;
+}
+
-- 
cgit