]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Library/UefiBootManagerLib/BmBoot.c
MdeModulePkg/UefiBootManagerLib: Generate boot description for NVME
[mirror_edk2.git] / MdeModulePkg / Library / UefiBootManagerLib / BmBoot.c
index 4da401d23cfd15d40afae5722a651e55cf05791a..8a3a4027eec0139d8203eee14a080eaf95cec3df 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   Library functions which relates with booting.\r
 \r
-Copyright (c) 2011 - 2016, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2011 - 2017, 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
@@ -991,9 +991,13 @@ BmExpandMediaDevicePath (
     return FileBuffer;\r
   }\r
 \r
+  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
+  ASSERT_EFI_ERROR (Status);\r
+\r
   //\r
-  // For device boot option only pointing to the removable device handle, \r
-  // should make sure all its children handles (its child partion or media handles) are created and connected. \r
+  // For device boot option only pointing to the removable device handle,\r
+  // should make sure all its children handles (its child partion or media handles)\r
+  // are created and connected.\r
   //\r
   gBS->ConnectController (Handle, NULL, NULL, TRUE);\r
 \r
@@ -1004,8 +1008,6 @@ BmExpandMediaDevicePath (
   // returned. After the Block IO protocol is reinstalled, subsequent\r
   // Block IO read/write will success.\r
   //\r
-  Status = gBS->LocateDevicePath (&gEfiBlockIoProtocolGuid, &TempDevicePath, &Handle);\r
-  ASSERT_EFI_ERROR (Status);\r
   Status = gBS->HandleProtocol (Handle, &gEfiBlockIoProtocolGuid, (VOID **) &BlockIo);\r
   ASSERT_EFI_ERROR (Status);\r
   Buffer = AllocatePool (BlockIo->Media->BlockSize);\r
@@ -1529,6 +1531,34 @@ EfiBootManagerGetLoadOptionBuffer (
   return BmGetFileBufferFromLoadFiles (FilePath, FullPath, FileSize);\r
 }\r
 \r
+/**\r
+  Check if it's a Device Path pointing to BootManagerMenu.\r
+\r
+  @param  DevicePath     Input device path.\r
+\r
+  @retval TRUE   The device path is BootManagerMenu File Device Path.\r
+  @retval FALSE  The device path is NOT BootManagerMenu File Device Path.\r
+**/\r
+BOOLEAN\r
+BmIsBootManagerMenuFilePath (\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
@@ -1562,14 +1592,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
@@ -1620,12 +1647,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 (BmIsBootManagerMenuFilePath (BootOption->FilePath)) {\r
     DEBUG ((EFI_D_INFO, "[Bds] Booting Boot Manager Menu.\n"));\r
     BmStopHotkeyService (NULL, NULL);\r
   } else {\r
@@ -1643,8 +1665,24 @@ 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
@@ -1700,28 +1738,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
@@ -2045,7 +2061,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
@@ -2055,6 +2071,12 @@ BmEnumerateBootOptions (
          &Handles\r
          );\r
   for (Index = 0; Index < HandleCount; Index++) {\r
+    //\r
+    // Ignore BootManagerMenu. its boot option will be created by EfiBootManagerGetBootManagerMenu().\r
+    //\r
+    if (BmIsBootManagerMenuFilePath (DevicePathFromHandle (Handles[Index]))) {\r
+      continue;\r
+    }\r
 \r
     Description = BmGetBootDescription (Handles[Index]);\r
     BootOptions = ReallocatePool (\r
@@ -2132,7 +2154,7 @@ EfiBootManagerRefreshAllBootOption (
       // Only check those added by BDS\r
       // so that the boot options added by end-user or OS installer won't be deleted\r
       //\r
-      if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == (UINTN) -1) {\r
+      if (EfiBootManagerFindLoadOption (&NvBootOptions[Index], BootOptions, BootOptionCount) == -1) {\r
         Status = EfiBootManagerDeleteLoadOptionVariable (NvBootOptions[Index].OptionNumber, LoadOptionTypeBoot);\r
         //\r
         // Deleting variable with current variable implementation shouldn't fail.\r
@@ -2146,7 +2168,7 @@ EfiBootManagerRefreshAllBootOption (
   // Add new EFI boot options to NV\r
   //\r
   for (Index = 0; Index < BootOptionCount; Index++) {\r
-    if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == (UINTN) -1) {\r
+    if (EfiBootManagerFindLoadOption (&BootOptions[Index], NvBootOptions, NvBootOptionCount) == -1) {\r
       EfiBootManagerAddLoadOptionVariable (&BootOptions[Index], (UINTN) -1);\r
       //\r
       // Try best to add the boot options so continue upon failure.\r
@@ -2183,51 +2205,79 @@ 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
-  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
+  DevicePath = NULL;\r
+  Description = NULL;\r
   //\r
-  // Get BootManagerMenu application's description from EFI User Interface Section.\r
+  // Try to find BootManagerMenu from LoadFile protocol\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
+  gBS->LocateHandleBuffer (\r
+         ByProtocol,\r
+         &gEfiLoadFileProtocolGuid,\r
+         NULL,\r
+         &HandleCount,\r
+         &Handles\r
+         );\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    if (BmIsBootManagerMenuFilePath (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
@@ -2279,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 (BmIsBootManagerMenuFilePath (BootOptions[Index].FilePath)) {\r
         Status = EfiBootManagerInitializeLoadOption (\r
                    BootOption,\r
                    BootOptions[Index].OptionNumber,\r
@@ -2305,7 +2346,6 @@ EfiBootManagerGetBootManagerMenu (
                    );\r
         ASSERT_EFI_ERROR (Status);\r
         break;\r
-      }\r
     }\r
   }\r
 \r