]> git.proxmox.com Git - mirror_edk2.git/blobdiff - MdeModulePkg/Universal/BdsDxe/BdsEntry.c
MdeModulePkg: Process Sys Prep load options in BdsDxe driver.
[mirror_edk2.git] / MdeModulePkg / Universal / BdsDxe / BdsEntry.c
index 7eebe8402110f0d9cab239ab1c27eb6a9b02bb20..020f18d48c3a7bb0d0cf8d59f7dcf536d4b45caa 100644 (file)
@@ -47,6 +47,12 @@ CHAR16  *mReadOnlyVariables[] = {
   EFI_OS_INDICATIONS_SUPPORT_VARIABLE_NAME\r
   };\r
 \r
+CHAR16 *mBdsLoadOptionName[] = {\r
+  L"Driver",\r
+  L"SysPrep",\r
+  L"Boot"\r
+};\r
+\r
 CHAR16  mRecoveryBoot[] = L"Recovery Boot";\r
 /**\r
   Event to Connect ConIn.\r
@@ -75,7 +81,7 @@ BdsDxeOnConnectConInCallBack (
     // Should not enter this case, if enter, the keyboard will not work.\r
     // May need platfrom policy to connect keyboard.\r
     //\r
-    DEBUG ((EFI_D_WARN, "[Bds] ASSERT Connect ConIn failed!!!\n"));\r
+    DEBUG ((EFI_D_WARN, "[Bds] Connect ConIn failed - %r!!!\n", Status));\r
   }\r
 }\r
 \r
@@ -553,103 +559,55 @@ DefaultBootBehavior (
 }\r
 \r
 /**\r
-  The function will go through the driver option link list, load and start\r
-  every driver the driver option device path point to.\r
+  The function will load and start every Driver####/SysPrep####.\r
 \r
-  @param  DriverOption        Input driver option array.\r
-  @param  DriverOptionCount   Input driver option count.\r
+  @param  LoadOptions        Load option array.\r
+  @param  LoadOptionCount    Load option count.\r
 \r
 **/\r
 VOID\r
