summaryrefslogtreecommitdiffstats
path: root/MdeModulePkg/Universal/LoadFileOnFv2
diff options
context:
space:
mode:
Diffstat (limited to 'MdeModulePkg/Universal/LoadFileOnFv2')
-rw-r--r--MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c421
-rw-r--r--MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf68
-rw-r--r--MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.uni24
-rw-r--r--MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2Extra.uni18
4 files changed, 531 insertions, 0 deletions
diff --git a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
new file mode 100644
index 0000000000..6ef9facc93
--- /dev/null
+++ b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.c
@@ -0,0 +1,421 @@
+/** @file
+ Produce Load File Protocol for UEFI Applications in Firmware Volumes
+
+ Copyright (c) 2011 - 2013, Intel Corporation
+ All rights reserved. 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
+ http://opensource.org/licenses/bsd-license.php
+
+ THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+
+**/
+
+#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)
+
+EFI_EVENT 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 EFI_GUID File GUID.
+
+ @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 occured
+ @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);
+ Status = gBS->LocateHandle (
+ ByProtocol,
+ &gEfiFirmwareVolume2ProtocolGuid,
+ NULL,
+ &BufferSize,
+ Handle
+ );
+ if (EFI_BUFFER_TOO_SMALL == Status) {
+ FreePool (Handle);
+ Handle = AllocateZeroPool (BufferSize);
+ 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;
+}
+
diff --git a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
new file mode 100644
index 0000000000..a4ded94e7f
--- /dev/null
+++ b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.inf
@@ -0,0 +1,68 @@
+## @file
+# Load File Module
+#
+# Allows the system to load a file from a FV2 based firmware volume. This
+# version of the module only supports loading of files for the purpose of
+# booting from the file.
+#
+# Copyright (c) 2016, Intel Corporation. All rights reserved.<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
+# http://opensource.org/licenses/bsd-license.php
+#
+# THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+# WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+#
+##
+
+[Defines]
+ INF_VERSION = 0x00010018
+ BASE_NAME = LoadFileOnFv2
+ FILE_GUID = BD712601-082F-4c59-8677-2C8A3C297948
+ MODULE_TYPE = DXE_DRIVER
+ VERSION_STRING = 1.0
+ ENTRY_POINT = LoadFileOnFv2Intialize
+ MODULE_UNI_FILE = LoadFileOnFv2.uni
+
+#
+# The following information is for reference only and not required by the build tools.
+#
+# VALID_ARCHITECTURES = IA32 X64 IPF EBC
+#
+
+[Sources]
+ LoadFileOnFv2.c
+
+[Packages]
+ MdePkg/MdePkg.dec
+ MdeModulePkg/MdeModulePkg.dec
+
+[LibraryClasses]
+ DebugLib
+ UefiLib
+ BaseMemoryLib
+ UefiDriverEntryPoint
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ DevicePathLib
+
+[Guids]
+ ## SOMETIMES_CONSUMES ## UNDEFINED # Notify gLzmaCustomDecompressGuid SectionExtraction.
+ gLzmaCustomDecompressGuid
+
+[Protocols]
+ ## NOTIFY
+ ## CONSUMES
+ gEfiFirmwareVolume2ProtocolGuid
+ gEfiFirmwareVolumeBlockProtocolGuid ## SOMETIMES_CONSUMES
+ gEfiLoadFileProtocolGuid ## PRODUCES
+ gEfiDevicePathProtocolGuid ## SOMETIMES_PRODUCES
+
+[Depex]
+ TRUE
+
+[UserExtensions.TianoCore."ExtraFiles"]
+ LoadFileOnFv2Extra.uni
+
diff --git a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.uni b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.uni
new file mode 100644
index 0000000000..19e42a2830
--- /dev/null
+++ b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2.uni
@@ -0,0 +1,24 @@
+// /** @file
+// LoadFileOnFv2 Localized Abstract and Description Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<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
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_MODULE_ABSTRACT
+#language en-US
+"Allows system to load files from an FV2-based firmware volume"
+
+#string STR_MODULE_DESCRIPTION
+#language en-US
+"This module allows the system to load a file from an FV2-based firmware "
+"volume. This version of the module only supports loading of files for the "
+"purpose of booting from a file."
diff --git a/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2Extra.uni b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2Extra.uni
new file mode 100644
index 0000000000..aa5eb98400
--- /dev/null
+++ b/MdeModulePkg/Universal/LoadFileOnFv2/LoadFileOnFv2Extra.uni
@@ -0,0 +1,18 @@
+// /** @file
+// LoadFileOnFv2 Localized Strings and Content
+//
+// Copyright (c) 2016, Intel Corporation. All rights reserved.<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
+// http://opensource.org/licenses/bsd-license.php
+//
+// THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
+// WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
+//
+// **/
+
+#string STR_PROPERTIES_MODULE_NAME
+#language en-US
+"Firmware Volume Load File Module"