]> git.proxmox.com Git - mirror_edk2.git/blobdiff - IntelFrameworkModulePkg/Library/GenericBdsLib/BdsBoot.c
For network dynamic media detect support: invoke Snp->GetStatus() before use Snp...
[mirror_edk2.git] / IntelFrameworkModulePkg / Library / GenericBdsLib / BdsBoot.c
index e6b2fe4d17cf6539a042ac9cc5f8fe4f8115a535..59e3a6e20f592ce9ba5b7048e0bfb6bfb2a49e67 100644 (file)
@@ -13,8 +13,10 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 **/\r
 \r
 #include "InternalBdsLib.h"\r
+#include "String.h"\r
 \r
 BOOLEAN mEnumBootDevice = FALSE;\r
+EFI_HII_HANDLE gBdsLibStringPackHandle = NULL;\r
 \r
 ///\r
 /// This GUID is used for an EFI Variable that stores the front device pathes\r
@@ -22,6 +24,49 @@ BOOLEAN mEnumBootDevice = FALSE;
 ///\r
 EFI_GUID  mHdBootVariablePrivateGuid = { 0xfab7e9e1, 0x39dd, 0x4f2b, { 0x84, 0x8, 0xe2, 0xe, 0x90, 0x6c, 0xb6, 0xde } };\r
 \r
