]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/BdsDxe/BdsEntry.c
MdeModulePkg/BdsDxe: Initialize gConnectConInEvent earlier
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BdsEntry.c
index c86cd7a576adcd4c32f2055e2c5b507b2a661f69..b5e6ef61e1e19bff5ad0582c261431943f0f3d3c 100644 (file)
@@ -86,6 +86,81 @@ BdsDxeOnConnectConInCallBack (
     DEBUG ((EFI_D_WARN, "[Bds] Connect ConIn failed - %r!!!\n", Status));\r
   }\r
 }\r
+/**\r
+  Notify function for event group EFI_EVENT_GROUP_READY_TO_BOOT. This is used to\r
+  check whether there is remaining deferred load images.\r
+\r
+  @param[in]  Event   The Event that is being processed.\r
+  @param[in]  Context The Event Context.\r
+\r
+**/\r
+VOID\r
+EFIAPI\r
+CheckDeferredLoadImageOnReadyToBoot (\r
+  IN EFI_EVENT        Event,\r
+  IN VOID             *Context\r
+  )\r
+{\r
+  EFI_STATUS                         Status;\r
+  EFI_DEFERRED_IMAGE_LOAD_PROTOCOL   *DeferredImage;\r
+  UINTN                              HandleCount;\r
+  EFI_HANDLE                         *Handles;\r
+  UINTN                              Index;\r
+  UINTN                              ImageIndex;\r
+  EFI_DEVICE_PATH_PROTOCOL           *ImageDevicePath;\r
+  VOID                               *Image;\r
+  UINTN                              ImageSize;\r
+  BOOLEAN                            BootOption;\r
+  CHAR16                             *DevicePathStr;\r
+\r
+  //\r
+  // Find all the deferred image load protocols.\r
+  //\r
+  HandleCount = 0;\r
+  Handles = NULL;\r
+  Status = gBS->LocateHandleBuffer (\r
+    ByProtocol,\r
+    &gEfiDeferredImageLoadProtocolGuid,\r
+    NULL,\r
+    &HandleCount,\r
+    &Handles\r
+  );\r
+  if (EFI_ERROR (Status)) {\r
+    return;\r
+  }\r
+\r
+  for (Index = 0; Index < HandleCount; Index++) {\r
+    Status = gBS->HandleProtocol (Handles[Index], &gEfiDeferredImageLoadProtocolGuid, (VOID **) &DeferredImage);\r
+    if (EFI_ERROR (Status)) {\r
+      continue;\r
+    }\r
+\r
+    for (ImageIndex = 0; ; ImageIndex++) {\r
+      //\r
+      // Load all the deferred images in this protocol instance.\r
+      //\r
+      Status = DeferredImage->GetImageInfo (\r
+        DeferredImage,\r
+        ImageIndex,\r
+        &ImageDevicePath,\r
+        (VOID **) &Image,\r
+        &ImageSize,\r
+        &BootOption\r
+      );\r
+      if (EFI_ERROR (Status)) {\r
+        break;\r
+      }\r
+      DevicePathStr = ConvertDevicePathToText (ImageDevicePath, FALSE, FALSE);\r
+      DEBUG ((DEBUG_LOAD, "[Bds] Image was deferred but not loaded: %s.\n", DevicePathStr));\r
+      if (DevicePathStr != NULL) {\r
+        FreePool (DevicePathStr);\r
+      }\r
+    }\r
+  }\r
+  if (Handles != NULL) {\r
+    FreePool (Handles);\r
+  }\r
+}\r
 \r
 /**\r
 \r
@@ -119,6 +194,21 @@ BdsInitialize (
                   );\r
   ASSERT_EFI_ERROR (Status);\r
 \r
+  DEBUG_CODE (\r
+    EFI_EVENT   Event;\r
+    //\r
+    // Register notify function to check deferred images on ReadyToBoot Event.\r
+    //\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    CheckDeferredLoadImageOnReadyToBoot,\r
+                    NULL,\r
+                    &gEfiEventReadyToBootGuid,\r
+                    &Event\r
+                    );\r
+    ASSERT_EFI_ERROR (Status);\r
+  );\r
   return Status;\r
 }\r
 \r
@@ -353,17 +443,28 @@ ProcessLoadOptions (
       LoadOptionType = LoadOptions[Index].OptionType;\r
     }\r
     ASSERT (LoadOptionType == LoadOptions[Index].OptionType);\r
+    ASSERT (LoadOptionType != LoadOptionTypeBoot);\r
 \r
     Status = EfiBootManagerProcessLoadOption (&LoadOptions[Index]);\r
 \r
+    //\r
+    // Status indicates whether the load option is loaded and executed\r
+    // LoadOptions[Index].Status is what the load option returns\r
+    //\r
     if (!EFI_ERROR (Status)) {\r
-      if (LoadOptionType == LoadOptionTypePlatformRecovery) {\r
-        //\r
-        // Stop processing if any entry is successful\r
-        //\r
+      //\r
+      // Stop processing if any PlatformRecovery#### returns success.\r
+      //\r
+      if ((LoadOptions[Index].Status == EFI_SUCCESS) &&\r
+          (LoadOptionType == LoadOptionTypePlatformRecovery)) {\r
         break;\r
       }\r
-      if ((LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {\r
+\r
+      //\r
+      // Only set ReconnectAll flag when the load option executes successfully.\r
+      //\r
+      if (!EFI_ERROR (LoadOptions[Index].Status) &&\r
+          (LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {\r
         ReconnectAll = TRUE;\r
       }\r
     }\r
@@ -654,7 +755,7 @@ BdsEntry (
   Status = gBS->LocateProtocol (&gEdkiiVariableLockProtocolGuid, NULL, (VOID **) &VariableLock);\r
   DEBUG ((EFI_D_INFO, "[BdsDxe] Locate Variable Lock protocol - %r\n", Status));\r
   if (!EFI_ERROR (Status)) {\r
-    for (Index = 0; Index < sizeof (mReadOnlyVariables) / sizeof (mReadOnlyVariables[0]); Index++) {\r
+    for (Index = 0; Index < ARRAY_SIZE (mReadOnlyVariables); Index++) {\r
       Status = VariableLock->RequestToLock (VariableLock, mReadOnlyVariables[Index], &gEfiGlobalVariableGuid);\r
       ASSERT_EFI_ERROR (Status);\r
     }\r
@@ -736,7 +837,7 @@ BdsEntry (
   FilePath = FileDevicePath (NULL, EFI_REMOVABLE_MEDIA_FILE_NAME);\r
   Status = EfiBootManagerInitializeLoadOption (\r
              &LoadOption,\r
-             0,\r
+             LoadOptionNumberUnassigned,\r
              LoadOptionTypePlatformRecovery,\r
              LOAD_OPTION_ACTIVE,\r
              L"Default PlatformRecovery",\r
@@ -745,9 +846,24 @@ BdsEntry (
              0\r
              );\r
   ASSERT_EFI_ERROR (Status);\r
-  EfiBootManagerLoadOptionToVariable (&LoadOption);\r
+  LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypePlatformRecovery);\r
+  if (EfiBootManagerFindLoadOption (&LoadOption, LoadOptions, LoadOptionCount) == -1) {\r
+    for (Index = 0; Index < LoadOptionCount; Index++) {\r
+      //\r
+      // The PlatformRecovery#### options are sorted by OptionNumber.\r
+      // Find the the smallest unused number as the new OptionNumber.\r
+      //\r
+      if (LoadOptions[Index].OptionNumber != Index) {\r
+        break;\r
+      }\r
+    }\r
+    LoadOption.OptionNumber = Index;\r
+    Status = EfiBootManagerLoadOptionToVariable (&LoadOption);\r
+    ASSERT_EFI_ERROR (Status);\r
+  }\r
   EfiBootManagerFreeLoadOption (&LoadOption);\r
   FreePool (FilePath);\r
+  EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);\r
 \r
   //\r
   // Report Status Code to indicate connecting drivers will happen\r
@@ -757,6 +873,23 @@ BdsEntry (
     (EFI_SOFTWARE_DXE_BS_DRIVER | EFI_SW_DXE_BS_PC_BEGIN_CONNECTING_DRIVERS)\r
     );\r
 \r
+  //\r
+  // Initialize ConnectConIn event before calling platform code.\r
+  //\r
+  if (PcdGetBool (PcdConInConnectOnDemand)) {\r
+    Status = gBS->CreateEventEx (\r
+                    EVT_NOTIFY_SIGNAL,\r
+                    TPL_CALLBACK,\r
+                    BdsDxeOnConnectConInCallBack,\r
+                    NULL,\r
+                    &gConnectConInEventGuid,\r
+                    &gConnectConInEvent\r
+                    );\r
+    if (EFI_ERROR (Status)) {\r
+      gConnectConInEvent = NULL;\r
+    }\r
+  }\r
+\r
   //\r
   // Do the platform init, can be customized by OEM/IBV\r
   // Possible things that can be done in PlatformBootManagerBeforeConsole:\r
@@ -789,21 +922,9 @@ BdsEntry (
   if (PcdGetBool (PcdConInConnectOnDemand)) {\r
     EfiBootManagerConnectConsoleVariable (ConOut);\r
     EfiBootManagerConnectConsoleVariable (ErrOut);\r
-\r
     //\r
-    // Initialize ConnectConIn event\r
+    // Do not connect ConIn devices when lazy ConIn feature is ON.\r
     //\r
-    Status = gBS->CreateEventEx (\r
-                    EVT_NOTIFY_SIGNAL,\r
-                    TPL_CALLBACK,\r
-                    BdsDxeOnConnectConInCallBack,\r
-                    NULL,\r
-                    &gConnectConInEventGuid,\r
-                    &gConnectConInEvent\r
-                    );\r
-    if (EFI_ERROR (Status)) {\r
-      gConnectConInEvent = NULL;\r
-    }\r
   } else {\r
     EfiBootManagerConnectAllDefaultConsoles ();\r
   }\r