]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg UefiBootManagerLib: Update LoadFile boot description
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmBoot.c
index beb2eafe2943af2c8a0f32169d4ab61647b394d7..d5818ca0698520ee93e47b3949285fc7bafaf7a4 100644 (file)
@@ -2,7 +2,7 @@
   Library functions which relates with booting.\r
 \r
 Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
-(C) Copyright 2015 Hewlett Packard Enterprise Development LP<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
@@ -586,7 +586,7 @@ BmExpandUsbDevicePath (
 \r
   for (Index = 0; (Index < HandleCount) && (FileBuffer == NULL); Index++) {\r
     FullDevicePath = AppendDevicePath (DevicePathFromHandle (Handles[Index]), RemainingDevicePath);\r
-    FileBuffer = BmGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
+    FileBuffer = EfiBootManagerGetLoadOptionBuffer (FullDevicePath, FullPath, FileSize);\r
     FreePool (FullDevicePath);\r
   }\r
 \r
@@ -851,7 +851,7 @@ BmExpandPartitionDevicePath (
         Status = EfiBootManagerConnectDevicePath (Instance, NULL);\r
         if (!EFI_ERROR (Status)) {\r
           TempDevicePath = AppendDevicePath (Instance, NextDevicePathNode (FilePath));\r
-          FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+          FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
           FreePool (TempDevicePath);\r
 \r
           if (FileBuffer != NULL) {\r
@@ -911,7 +911,7 @@ BmExpandPartitionDevicePath (
       // Find the matched partition device path\r
       //\r
       TempDevicePath = AppendDevicePath (BlockIoDevicePath, NextDevicePathNode (FilePath));\r
-      FileBuffer = BmGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
+      FileBuffer = EfiBootManagerGetLoadOptionBuffer (TempDevicePath, FullPath, FileSize);\r
       FreePool (TempDevicePath);\r
 \r
       if (FileBuffer != NULL) {\r
@@ -1425,7 +1425,8 @@ BmGetFileBufferFromLoadFiles (
   @return The load option buffer. Caller is responsible to free the memory.\r
 **/\r
 VOID *\r
-BmGetLoadOptionBuffer (\r
+EFIAPI\r
+EfiBootManagerGetLoadOptionBuffer (\r
   IN  EFI_DEVICE_PATH_PROTOCOL          *FilePath,\r
   OUT EFI_DEVICE_PATH_PROTOCOL          **FullPath,\r
   OUT UINTN                             *FileSize\r
@@ -1528,6 +1529,34 @@ BmGetLoadOptionBuffer (
   return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);\r
 }\r
 \r
+/**\r
+  Check if it's a Device Path pointing to BootMenuApp.\r
+\r
+  @param  DevicePath     Input device path.\r
+\r
+  @retval TRUE   The device path is BootMenuApp File Device Path.\r
+  @retval FALSE  The device path is NOT BootMenuApp File Device Path.\r
+**/\r
+BOOLEAN\r
+BmIsBootMenuAppFilePath (\r
+  EFI_DEVICE_PATH_PROTOCOL     *DevicePath\r
+)\r
+{\r
+  EFI_HANDLE                      FvHandle;\r
+  VOID                            *NameGuid;\r
+  EFI_STATUS                      Status;\r
+\r
+  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &DevicePath, &FvHandle);\r
+  if (!EFI_ERROR (Status)) {\r
+    NameGuid = EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) DevicePath);\r
+    if (NameGuid != NULL) {\r
+      return CompareGuid (NameGuid, PcdGetPtr (PcdBootManagerMenuFile));\r
+    }\r
+  }\r
+\r
+  return FALSE;\r
+}\r
+\r
 /**\r
   Attempt to boot the EFI boot option. This routine sets L"BootCurent" and\r
   also signals the EFI ready to boot event. If the device path for the option\r
@@ -1561,14 +1590,11 @@ EfiBootManagerBoot (
   UINTN                     OptionNumber;\r
   UINTN                     OriginalOptionNumber;\r
   EFI_DEVICE_PATH_PROTOCOL  *FilePath;\r
-  EFI_DEVICE_PATH_PROTOCOL  *Node;\r
   EFI_DEVICE_PATH_PROTOCOL  *RamDiskDevicePath;\r
-  EFI_HANDLE                FvHandle;\r
   VOID                      *FileBuffer;\r
   UINTN                     FileSize;\r
   EFI_BOOT_LOGO_PROTOCOL    *BootLogo;\r
   EFI_EVENT                 LegacyBootEvent;\r
-  UINTN                     RamDiskSizeInPages;\r
 \r
   if (BootOption == NULL) {\r
     return;\r
@@ -1619,12 +1645,7 @@ EfiBootManagerBoot (
   // 3. Signal the EVT_SIGNAL_READY_TO_BOOT event when we are about to load and execute\r
   //    the boot option.\r
   //\r
-  Node   = BootOption->FilePath;\r
-  Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
-  if (!EFI_ERROR (Status) && CompareGuid (\r
-        EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
-        PcdGetPtr (PcdBootManagerMenuFile)\r
-        )) {\r
+  if (BmIsBootMenuAppFilePath (BootOption->FilePath)) {\r
     DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));\r
     BmStopHotkeyService (NULL, NULL);\r
   } else {\r
@@ -1642,13 +1663,29 @@ EfiBootManagerBoot (
   PERF_START_EX (gImageHandle, "BdsAttempt", NULL, 0, (UINT32) OptionNumber);\r
 \r
   //\r
-  // 5. Load EFI boot option to ImageHandle\r
+  // 5. Adjust the different type memory page number just before booting\r
+  //    and save the updated info into the variable for next boot to use\r
+  //\r
+  BmSetMemoryTypeInformationVariable (\r
+    (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT)\r
+  );\r
+\r
+  //\r
+  // 6. Load EFI boot option to ImageHandle\r
   //\r
+  DEBUG_CODE_BEGIN ();\r
+  if (BootOption->Description == NULL) {\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
+  } else {\r
+    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
+  }\r
+  DEBUG_CODE_END ();\r
+\r
   ImageHandle       = NULL;\r
   RamDiskDevicePath = NULL;\r
   if (DevicePathType (BootOption->FilePath) != BBS_DEVICE_PATH) {\r
     Status     = EFI_NOT_FOUND;\r
-    FileBuffer = BmGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
+    FileBuffer = EfiBootManagerGetLoadOptionBuffer (BootOption->FilePath, &FilePath, &FileSize);\r
     if (FileBuffer != NULL) {\r
       RamDiskDevicePath = BmGetRamDiskDevicePath (FilePath);\r
     }\r
@@ -1699,28 +1736,6 @@ EfiBootManagerBoot (
     }\r
   }\r
 \r
-  //\r
-  // 6. Adjust the different type memory page number just before booting\r
-  //    and save the updated info into the variable for next boot to use\r
-  //\r
-  if (RamDiskDevicePath == NULL) {\r
-    RamDiskSizeInPages = 0;\r
-  } else {\r
-    BmGetRamDiskMemoryInfo (RamDiskDevicePath, &RamDiskSizeInPages);\r
-  }\r
-  BmSetMemoryTypeInformationVariable (\r
-    (BOOLEAN) ((BootOption->Attributes & LOAD_OPTION_CATEGORY) == LOAD_OPTION_CATEGORY_BOOT),\r
-    RamDiskSizeInPages\r
-    );\r
-\r
-  DEBUG_CODE_BEGIN();\r
-    if (BootOption->Description == NULL) {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting from unknown device path\n"));\r
-    } else {\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "[Bds]Booting %s\n", BootOption->Description));\r
-    }\r
-  DEBUG_CODE_END();\r
-\r
   //\r
   // Check to see if we should legacy BOOT. If yes then do the legacy boot\r
   // Write boot to OS performance data for Legacy boot\r
@@ -1925,6 +1940,7 @@ BmEnumerateBootOptions (
   UINTN                                 Removable;\r
   UINTN                                 Index;\r
   CHAR16                                *Description;\r
+  UINT32                                BootAttributes;\r
 \r
   ASSERT (BootOptionCount != NULL);\r
 \r
@@ -2044,7 +2060,7 @@ BmEnumerateBootOptions (
   }\r
 \r
   //\r
-  // Parse load file, assuming UEFI Network boot option\r
+  // Parse load file protocol\r
   //\r
   gBS->LocateHandleBuffer (\r
          ByProtocol,\r
@@ -2063,11 +2079,19 @@ BmEnumerateBootOptions (
                     );\r
     ASSERT (BootOptions != NULL);\r
 \r
+    //\r
+    // If LoadFile includes BootMenuApp, its boot attribue will be set to APP and HIDDEN.\r
+    //\r
+    BootAttributes = LOAD_OPTION_ACTIVE;\r
+    if (BmIsBootMenuAppFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+      BootAttributes = LOAD_OPTION_CATEGORY_APP | LOAD_OPTION_ACTIVE | LOAD_OPTION_HIDDEN;\r
+    }\r
+\r
     Status = EfiBootManagerInitializeLoadOption (\r
                &BootOptions[(*BootOptionCount)++],\r
                LoadOptionNumberUnassigned,\r
                LoadOptionTypeBoot,\r
-               LOAD_OPTION_ACTIVE,\r
+               BootAttributes,\r
                Description,\r
                DevicePathFromHandle (Handles[Index]),\r
                NULL,\r
@@ -2158,7 +2182,7 @@ EfiBootManagerRefreshAllBootOption (
 }\r
 \r
 /**\r
-  This function is called to create the boot option for the Boot Manager Menu.\r
+  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
@@ -2166,8 +2190,10 @@ EfiBootManagerRefreshAllBootOption (
   @param  BootOption    Return the boot option of the Boot Manager Menu\r
 \r
   @retval EFI_SUCCESS   Successfully register the Boot Manager Menu.\r
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+  @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+  @retval others        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+                        and EFI_NOT_FOUND.\r
 **/\r
 EFI_STATUS\r
 BmRegisterBootManagerMenu (\r
@@ -2180,30 +2206,78 @@ BmRegisterBootManagerMenu (
   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
-  Status = GetSectionFromFv (\r
-             PcdGetPtr (PcdBootManagerMenuFile),\r
-             EFI_SECTION_USER_INTERFACE,\r
-             0,\r
-             (VOID **) &Description,\r
-             &DescriptionLength\r
-             );\r
-  if (EFI_ERROR (Status)) {\r
-    Description = NULL;\r
+  DevicePath = NULL;\r
+  //\r
+  // Try to find BootMenuApp from LoadFile protocol\r
+  //\r
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiLoadFileProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    if (BmIsBootMenuAppFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+      DevicePath  = DuplicateDevicePath (DevicePathFromHandle (Handles[Index]));\r
+      Description = BmGetBootDescription (Handles[Index]);\r
+      break;\r
+    }\r
+  }\r
+  if (HandleCount != 0) {\r
+    FreePool (Handles);\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
+  if (DevicePath == NULL) {\r
+    Data = NULL;\r
+    Status = GetSectionFromFv (\r
+               PcdGetPtr (PcdBootManagerMenuFile),\r
+               EFI_SECTION_PE32,\r
+               0,\r
+               (VOID **) &Data,\r
+               &DataSize\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
+    //\r
+    // Get BootManagerMenu application's description from EFI User Interface Section.\r
+    //\r
+    Status = GetSectionFromFv (\r
+               PcdGetPtr (PcdBootManagerMenuFile),\r
+               EFI_SECTION_USER_INTERFACE,\r
+               0,\r
+               (VOID **) &Description,\r
+               &DescriptionLength\r
+               );\r
+    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
              BootOption,\r
@@ -2236,12 +2310,14 @@ BmRegisterBootManagerMenu (
 /**\r
   Return the boot option corresponding to the Boot Manager Menu.\r
   It may automatically create one if the boot option hasn't been created yet.\r
-  \r
+\r
   @param BootOption    Return the Boot Manager Menu.\r
 \r
   @retval EFI_SUCCESS   The Boot Manager Menu is successfully returned.\r
-  @retval Status        Return status of gRT->SetVariable (). BootOption still points\r
-                        to the Boot Manager Menu even the Status is not EFI_SUCCESS.\r
+  @retval EFI_NOT_FOUND The Boot Manager Menu cannot be found.\r
+  @retval others        Return status of gRT->SetVariable (). BootOption still points\r
+                        to the Boot Manager Menu even the Status is not EFI_SUCCESS\r
+                        and EFI_NOT_FOUND.\r
 **/\r
 EFI_STATUS\r
 EFIAPI\r
@@ -2253,20 +2329,11 @@ EfiBootManagerGetBootManagerMenu (
   UINTN                        BootOptionCount;\r
   EFI_BOOT_MANAGER_LOAD_OPTION *BootOptions;\r
   UINTN                        Index;\r
-  EFI_DEVICE_PATH_PROTOCOL     *Node;\r
-  EFI_HANDLE                   FvHandle;\r
   \r
   BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
 \r
   for (Index = 0; Index < BootOptionCount; Index++) {\r
-    Node   = BootOptions[Index].FilePath;\r
-    Status = gBS->LocateDevicePath (&gEfiFirmwareVolume2ProtocolGuid, &Node, &FvHandle);\r
-    if (!EFI_ERROR (Status)) {\r
-      if (CompareGuid (\r
-            EfiGetNameGuidFromFwVolDevicePathNode ((CONST MEDIA_FW_VOL_FILEPATH_DEVICE_PATH *) Node),\r
-            PcdGetPtr (PcdBootManagerMenuFile)\r
-            )\r
-          ) {        \r
+    if (BmIsBootMenuAppFilePath (BootOptions[Index].FilePath)) {\r
         Status = EfiBootManagerInitializeLoadOption (\r
                    BootOption,\r
                    BootOptions[Index].OptionNumber,\r
@@ -2279,7 +2346,6 @@ EfiBootManagerGetBootManagerMenu (
                    );\r
         ASSERT_EFI_ERROR (Status);\r
         break;\r
-      }\r
     }\r
   }\r
 \r