summaryrefslogtreecommitdiff
path: root/ArmVirtPkg/Library
diff options
context:
space:
mode:
authorLaszlo Ersek <lersek@redhat.com>2016-07-13 17:40:15 +0200
committerLaszlo Ersek <lersek@redhat.com>2016-07-13 22:44:34 +0200
commit0e2c6c552990edcd6352c2395860cb0df62b158d (patch)
treee7b108983b242e4c548288f83db8ee6ce70a1ed6 /ArmVirtPkg/Library
parent7ffced92a7b6e5a0eb4433123b3973c635da7355 (diff)
downloadedk2-platforms-0e2c6c552990edcd6352c2395860cb0df62b158d.tar.xz
ArmVirtPkg/PlatformBootManagerLib: remove stale FvFile boot options
(This patch ports OvmfPkg commit 2eb358986052 to ArmVirtPkg. That functionality was not added to QemuBootOrderLib, because it was (and is) independent from QEMU and fw_cfg.) Remove any boot options that point to binaries built into the firmware and have become stale due to any of the following: - FvMain's base address or size changed (historical -- see commit e191a3114f4c), - FvMain's FvNameGuid changed, - the FILE_GUID of the pointed-to binary changed, - the referenced binary is no longer built into the firmware. For example, multiple such "EFI Internal Shell" boot options can coexist. They technically differ from each other, but may not describe any built-in shell binary exactly. Such options can accumulate in a varstore over time, and while they remain generally bootable (thanks to the efforts of BmGetFileBufferByFvFilePath()), they look bad. Filter out any stale options. Cc: Ard Biesheuvel <ard.biesheuvel@linaro.org> Fixes: https://github.com/tianocore/edk2/issues/107 Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Laszlo Ersek <lersek@redhat.com> Reviewed-by: Ard Biesheuvel <ard.biesheuvel@linaro.org>
Diffstat (limited to 'ArmVirtPkg/Library')
-rw-r--r--ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c132
-rw-r--r--ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf1
2 files changed, 133 insertions, 0 deletions
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
index eaafe7ff57..c11196a8a5 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
+++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c
@@ -22,6 +22,7 @@
#include <Library/QemuBootOrderLib.h>
#include <Library/UefiBootManagerLib.h>
#include <Protocol/DevicePath.h>
+#include <Protocol/FirmwareVolume2.h>
#include <Protocol/GraphicsOutput.h>
#include <Protocol/LoadedImage.h>
#include <Protocol/PciIo.h>
@@ -387,6 +388,136 @@ PlatformRegisterFvBootOption (
}
+/**
+ Remove all MemoryMapped(...)/FvFile(...) and Fv(...)/FvFile(...) boot options
+ whose device paths do not resolve exactly to an FvFile in the system.
+
+ This removes any boot options that point to binaries built into the firmware
+ and have become stale due to any of the following:
+ - FvMain's base address or size changed (historical),
+ - FvMain's FvNameGuid changed,
+ - the FILE_GUID of the pointed-to binary changed,
+ - the referenced binary is no longer built into the firmware.
+
+ EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption() only
+ avoids exact duplicates.
+**/
+STATIC
+VOID
+RemoveStaleFvFileOptions (
+ VOID
+ )
+{
+ EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;
+ UINTN BootOptionCount;
+ UINTN Index;
+
+ BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount,
+ LoadOptionTypeBoot);
+
+ for (Index = 0; Index < BootOptionCount; ++Index) {
+ EFI_DEVICE_PATH_PROTOCOL *Node1, *Node2, *SearchNode;
+ EFI_STATUS Status;
+ EFI_HANDLE FvHandle;
+
+ //
+ // If the device path starts with neither MemoryMapped(...) nor Fv(...),
+ // then keep the boot option.
+ //
+ Node1 = BootOptions[Index].FilePath;
+ if (!(DevicePathType (Node1) == HARDWARE_DEVICE_PATH &&
+ DevicePathSubType (Node1) == HW_MEMMAP_DP) &&
+ !(DevicePathType (Node1) == MEDIA_DEVICE_PATH &&
+ DevicePathSubType (Node1) == MEDIA_PIWG_FW_VOL_DP)) {
+ continue;
+ }
+
+ //
+ // If the second device path node is not FvFile(...), then keep the boot
+ // option.
+ //
+ Node2 = NextDevicePathNode (Node1);
+ if (DevicePathType (Node2) != MEDIA_DEVICE_PATH ||
+ DevicePathSubType (Node2) != MEDIA_PIWG_FW_FILE_DP) {
+ continue;
+ }
+
+ //
+ // Locate the Firmware Volume2 protocol instance that is denoted by the
+ // boot option. If this lookup fails (i.e., the boot option references a
+ // firmware volume that doesn't exist), then we'll proceed to delete the
+ // boot option.
+ //
+ SearchNode = Node1;
+ Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
+ &SearchNode, &FvHandle);
+
+ if (!EFI_ERROR (Status)) {
+ //
+ // The firmware volume was found; now let's see if it contains the FvFile
+ // identified by GUID.
+ //
+ EFI_FIRMWARE_VOLUME2_PROTOCOL *FvProtocol;
+ MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *FvFileNode;
+ UINTN BufferSize;
+ EFI_FV_FILETYPE FoundType;
+ EFI_FV_FILE_ATTRIBUTES FileAttributes;
+ UINT32 AuthenticationStatus;
+
+ Status = gBS->HandleProtocol (FvHandle, &gEfiFirmwareVolume2ProtocolGuid,
+ (VOID **)&FvProtocol);
+ ASSERT_EFI_ERROR (Status);
+
+ FvFileNode = (MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *)Node2;
+ //
+ // Buffer==NULL means we request metadata only: BufferSize, FoundType,
+ // FileAttributes.
+ //
+ Status = FvProtocol->ReadFile (
+ FvProtocol,
+ &FvFileNode->FvFileName, // NameGuid
+ NULL, // Buffer
+ &BufferSize,
+ &FoundType,
+ &FileAttributes,
+ &AuthenticationStatus
+ );
+ if (!EFI_ERROR (Status)) {
+ //
+ // The FvFile was found. Keep the boot option.
+ //
+ continue;
+ }
+ }
+
+ //
+ // Delete the boot option.
+ //
+ Status = EfiBootManagerDeleteLoadOptionVariable (
+ BootOptions[Index].OptionNumber, LoadOptionTypeBoot);
+ DEBUG_CODE (
+ CHAR16 *DevicePathString;
+
+ DevicePathString = ConvertDevicePathToText(BootOptions[Index].FilePath,
+ FALSE, FALSE);
+ DEBUG ((
+ EFI_ERROR (Status) ? EFI_D_WARN : EFI_D_VERBOSE,
+ "%a: removing stale Boot#%04x %s: %r\n",
+ __FUNCTION__,
+ (UINT32)BootOptions[Index].OptionNumber,
+ DevicePathString == NULL ? L"<unavailable>" : DevicePathString,
+ Status
+ ));
+ if (DevicePathString != NULL) {
+ FreePool (DevicePathString);
+ }
+ );
+ }
+
+ EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);
+}
+
+
STATIC
VOID
PlatformRegisterOptionsAndKeys (
@@ -560,6 +691,7 @@ PlatformBootManagerAfterConsole (
PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
);
+ RemoveStaleFvFileOptions ();
SetBootOrderFromQemu ();
}
diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
index 9c95b69cc9..bec7fabb47 100644
--- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
+++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
@@ -78,6 +78,7 @@
[Protocols]
gEfiDevicePathProtocolGuid
+ gEfiFirmwareVolume2ProtocolGuid
gEfiGraphicsOutputProtocolGuid
gEfiLoadedImageProtocolGuid
gEfiPciRootBridgeIoProtocolGuid