Laszlo,
OVMF uses old style of FV device path node: MemoryMapped(...).
If you check Nt32Pkg/Nt32Pkg.fdf, there is FvNameGuid field under[FV] section.
-----
[FV.FvRecovery]
......
FvNameGuid         = 6D99E806-3D38-42c2-A095-5F4300BFD7DC
----

If you add FvNameGuid field under [FV] section for OVMF, the firmware will
produce Fv(...) device path node for FV.
Which is also the recommended way to identify a FV because it won't cause
the FV boot option file path changing across boot.

You patch looks good but it assumes a FV boot option should always starts
with MemoryMapped(...) node, which is not always TRUE.

I recommend you change FDF to add FvNameGuid field to [FV] section
and then just use the following algorithm to remove stale options:

For each option:
  Node = option.FilePath
   Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid,
                    &Node, &FvHandle);
  If (EFI_ERROR (Status)) {
    // Current one is not a FV boot option
    Continue;
  }
  //... Use Fv->ReadFile as what you did in below patch to check.
  
With the above code, you don't need to check whether the first node is
a MemoryMapped(...) node and second node is a FvFile(...) node.


Thanks/Ray

> -----Original Message-----
> From: Laszlo Ersek [mailto:ler...@redhat.com]
> Sent: Tuesday, July 12, 2016 3:51 AM
> To: edk2-devel-01 <edk2-de...@ml01.01.org>
> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>; Gary Lin <g...@suse.com>;
> Justen, Jordan L <jordan.l.jus...@intel.com>; Ni, Ruiyu <ruiyu...@intel.com>
> Subject: [PATCH] OvmfPkg/PlatformBootManagerLib: remove stale FvFile
> boot options
> 
> Changing the base address or the size of DXEFV, changing PcdShellFile, or
> omitting the UEFI Shell from the OVMF binary, all lead to "EFI Internal Shell"
> boot options that are technically different from each other and do 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.
> 
> This functionality is not added to QemuBootOrderLib, because it is
> independent from QEMU and fw_cfg.
> 
> Cc: Ard Biesheuvel <ard.biesheu...@linaro.org>
> Cc: Gary Lin <g...@suse.com>
> Cc: Jordan Justen <jordan.l.jus...@intel.com>
> Cc: Ruiyu Ni <ruiyu...@intel.com>
> Contributed-under: TianoCore Contribution Agreement 1.0
> Signed-off-by: Laszlo Ersek <ler...@redhat.com>
> ---
> 
> Notes:
>     Once this patch converges, I'll port it to ArmVirtPkg.
> 
>  OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf |
> 1 +
>  OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c              | 115
> ++++++++++++++++++++
>  2 files changed, 116 insertions(+)
> 
> diff --git
> a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> index ffa1288e4d1a..f3303b9f2cf3 100644
> ---
> a/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> +++
> b/OvmfPkg/Library/PlatformBootManagerLib/PlatformBootManagerLib.inf
> @@ -72,6 +72,7 @@ [Protocols]
>    gEfiS3SaveStateProtocolGuid                   # PROTOCOL
> SOMETIMES_CONSUMED
>    gEfiDxeSmmReadyToLockProtocolGuid             # PROTOCOL
> SOMETIMES_PRODUCED
>    gEfiLoadedImageProtocolGuid                   # PROTOCOL
> SOMETIMES_PRODUCED
> +  gEfiFirmwareVolume2ProtocolGuid               # PROTOCOL
> SOMETIMES_CONSUMED
> 
>  [Guids]
>    gEfiXenInfoGuid
> diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> index 912c5ed1ece4..727c8b4792c0 100644
> --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c
> @@ -15,6 +15,7 @@
>  #include "BdsPlatform.h"
>  #include <Guid/XenInfo.h>
>  #include <Guid/RootBridgesConnectedEventGroup.h>
> +#include <Protocol/FirmwareVolume2.h>
> 
> 
>  //
> @@ -149,6 +150,119 @@ PlatformRegisterFvBootOption (
>    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);  }
> 
> +/**
> +  Remove all MemoryMapped(...)/FvFile(...) boot options whose device
> +paths do
> +  not resolve exactly to an FvFile in the system.
> +
> +  This prevents the proliferation of UEFI Shell boot options if DXEFV's
> +base
> +  address or size changes, or a different FILE_GUID binary is used as Shell.
> +  EfiBootManagerFindLoadOption() used in PlatformRegisterFvBootOption()
> +only
> +  avoids exact duplicates.
> +**/
> +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;
> +
> +    Node1 = BootOptions[Index].FilePath;
> +    if (DevicePathType (Node1) != HARDWARE_DEVICE_PATH ||
> +        DevicePathSubType (Node1) != HW_MEMMAP_DP) {
> +      continue;
> +    }
> +
> +    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); }
> +
>  VOID
>  PlatformRegisterOptionsAndKeys (
>    VOID
> @@ -1343,6 +1457,7 @@ Routine Description:
>      PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE
>      );
> 
> +  RemoveStaleFvFileOptions ();
>    SetBootOrderFromQemu ();
>  }
> 
> --
> 1.8.3.1

_______________________________________________
edk2-devel mailing list
edk2-devel@lists.01.org
https://lists.01.org/mailman/listinfo/edk2-devel

Reply via email to