]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg/DxeCapsuleLibFmp: Use new Variable Lock interface
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmBoot.c
index 0535cd7335b43162a798069dd77a35fbca5500fb..95d185b639d54a6b84d393ffd5f5d513a1e0142b 100644 (file)
@@ -1,15 +1,10 @@
 /** @file\r
   Library functions which relates with booting.\r
 \r
-Copyright (c) 2011 - 2019, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2015-2016 Hewlett Packard Enterprise Development LP<BR>\r
-This program and the accompanying materials\r
-are licensed and made available under the terms and conditions of the BSD License\r
-which accompanies this distribution.  The full text of the license may be found at\r
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2019, NVIDIA CORPORATION. All rights reserved.\r
+Copyright (c) 2011 - 2021, Intel Corporation. All rights reserved.<BR>\r
+(C) Copyright 2015-2021 Hewlett Packard Enterprise Development LP<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
@@ -1392,6 +1387,37 @@ BmExpandLoadFile (
   //\r
   FileBuffer = AllocateReservedPages (EFI_SIZE_TO_PAGES (BufferSize));\r
   if (FileBuffer == NULL) {\r
+    DEBUG_CODE (\r
+      EFI_DEVICE_PATH *LoadFilePath;\r
+      CHAR16          *LoadFileText;\r
+      CHAR16          *FileText;\r
+\r
+      LoadFilePath = DevicePathFromHandle (LoadFileHandle);\r
+      if (LoadFilePath == NULL) {\r
+        LoadFileText = NULL;\r
+      } else {\r
+        LoadFileText = ConvertDevicePathToText (LoadFilePath, FALSE, FALSE);\r
+      }\r
+      FileText = ConvertDevicePathToText (FilePath, FALSE, FALSE);\r
+\r
+      DEBUG ((\r
+        DEBUG_ERROR,\r
+        "%a:%a: failed to allocate reserved pages: "\r
+        "BufferSize=%Lu LoadFile=\"%s\" FilePath=\"%s\"\n",\r
+        gEfiCallerBaseName,\r
+        __FUNCTION__,\r
+        (UINT64)BufferSize,\r
+        LoadFileText,\r
+        FileText\r
+        ));\r
+\r
+      if (FileText != NULL) {\r
+        FreePool (FileText);\r
+      }\r
+      if (LoadFileText != NULL) {\r
+        FreePool (LoadFileText);\r
+      }\r
+      );\r
     return NULL;\r
   }\r
 \r
@@ -1868,10 +1894,14 @@ EfiBootManagerBoot (
 \r
     if (EFI_ERROR (Status)) {\r
       //\r
-      // Report Status Code with the failure status to indicate that the failure to load boot option\r
+      // With EFI_SECURITY_VIOLATION retval, the Image was loaded and an ImageHandle was created\r
+      // with a valid EFI_LOADED_IMAGE_PROTOCOL, but the image can not be started right now.\r
+      // If the caller doesn't have the option to defer the execution of an image, we should\r
+      // unload image for the EFI_SECURITY_VIOLATION to avoid resource leak.\r
       //\r
-      BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status);\r
-      BootOption->Status = Status;\r
+      if (Status == EFI_SECURITY_VIOLATION) {\r
+        gBS->UnloadImage (ImageHandle);\r
+      }\r
       //\r
       // Destroy the RAM disk\r
       //\r
@@ -1879,6 +1909,11 @@ EfiBootManagerBoot (
         BmDestroyRamDisk (RamDiskDevicePath);\r
         FreePool (RamDiskDevicePath);\r
       }\r
+      //\r
+      // Report Status Code with the failure status to indicate that the failure to load boot option\r
+      //\r
+      BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_LOAD_ERROR, Status);\r
+      BootOption->Status = Status;\r
       return;\r
     }\r
   }\r
@@ -1947,13 +1982,6 @@ EfiBootManagerBoot (
   Status = gBS->StartImage (ImageHandle, &BootOption->ExitDataSize, &BootOption->ExitData);\r
   DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Image Return Status = %r\n", Status));\r
   BootOption->Status = Status;\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // Report Status Code with the failure status to indicate that boot failure\r
-    //\r
-    BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED, Status);\r
-  }\r
-  PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
 \r
   //\r
   // Destroy the RAM disk\r
@@ -1963,6 +1991,15 @@ EfiBootManagerBoot (
     FreePool (RamDiskDevicePath);\r
   }\r
 \r
+  if (EFI_ERROR (Status)) {\r
+    //\r
+    // Report Status Code with the failure status to indicate that boot failure\r
+    //\r
+    BmReportLoadFailure (EFI_SW_DXE_BS_EC_BOOT_OPTION_FAILED, Status);\r
+  }\r
+  PERF_END_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
+\r
+\r
   //\r
   // Clear the Watchdog Timer after the image returns\r
   //\r
@@ -2255,12 +2292,15 @@ EfiBootManagerRefreshAllBootOption (
   VOID\r
   )\r
 {\r
-  EFI_STATUS                    Status;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION  *NvBootOptions;\r
-  UINTN                         NvBootOptionCount;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION  *BootOptions;\r
-  UINTN                         BootOptionCount;\r
-  UINTN                         Index;\r
+  EFI_STATUS                           Status;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION         *NvBootOptions;\r
+  UINTN                                NvBootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION         *BootOptions;\r
+  UINTN                                BootOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION         *UpdatedBootOptions;\r
+  UINTN                                UpdatedBootOptionCount;\r
+  UINTN                                Index;\r
+  EDKII_PLATFORM_BOOT_MANAGER_PROTOCOL *PlatformBootManager;\r
 \r
   //\r
   // Optionally refresh the legacy boot option\r
@@ -2270,7 +2310,6 @@ EfiBootManagerRefreshAllBootOption (
   }\r
 \r
   BootOptions   = BmEnumerateBootOptions (&BootOptionCount);\r
-  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);\r
 \r
   //\r
   // Mark the boot option as added by BDS by setting OptionalData to a special GUID\r
@@ -2280,6 +2319,30 @@ EfiBootManagerRefreshAllBootOption (
     BootOptions[Index].OptionalDataSize = sizeof (EFI_GUID);\r
   }\r
 \r
+  //\r
+  // Locate Platform Boot Options Protocol\r
+  //\r
+  Status = gBS->LocateProtocol (&gEdkiiPlatformBootManagerProtocolGuid,\r
+                                NULL,\r
+                                (VOID **)&PlatformBootManager);\r
+  if (!EFI_ERROR (Status)) {\r
+    //\r
+    // If found, call platform specific refresh to all auto enumerated and NV\r
+    // boot options.\r
+    //\r
+    Status = PlatformBootManager->RefreshAllBootOptions ((CONST EFI_BOOT_MANAGER_LOAD_OPTION *)BootOptions,\r
+                                                         (CONST UINTN)BootOptionCount,\r
+                                                         &UpdatedBootOptions,\r
+                                                         &UpdatedBootOptionCount);\r
+    if (!EFI_ERROR (Status)) {\r
+      EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
+      BootOptions = UpdatedBootOptions;\r
+      BootOptionCount = UpdatedBootOptionCount;\r
+    }\r
+  }\r
+\r
+  NvBootOptions = EfiBootManagerGetLoadOptions (&NvBootOptionCount, LoadOptionTypeBoot);\r
+\r
   //\r
   // Remove invalid EFI boot options from NV\r
   //\r
@@ -2322,7 +2385,8 @@ EfiBootManagerRefreshAllBootOption (
   This function is called to get or create the boot option for the Boot Manager Menu.\r
 \r
   The Boot Manager Menu is shown after successfully booting a boot option.\r
-  Assume the BootManagerMenuFile is in the same FV as the module links to this library.\r
+  This function will first try to search the BootManagerMenuFile is in the same FV as\r
+  the module links to this library. If fails, it will search in all FVs.\r
 \r
   @param  BootOption    Return the boot option of the Boot Manager Menu\r
 \r
@@ -2341,13 +2405,9 @@ BmRegisterBootManagerMenu (
   CHAR16                             *Description;\r
   UINTN                              DescriptionLength;\r
   EFI_DEVICE_PATH_PROTOCOL           *DevicePath;\r
-  EFI_LOADED_IMAGE_PROTOCOL          *LoadedImage;\r
-  MEDIA_FW_VOL_FILEPATH_DEVICE_PATH  FileNode;\r
   UINTN                              HandleCount;\r
   EFI_HANDLE                         *Handles;\r
   UINTN                              Index;\r
-  VOID                               *Data;\r
-  UINTN                              DataSize;\r
 \r
   DevicePath = NULL;\r
   Description = NULL;\r
@@ -2373,26 +2433,21 @@ BmRegisterBootManagerMenu (
   }\r
 \r
   if (DevicePath == NULL) {\r
-    Data = NULL;\r
-    Status = GetSectionFromFv (\r
+    Status = GetFileDevicePathFromAnyFv (\r
                PcdGetPtr (PcdBootManagerMenuFile),\r
                EFI_SECTION_PE32,\r
                0,\r
-               (VOID **) &Data,\r
-               &DataSize\r
+               &DevicePath\r
                );\r
-    if (Data != NULL) {\r
-      FreePool (Data);\r
-    }\r
     if (EFI_ERROR (Status)) {\r
       DEBUG ((EFI_D_WARN, "[Bds]BootManagerMenu FFS section can not be found, skip its boot option registration\n"));\r
       return EFI_NOT_FOUND;\r
     }\r
-\r
+    ASSERT (DevicePath != NULL);\r
     //\r
     // Get BootManagerMenu application's description from EFI User Interface Section.\r
     //\r
-    Status = GetSectionFromFv (\r
+    Status = GetSectionFromAnyFv (\r
                PcdGetPtr (PcdBootManagerMenuFile),\r
                EFI_SECTION_USER_INTERFACE,\r
                0,\r
@@ -2402,19 +2457,6 @@ BmRegisterBootManagerMenu (
     if (EFI_ERROR (Status)) {\r
       Description = NULL;\r
     }\r
-\r
-    EfiInitializeFwVolDevicepathNode (&FileNode, PcdGetPtr (PcdBootManagerMenuFile));\r
-    Status = gBS->HandleProtocol (\r
-                    gImageHandle,\r
-                    &gEfiLoadedImageProtocolGuid,\r
-                    (VOID **) &LoadedImage\r
-                    );\r
-    ASSERT_EFI_ERROR (Status);\r
-    DevicePath = AppendDevicePathNode (\r
-                   DevicePathFromHandle (LoadedImage->DeviceHandle),\r
-                   (EFI_DEVICE_PATH_PROTOCOL *) &FileNode\r
-                   );\r
-    ASSERT (DevicePath != NULL);\r
   }\r
 \r
   Status = EfiBootManagerInitializeLoadOption (\r
@@ -2442,7 +2484,7 @@ BmRegisterBootManagerMenu (
     EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
     );\r
 \r
-  return EfiBootManagerAddLoadOptionVariable (BootOption, 0);\r
+  return EfiBootManagerAddLoadOptionVariable (BootOption, (UINTN) -1);\r
 }\r
 \r
 /**\r