-LoadDrivers (\r
-  IN EFI_BOOT_MANAGER_LOAD_OPTION       *DriverOption,\r
-  IN UINTN                              DriverOptionCount\r
+ProcessLoadOptions (\r
+  IN EFI_BOOT_MANAGER_LOAD_OPTION       *LoadOptions,\r
+  IN UINTN                              LoadOptionCount\r
   )\r
 {\r
-  EFI_STATUS                Status;\r
-  UINTN                     Index;\r
-  EFI_HANDLE                ImageHandle;\r
-  EFI_LOADED_IMAGE_PROTOCOL *ImageInfo;\r
-  BOOLEAN                   ReconnectAll;\r
+  EFI_STATUS                        Status;\r
+  UINTN                             Index;\r
+  BOOLEAN                           ReconnectAll;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;\r
 \r
   ReconnectAll = FALSE;\r
+  LoadOptionType = LoadOptionTypeMax;\r
 \r
   //\r
   // Process the driver option\r
   //\r
-  for (Index = 0; Index < DriverOptionCount; Index++) {\r
+  for (Index = 0; Index < LoadOptionCount; Index++) {\r
     //\r
-    // If a load option is not marked as LOAD_OPTION_ACTIVE,\r
-    // the boot manager will not automatically load the option.\r
+    // All the load options in the array should be of the same type.\r
     //\r
-    if ((DriverOption[Index].Attributes & LOAD_OPTION_ACTIVE) == 0) {\r
-      continue;\r
-    }\r
-    \r
-    //\r
-    // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
-    // then all of the EFI drivers in the system will be disconnected and\r
-    // reconnected after the last driver load option is processed.\r
-    //\r
-    if ((DriverOption[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0) {\r
-      ReconnectAll = TRUE;\r
+    if (LoadOptionType == LoadOptionTypeMax) {\r
+      LoadOptionType = LoadOptions[Index].OptionType;\r
     }\r
-    \r
-    //\r
-    // Make sure the driver path is connected.\r
-    //\r
-    EfiBootManagerConnectDevicePath (DriverOption[Index].FilePath, NULL);\r
+    ASSERT (LoadOptionType == LoadOptions[Index].OptionType);\r
+    ASSERT (LoadOptionType == LoadOptionTypeDriver || LoadOptionType == LoadOptionTypeSysPrep);\r
 \r
-    //\r
-    // Load and start the image that Driver#### describes\r
-    //\r
-    Status = gBS->LoadImage (\r
-                    FALSE,\r
-                    gImageHandle,\r
-                    DriverOption[Index].FilePath,\r
-                    NULL,\r
-                    0,\r
-                    &ImageHandle\r
-                    );\r
+    Status = EfiBootManagerProcessLoadOption (&LoadOptions[Index]);\r
 \r
-    if (!EFI_ERROR (Status)) {\r
-      gBS->HandleProtocol (ImageHandle, &gEfiLoadedImageProtocolGuid, (VOID **) &ImageInfo);\r
-\r
-      //\r
-      // Verify whether this image is a driver, if not,\r
-      // exit it and continue to parse next load option\r
-      //\r
-      if (ImageInfo->ImageCodeType != EfiBootServicesCode && ImageInfo->ImageCodeType != EfiRuntimeServicesCode) {\r
-        gBS->Exit (ImageHandle, EFI_INVALID_PARAMETER, 0, NULL);\r
-        continue;\r
-      }\r
-\r
-      ImageInfo->LoadOptionsSize  = DriverOption[Index].OptionalDataSize;\r
-      ImageInfo->LoadOptions      = DriverOption[Index].OptionalData;\r
-      //\r
-      // Before calling the image, enable the Watchdog Timer for\r
-      // the 5 Minute period\r
-      //\r
-      gBS->SetWatchdogTimer (5 * 60, 0x0000, 0x00, NULL);\r
-\r
-      DriverOption[Index].Status = gBS->StartImage (ImageHandle, &DriverOption[Index].ExitDataSize, &DriverOption[Index].ExitData);\r
-      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Driver Return Status = %r\n", DriverOption[Index].Status));\r
-\r
-      //\r
-      // Clear the Watchdog Timer after the image returns\r
-      //\r
-      gBS->SetWatchdogTimer (0x0000, 0x0000, 0x0000, NULL);\r
+    if (!EFI_ERROR (Status) && ((LoadOptions[Index].Attributes & LOAD_OPTION_FORCE_RECONNECT) != 0)) {\r
+      ReconnectAll = TRUE;\r
     }\r
   }\r
-  \r
+\r
   //\r
-  // Process the LOAD_OPTION_FORCE_RECONNECT driver option\r
+  // If a driver load option is marked as LOAD_OPTION_FORCE_RECONNECT,\r
+  // then all of the EFI drivers in the system will be disconnected and\r
+  // reconnected after the last driver load option is processed.\r
   //\r
-  if (ReconnectAll) {\r
+  if (ReconnectAll && LoadOptionType == LoadOptionTypeDriver) {\r
     EfiBootManagerDisconnectAll ();\r
     EfiBootManagerConnectAll ();\r
   }\r
-\r
 }\r
 \r
 /**\r
@@ -855,9 +813,8 @@ BdsEntry (
   IN EFI_BDS_ARCH_PROTOCOL  *This\r
   )\r
 {\r
-  EFI_BOOT_MANAGER_LOAD_OPTION    *DriverOption;\r
-  EFI_BOOT_MANAGER_LOAD_OPTION    BootOption;\r
-  UINTN                           DriverOptionCount;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    *LoadOptions;\r
+  UINTN                           LoadOptionCount;\r
   CHAR16                          *FirmwareVendor;\r
   EFI_EVENT                       HotkeyTriggered;\r
   UINT64                          OsIndication;\r
@@ -867,8 +824,11 @@ BdsEntry (
   UINT16                          BootTimeOut;\r
   EDKII_VARIABLE_LOCK_PROTOCOL    *VariableLock;\r
   UINTN                           Index;\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    BootOption;\r
   UINT16                          *BootNext;\r
   CHAR16                          BootNextVariableName[sizeof ("Boot####")];\r
+  EFI_BOOT_MANAGER_LOAD_OPTION    BootManagerMenu;\r
+  BOOLEAN                         BootFwUi;\r
 \r
   HotkeyTriggered = NULL;\r
   Status          = EFI_SUCCESS;\r
@@ -939,7 +899,7 @@ BdsEntry (
   // Initialize L"BootOptionSupport" EFI global variable.\r
   // Lazy-ConIn implictly disables BDS hotkey.\r
   //\r
-  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP;\r
+  BootOptionSupport = EFI_BOOT_OPTION_SUPPORT_APP | EFI_BOOT_OPTION_SUPPORT_SYSPREP;\r
   if (!PcdGetBool (PcdConInConnectOnDemand)) {\r
     BootOptionSupport |= EFI_BOOT_OPTION_SUPPORT_KEY;\r
     SET_BOOT_OPTION_SUPPORT_KEY_COUNT (BootOptionSupport, 3);\r
@@ -1010,11 +970,11 @@ BdsEntry (
   EfiBootManagerStartHotkeyService (&HotkeyTriggered);\r
 \r
   //\r
-  // Load Driver Options\r
+  // Execute Driver Options\r
   //\r
-  DriverOption = EfiBootManagerGetLoadOptions (&DriverOptionCount, LoadOptionTypeDriver);\r
-  LoadDrivers (DriverOption, DriverOptionCount);\r
-  EfiBootManagerFreeLoadOptions (DriverOption, DriverOptionCount);\r
+  LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeDriver);\r
+  ProcessLoadOptions (LoadOptions, LoadOptionCount);\r
+  EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);\r
 \r
   //\r
   // Connect consoles\r
@@ -1059,23 +1019,28 @@ BdsEntry (
   PERF_END   (NULL, "PlatformBootManagerAfterConsole", "BDS", 0);\r
 \r
   DEBUG_CODE (\r
-    EFI_BOOT_MANAGER_LOAD_OPTION    *BootOptions;\r
-    UINTN                           BootOptionCount;\r
-    UINTN                           Index;\r
-\r
-    BootOptions = EfiBootManagerGetLoadOptions (&BootOptionCount, LoadOptionTypeBoot);\r
-    DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options=============\n"));\r
-    for (Index = 0; Index < BootOptionCount; Index++) {\r
+    UINTN                             Index;\r
+    EFI_BOOT_MANAGER_LOAD_OPTION_TYPE LoadOptionType;\r
+    DEBUG ((EFI_D_INFO, "[Bds]=============Begin Load Options Dumping ...=============\n"));\r
+    for (LoadOptionType = 0; LoadOptionType < LoadOptionTypeMax; LoadOptionType++) {\r
       DEBUG ((\r
-        EFI_D_INFO, "[Bds]Boot%04x: %s \t\t 0x%04x\n",\r
-        BootOptions[Index].OptionNumber, \r
-        BootOptions[Index].Description, \r
-        BootOptions[Index].Attributes\r
+        EFI_D_INFO, "  %s Options:\n",\r
+        mBdsLoadOptionName[LoadOptionType]\r
         ));\r
+      LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionType);\r
+      for (Index = 0; Index < LoadOptionCount; Index++) {\r
+        DEBUG ((\r
+          EFI_D_INFO, "    %s%04x: %s \t\t 0x%04x\n",\r
+          mBdsLoadOptionName[LoadOptionType],\r
+          LoadOptions[Index].OptionNumber,\r
+          LoadOptions[Index].Description,\r
+          LoadOptions[Index].Attributes\r
+          ));\r
+      }\r
+      EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);\r
     }\r
-    DEBUG ((EFI_D_INFO, "[Bds]=============Dumping Boot Options Finished====\n"));\r
-    EfiBootManagerFreeLoadOptions (BootOptions, BootOptionCount);\r
-    );\r
+    DEBUG ((EFI_D_INFO, "[Bds]=============End Load Options Dumping=============\n"));\r
+  );\r
 \r
   //\r
   // Boot to Boot Manager Menu when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot\r
@@ -1088,10 +1053,15 @@ BdsEntry (
                   &DataSize,\r
                   &OsIndication\r
                   );\r
-  if (!EFI_ERROR(Status) && ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0)) {\r
-    //\r
-    // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS\r
-    // \r
+  if (EFI_ERROR (Status)) {\r
+    OsIndication = 0;\r
+  }\r
+\r
+  BootFwUi = (BOOLEAN) ((OsIndication & EFI_OS_INDICATIONS_BOOT_TO_FW_UI) != 0);\r
+  //\r
+  // Clear EFI_OS_INDICATIONS_BOOT_TO_FW_UI to acknowledge OS\r
+  // \r
+  if (BootFwUi) {\r
     OsIndication &= ~((UINT64) EFI_OS_INDICATIONS_BOOT_TO_FW_UI);\r
     Status = gRT->SetVariable (\r
                L"OsIndications",\r
@@ -1104,7 +1074,12 @@ BdsEntry (
     // Changing the content without increasing its size with current variable implementation shouldn't fail.\r
     //\r
     ASSERT_EFI_ERROR (Status);\r
+  }\r
 \r
+  //\r
+  // Launch Boot Manager Menu directly when EFI_OS_INDICATIONS_BOOT_TO_FW_UI is set. Skip HotkeyBoot\r
+  //\r
+  if (BootFwUi) {\r
     //\r
     // Follow generic rule, Call BdsDxeOnConnectConInCallBack to connect ConIn before enter UI\r
     //\r
@@ -1113,24 +1088,35 @@ BdsEntry (
     }\r
 \r
     //\r
-    // Directly boot to Boot Manager Menu.\r
+    // Directly enter the setup page.\r
+    // BootManagerMenu always contains the correct information even call fails.\r
     //\r
-    EfiBootManagerGetBootManagerMenu (&BootOption);\r
-    EfiBootManagerBoot (&BootOption);\r
-    EfiBootManagerFreeLoadOption (&BootOption);\r
-  } else {\r
-    PERF_START (NULL, "BdsWait", "BDS", 0);\r
-    BdsWait (HotkeyTriggered);\r
-    PERF_END   (NULL, "BdsWait", "BDS", 0);\r
-\r
-    //\r
-    // BdsReadKeys() be removed after all keyboard drivers invoke callback in timer callback.\r
-    //\r
-    BdsReadKeys ();\r
-    \r
-    EfiBootManagerHotkeyBoot ();\r
+    EfiBootManagerGetBootManagerMenu (&BootManagerMenu);\r
+    EfiBootManagerBoot (&BootManagerMenu);\r
+    EfiBootManagerFreeLoadOption (&BootManagerMenu);\r
   }\r
 \r
+  //\r
+  // Execute SysPrep####\r
+  //\r
+  LoadOptions = EfiBootManagerGetLoadOptions (&LoadOptionCount, LoadOptionTypeSysPrep);\r
+  ProcessLoadOptions (LoadOptions, LoadOptionCount);\r
+  EfiBootManagerFreeLoadOptions (LoadOptions, LoadOptionCount);\r
+\r
+  //\r
+  // Execute Key####\r
+  //\r
+  PERF_START (NULL, "BdsWait", "BDS", 0);\r
+  BdsWait (HotkeyTriggered);\r
+  PERF_END   (NULL, "BdsWait", "BDS", 0);\r
+\r
+  //\r
+  // BdsReadKeys() be removed after all keyboard drivers invoke callback in timer callback.\r
+  //\r
+  BdsReadKeys ();\r
+\r
+  EfiBootManagerHotkeyBoot ();\r
+\r
   //\r
   // Boot to "BootNext"\r
   //\r