X-Git-Url: https://git.proxmox.com/?a=blobdiff_plain;f=ArmVirtPkg%2FLibrary%2FPlatformBootManagerLib%2FPlatformBm.c;h=56f4c921b51396961bde0e0b2afc33e448f92e86;hb=e048823f57f66b5be38d46b0095af2fc905c4033;hp=d4bfcd0c071572b0d20d2bcac688183dc1758140;hpb=afa456de2538c82d227e50445fb1d4f2841e46c4;p=mirror_edk2.git diff --git a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c index d4bfcd0c07..56f4c921b5 100644 --- a/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c +++ b/ArmVirtPkg/Library/PlatformBootManagerLib/PlatformBm.c @@ -16,11 +16,13 @@ **/ #include +#include #include #include #include #include #include +#include #include #include #include @@ -386,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"" : DevicePathString, + Status + )); + if (DevicePathString != NULL) { + FreePool (DevicePathString); + } + ); + } + + EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount); +} + + STATIC VOID PlatformRegisterOptionsAndKeys ( @@ -423,12 +555,6 @@ PlatformRegisterOptionsAndKeys ( NULL, (UINT16) BootOption.OptionNumber, 0, &Esc, NULL ); ASSERT (Status == EFI_SUCCESS || Status == EFI_ALREADY_STARTED); - // - // Register UEFI Shell - // - PlatformRegisterFvBootOption ( - PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE - ); } @@ -452,6 +578,8 @@ PlatformBootManagerBeforeConsole ( VOID ) { + RETURN_STATUS PcdStatus; + // // Signal EndOfDxe PI Event // @@ -503,7 +631,9 @@ PlatformBootManagerBeforeConsole ( // // Set the front page timeout from the QEMU configuration. // - PcdSet16 (PcdPlatformBootTimeOut, GetFrontPageTimeoutFromQemu ()); + PcdStatus = PcdSet16S (PcdPlatformBootTimeOut, + GetFrontPageTimeoutFromQemu ()); + ASSERT_RETURN_ERROR (PcdStatus); // // Register platform-specific boot options and keyboard shortcuts. @@ -531,7 +661,7 @@ PlatformBootManagerAfterConsole ( // // Show the splash screen. // - EnableQuietBoot (PcdGetPtr (PcdLogoFile)); + BootLogoEnableLogo (); // // Connect the rest of the devices. @@ -551,7 +681,16 @@ PlatformBootManagerAfterConsole ( // the QEMU configuration. // EfiBootManagerRefreshAllBootOption (); - SetBootOrderFromQemu (NULL); + + // + // Register UEFI Shell + // + PlatformRegisterFvBootOption ( + PcdGetPtr (PcdShellFile), L"EFI Internal Shell", LOAD_OPTION_ACTIVE + ); + + RemoveStaleFvFileOptions (); + SetBootOrderFromQemu (); } /** @@ -566,4 +705,21 @@ PlatformBootManagerWaitCallback ( UINT16 TimeoutRemain ) { + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION Black; + EFI_GRAPHICS_OUTPUT_BLT_PIXEL_UNION White; + UINT16 Timeout; + + Timeout = PcdGet16 (PcdPlatformBootTimeOut); + + Black.Raw = 0x00000000; + White.Raw = 0x00FFFFFF; + + BootLogoUpdateProgress ( + White.Pixel, + Black.Pixel, + L"Start boot option", + White.Pixel, + (Timeout - TimeoutRemain) * 100 / Timeout, + 0 + ); }