+///\r
+/// This GUID is used for register UNI string.\r
+///\r
+EFI_GUID mBdsLibStringPackGuid = {  0x3b4d9b23, 0x95ac, 0x44f6, { 0x9f, 0xcd, 0xe, 0x95, 0x94, 0x58, 0x6c, 0x72 } };\r
+\r
+///\r
+/// This GUID is used for Set/Get platform language into/from variable at last time enumeration to ensure the enumeration will\r
+/// only execute once.\r
+///\r
+EFI_GUID mBdsLibLastLangGuid = { 0xe8c545b, 0xa2ee, 0x470d, { 0x8e, 0x26, 0xbd, 0xa1, 0xa1, 0x3c, 0xa, 0xa3 } };\r
+\r
+/**\r
+  The constructor function register UNI strings into imageHandle.\r
+  \r
+  It will ASSERT() if that operation fails and it will always return EFI_SUCCESS. \r
+\r
+  @param  ImageHandle   The firmware allocated handle for the EFI image.\r
+  @param  SystemTable   A pointer to the EFI System Table.\r
+  \r
+  @retval EFI_SUCCESS   The constructor successfully added string package.\r
+  @retval Other value   The constructor can't add string package.\r
+\r
+**/\r
+EFI_STATUS\r
+EFIAPI\r
+GenericBdsLibConstructor (\r
+  IN EFI_HANDLE        ImageHandle,\r
+  IN EFI_SYSTEM_TABLE  *SystemTable\r
+  )\r
+{\r
+\r
+  gBdsLibStringPackHandle = HiiAddPackages (\r
+                              &mBdsLibStringPackGuid,\r
+                              &ImageHandle,\r
+                              GenericBdsLibStrings,\r
+                              NULL\r
+                              );\r
+\r
+  ASSERT (gBdsLibStringPackHandle != NULL);\r
+\r
+  return EFI_SUCCESS;\r
+}\r
+\r
 \r
 \r
 /**\r
@@ -241,67 +286,13 @@ BdsLibBootViaBootOption (
   }\r
 \r
   DEBUG_CODE_BEGIN();\r
-    UINTN                     DevicePathTypeValue;\r
-    CHAR16                    *HiiString;\r
-    CHAR16                    *BootStringNumber;\r
-    UINTN                     BufferSize;\r
-  \r
-    DevicePathTypeValue = BdsGetBootTypeFromDevicePath (Option->DevicePath);\r
-  \r
-    //\r
-    // store number string of boot option temporary.\r
-    //\r
-    HiiString = NULL;\r
-    switch (DevicePathTypeValue) {\r
-    case BDS_EFI_ACPI_FLOPPY_BOOT:\r
-      HiiString = L"EFI Floppy";\r
-      break;\r
-    case BDS_EFI_MEDIA_CDROM_BOOT:\r
-    case BDS_EFI_MESSAGE_SATA_BOOT:\r
-    case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
-      HiiString = L"EFI DVD/CDROM";\r
-      break;\r
-    case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
-      HiiString = L"EFI USB Device";\r
-      break;\r
-    case BDS_EFI_MESSAGE_SCSI_BOOT:\r
-      HiiString = L"EFI SCSI Device";\r
-      break;\r
-    case BDS_EFI_MESSAGE_MISC_BOOT:\r
-      HiiString = L"EFI Misc Device";\r
-      break;\r
-    case BDS_EFI_MESSAGE_MAC_BOOT:\r
-      HiiString = L"EFI Network";\r
-      break;\r
-    case BBS_DEVICE_PATH:\r
-      //\r
-      // Do nothing for legacy boot option.\r
-      //\r
-      break;\r
-    default:\r
-      DEBUG((EFI_D_INFO, "Can not find HiiString for given device path type 0x%x\n", DevicePathTypeValue));\r
-    }\r
 \r
-    //\r
-    // If found Hii description string then cat Hii string with original description.\r
-    //\r
-    if (HiiString != NULL) {\r
-      BootStringNumber = Option->Description;\r
-      BufferSize = StrSize(BootStringNumber);\r
-      BufferSize += StrSize(HiiString);\r
-      Option->Description = AllocateZeroPool(BufferSize);\r
-      ASSERT (Option->Description != NULL);\r
-      StrCpy (Option->Description, HiiString);\r
-      if (StrnCmp (BootStringNumber, L"0", 1) != 0) {\r
-        StrCat (Option->Description, L" ");\r
-        StrCat (Option->Description, BootStringNumber);\r
-      } \r
-      \r
-      FreePool (BootStringNumber);\r
+    if (Option->Description == NULL) {\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting from unknown device path\n"));\r
+    } else {\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
     }\r
-  \r
-    DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Booting %S\n", Option->Description));\r
-    \r
+        \r
   DEBUG_CODE_END();\r
   \r
   Status = gBS->LoadImage (\r
@@ -991,8 +982,8 @@ BdsLibEnumerateAllBootOption (
   EFI_HANDLE                    *BlockIoHandles;\r
   EFI_BLOCK_IO_PROTOCOL         *BlkIo;\r
   UINTN                         Index;\r
-  UINTN                         NumberNetworkHandles;\r
-  EFI_HANDLE                    *NetworkHandles;\r
+  UINTN                         NumOfLoadFileHandles;\r
+  EFI_HANDLE                    *LoadFileHandles;\r
   UINTN                         FvHandleCount;\r
   EFI_HANDLE                    *FvHandleBuffer;\r
   EFI_FV_FILETYPE               Type;\r
@@ -1007,6 +998,8 @@ BdsLibEnumerateAllBootOption (
   UINTN                         NumberFileSystemHandles;\r
   BOOLEAN                       NeedDelete;\r
   EFI_IMAGE_DOS_HEADER          DosHeader;\r
+  CHAR8                         *PlatLang;\r
+  CHAR8                         *LastLang;\r
   EFI_IMAGE_OPTIONAL_HEADER_UNION       HdrData;\r
   EFI_IMAGE_OPTIONAL_HEADER_PTR_UNION   Hdr;\r
 \r
@@ -1015,6 +1008,8 @@ BdsLibEnumerateAllBootOption (
   UsbNumber     = 0;\r
   MiscNumber    = 0;\r
   ScsiNumber    = 0;\r
+  PlatLang      = NULL;\r
+  LastLang      = NULL;\r
   ZeroMem (Buffer, sizeof (Buffer));\r
 \r
   //\r
@@ -1022,8 +1017,21 @@ BdsLibEnumerateAllBootOption (
   // device from the boot order variable\r
   //\r
   if (mEnumBootDevice) {\r
-    Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
-    return Status;\r
+    LastLang = GetVariable (L"LastEnumLang", &mBdsLibLastLangGuid);\r
+    PlatLang = GetEfiGlobalVariable (L"PlatformLang");\r
+    if (LastLang == PlatLang) {\r
+      Status = BdsLibBuildOptionFromVar (BdsBootOptionList, L"BootOrder");\r
+      return Status;\r
+    } else {\r
+      Status = gRT->SetVariable (\r
+        L"LastEnumLang",\r
+        &mBdsLibLastLangGuid,\r
+        EFI_VARIABLE_BOOTSERVICE_ACCESS | EFI_VARIABLE_NON_VOLATILE,\r
+        sizeof (PlatLang),\r
+        PlatLang\r
+        );\r
+      ASSERT_EFI_ERROR (Status);\r
+    }\r
   }\r
 \r
   //\r
@@ -1068,7 +1076,11 @@ BdsLibEnumerateAllBootOption (
 \r
     switch (DevicePathType) {\r
     case BDS_EFI_ACPI_FLOPPY_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", FloppyNumber);\r
+      if (FloppyNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)), FloppyNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_FLOPPY)));\r
+      }\r
       BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
       FloppyNumber++;\r
       break;\r
@@ -1078,25 +1090,42 @@ BdsLibEnumerateAllBootOption (
     //\r
     case BDS_EFI_MESSAGE_ATAPI_BOOT:\r
     case BDS_EFI_MESSAGE_SATA_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", CdromNumber);\r
+      if (CdromNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)), CdromNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_CD_DVD)));\r
+      }\r
+      DEBUG ((DEBUG_INFO | DEBUG_LOAD, "Buffer: %S\n", Buffer));\r
       BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
       CdromNumber++;\r
       break;\r
 \r
     case BDS_EFI_MESSAGE_USB_DEVICE_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", UsbNumber);\r
+      if (UsbNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)), UsbNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_USB)));\r
+      }\r
       BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
       UsbNumber++;\r
       break;\r
 \r
     case BDS_EFI_MESSAGE_SCSI_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", ScsiNumber);\r
+      if (ScsiNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)), ScsiNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_SCSI)));\r
+      }\r
       BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
       ScsiNumber++;\r
       break;\r
 \r
     case BDS_EFI_MESSAGE_MISC_BOOT:\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", MiscNumber);\r
+      if (MiscNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)), MiscNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_MISC)));\r
+      }\r
       BdsLibBuildOptionFromHandle (BlockIoHandles[Index], BdsBootOptionList, Buffer);\r
       MiscNumber++;\r
       break;\r
@@ -1158,7 +1187,11 @@ BdsLibEnumerateAllBootOption (
       //\r
       BdsLibDeleteOptionFromHandle (FileSystemHandles[Index]);\r
     } else {\r
-      UnicodeSPrint (Buffer, sizeof (Buffer), L"EFI Non-Block Boot Device %d", NonBlockNumber);\r
+      if (NonBlockNumber != 0) {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)), NonBlockNumber);\r
+      } else {\r
+        UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NON_BLOCK)));\r
+      }\r
       BdsLibBuildOptionFromHandle (FileSystemHandles[Index], BdsBootOptionList, Buffer);\r
       NonBlockNumber++;\r
     }\r
@@ -1171,37 +1204,29 @@ BdsLibEnumerateAllBootOption (
   //\r
   // Parse Network Boot Device\r
   //\r
-  NumberNetworkHandles = 0;\r
+  NumOfLoadFileHandles = 0;\r
   //\r
-  // Search MNP Service Binding protocol for UEFI network stack\r
+  // Search Load File protocol for PXE boot option.\r
   //\r
   gBS->LocateHandleBuffer (\r
         ByProtocol,\r
-        &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+        &gEfiLoadFileProtocolGuid,\r
         NULL,\r
-        &NumberNetworkHandles,\r
-        &NetworkHandles\r
+        &NumOfLoadFileHandles,\r
+        &LoadFileHandles\r
         );\r
-  if (NumberNetworkHandles == 0) {\r
-    //\r
-    // MNP Service Binding protocol not found, search SNP for EFI network stack\r
-    //\r
-    gBS->LocateHandleBuffer (\r
-          ByProtocol,\r
-          &gEfiSimpleNetworkProtocolGuid,\r
-          NULL,\r
-          &NumberNetworkHandles,\r
-          &NetworkHandles\r
-          );\r
-  }\r
 \r
-  for (Index = 0; Index < NumberNetworkHandles; Index++) {\r
-    UnicodeSPrint (Buffer, sizeof (Buffer), L"%d", Index);\r
-    BdsLibBuildOptionFromHandle (NetworkHandles[Index], BdsBootOptionList, Buffer);\r
+  for (Index = 0; Index < NumOfLoadFileHandles; Index++) {\r
+    if (Index != 0) {\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"%s %d", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)), Index);\r
+    } else {\r
+      UnicodeSPrint (Buffer, sizeof (Buffer), L"%s", BdsLibGetStringById (STRING_TOKEN (STR_DESCRIPTION_NETWORK)));\r
+    }\r
+    BdsLibBuildOptionFromHandle (LoadFileHandles[Index], BdsBootOptionList, Buffer);\r
   }\r
 \r
-  if (NumberNetworkHandles != 0) {\r
-    FreePool (NetworkHandles);\r
+  if (NumOfLoadFileHandles != 0) {\r
+    FreePool (LoadFileHandles);\r
   }\r
 \r
   //\r
@@ -1551,21 +1576,15 @@ BdsLibNetworkBootWithMediaPresent (
   EFI_HANDLE                      Handle;\r
   EFI_SIMPLE_NETWORK_PROTOCOL     *Snp;\r
   BOOLEAN                         MediaPresent;\r
+  UINT32                          InterruptStatus;\r
 \r
   MediaPresent = FALSE;\r
 \r
   UpdatedDevicePath = DevicePath;\r
   //\r
-  // Locate MNP Service Binding protocol for UEFI network stack first\r
+  // Locate Load File Protocol for PXE boot option first\r
   //\r
-  Status = gBS->LocateDevicePath (&gEfiManagedNetworkServiceBindingProtocolGuid, &UpdatedDevicePath, &Handle);\r
-  if (EFI_ERROR (Status)) {\r
-    //\r
-    // MNP Service Binding protocol not found, search SNP for EFI network stack\r
-    //\r
-    UpdatedDevicePath = DevicePath;\r
-    Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
-  }\r
+  Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // Device not present so see if we need to connect it\r
@@ -1575,11 +1594,7 @@ BdsLibNetworkBootWithMediaPresent (
       //\r
       // This one should work after we did the connect\r
       //\r
-      Status = gBS->LocateDevicePath (&gEfiManagedNetworkServiceBindingProtocolGuid, &UpdatedDevicePath, &Handle);\r
-      if (EFI_ERROR (Status)) {\r
-        UpdatedDevicePath = DevicePath;\r
-        Status = gBS->LocateDevicePath (&gEfiSimpleNetworkProtocolGuid, &UpdatedDevicePath, &Handle);\r
-      }\r
+      Status = gBS->LocateDevicePath (&gEfiLoadFileProtocolGuid, &UpdatedDevicePath, &Handle);\r
     }\r
   }\r
 \r
@@ -1604,6 +1619,11 @@ BdsLibNetworkBootWithMediaPresent (
     if (!EFI_ERROR (Status)) {\r
       if (Snp->Mode->MediaPresentSupported) {\r
         if (Snp->Mode->State == EfiSimpleNetworkInitialized) {\r
+          //\r
+          // Invoke Snp->GetStatus() to refresh the media status\r
+          //\r
+          Snp->GetStatus (Snp, &InterruptStatus, NULL);\r
+\r
           //\r
           // In case some one else is using the SNP check to see if it's connected\r
           //\r
@@ -1727,6 +1747,8 @@ BdsGetBootTypeFromDevicePath (
 \r
         case MSG_MAC_ADDR_DP:\r
         case MSG_VLAN_DP:\r
+        case MSG_IPv4_DP:\r
+        case MSG_IPv6_DP:\r
           BootType = BDS_EFI_MESSAGE_MAC_BOOT;\r
           break;\r
 \r
@@ -1794,29 +1816,20 @@ BdsLibIsValidEFIBootOptDevicePathExt (
   EFI_DEVICE_PATH_PROTOCOL  *TempDevicePath;\r
   EFI_DEVICE_PATH_PROTOCOL  *LastDeviceNode;\r
   EFI_BLOCK_IO_PROTOCOL     *BlockIo;\r
-  EFI_LOAD_FILE_PROTOCOL    *LoadFile;\r
 \r
   TempDevicePath = DevPath;\r
   LastDeviceNode = DevPath;\r
 \r
   //\r
-  // Check if it's a valid boot option for network boot device\r
-  // Check if there is MNP Service Binding Protocol or SimpleNetworkProtocol\r
-  // installed. If yes, that means there is the network card there.\r
+  // Check if it's a valid boot option for network boot device.\r
+  // Check if there is EfiLoadFileProtocol installed. \r
+  // If yes, that means there is a boot option for network.\r
   //\r
   Status = gBS->LocateDevicePath (\r
-                  &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                  &gEfiLoadFileProtocolGuid,\r
                   &TempDevicePath,\r
                   &Handle\r
                   );\r
-  if (EFI_ERROR (Status)) {\r
-    TempDevicePath = DevPath;\r
-    Status = gBS->LocateDevicePath (\r
-                    &gEfiSimpleNetworkProtocolGuid,\r
-                    &TempDevicePath,\r
-                    &Handle\r
-                    );\r
-  }\r
   if (EFI_ERROR (Status)) {\r
     //\r
     // Device not present so see if we need to connect it\r
@@ -1824,44 +1837,30 @@ BdsLibIsValidEFIBootOptDevicePathExt (
     TempDevicePath = DevPath;\r
     BdsLibConnectDevicePath (TempDevicePath);\r
     Status = gBS->LocateDevicePath (\r
-                    &gEfiManagedNetworkServiceBindingProtocolGuid,\r
+                    &gEfiLoadFileProtocolGuid,\r
                     &TempDevicePath,\r
                     &Handle\r
                     );\r
-    if (EFI_ERROR (Status)) {\r
-      TempDevicePath = DevPath;\r
-      Status = gBS->LocateDevicePath (\r
-                      &gEfiSimpleNetworkProtocolGuid,\r
-                      &TempDevicePath,\r
-                      &Handle\r
-                      );\r
-    }\r
   }\r
 \r
   if (!EFI_ERROR (Status)) {\r
-    //\r
-    // Check whether LoadFile protocol is installed\r
-    //\r
-    Status = gBS->HandleProtocol (Handle, &gEfiLoadFileProtocolGuid, (VOID **)&LoadFile);\r
-    if (!EFI_ERROR (Status)) {\r
-      if (!IsDevicePathEnd (TempDevicePath)) {\r
-        //\r
-        // LoadFile protocol is not installed on handle with exactly the same DevPath\r
-        //\r
-        return FALSE;\r
-      }\r
+    if (!IsDevicePathEnd (TempDevicePath)) {\r
+      //\r
+      // LoadFile protocol is not installed on handle with exactly the same DevPath\r
+      //\r
+      return FALSE;\r
+    }\r
 \r
-      if (CheckMedia) {\r
-        //\r
-        // Test if it is ready to boot now\r
-        //\r
-        if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
-          return TRUE;\r
-        }\r
-      } else {\r
+    if (CheckMedia) {\r
+      //\r
+      // Test if it is ready to boot now\r
+      //\r
+      if (BdsLibNetworkBootWithMediaPresent(DevPath)) {\r
         return TRUE;\r
       }\r
-    }\r
+    } else {\r
+      return TRUE;\r
+    }    \r
   }\r
 \r
   //\r