]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/IScsiDxe/IScsiDhcp6.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiDhcp6.c
index 2bf102ba8b88705f5c274976f066b754e788a447..8ca92b20d1ab526ab6f8c61a2f2734a0c2b6bf63 100644 (file)
@@ -1,20 +1,13 @@
 /** @file\r
   iSCSI DHCP6 related configuration routines.\r
 \r
-Copyright (c) 2009 - 2011, Intel Corporation. All rights reserved.<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
-http://opensource.org/licenses/bsd-license.php\r
-\r
-THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
-WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
+Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>\r
+SPDX-License-Identifier: BSD-2-Clause-Patent\r
 \r
 **/\r
 \r
 #include "IScsiImpl.h"\r
 \r
-\r
 /**\r
   Extract the Root Path option and get the required target information from\r
   Boot File Uniform Resource Locator (URL) Option.\r
@@ -35,78 +28,93 @@ EFI_STATUS
 IScsiDhcp6ExtractRootPath (\r
   IN     CHAR8                        *RootPath,\r
   IN     UINT16                       Length,\r
-  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData\r
+  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA  *ConfigData\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINT16                      IScsiRootPathIdLen;\r
-  CHAR8                       *TmpStr;\r
-  ISCSI_ROOT_PATH_FIELD       Fields[RP_FIELD_IDX_MAX];\r
-  ISCSI_ROOT_PATH_FIELD       *Field;\r
-  UINT32                      FieldIndex;\r
-  UINT8                       Index;\r
-  ISCSI_SESSION_CONFIG_NVDATA *ConfigNvData;\r
-  EFI_IP_ADDRESS              Ip;\r
-  UINT8                       IpMode;  \r
-\r
-  ConfigNvData = &ConfigData->SessionConfigData;\r
-\r
+  EFI_STATUS                   Status;\r
+  UINT16                       IScsiRootPathIdLen;\r
+  CHAR8                        *TmpStr;\r
+  ISCSI_ROOT_PATH_FIELD        Fields[RP_FIELD_IDX_MAX];\r
+  ISCSI_ROOT_PATH_FIELD        *Field;\r
+  UINT32                       FieldIndex;\r
+  UINT8                        Index;\r
+  ISCSI_SESSION_CONFIG_NVDATA  *ConfigNvData;\r
+  EFI_IP_ADDRESS               Ip;\r
+  UINT8                        IpMode;\r
+\r
+  ConfigNvData          = &ConfigData->SessionConfigData;\r
+  ConfigNvData->DnsMode = FALSE;\r
   //\r
   // "iscsi:"<servername>":"<protocol>":"<port>":"<LUN>":"<targetname>\r
   //\r
-  IScsiRootPathIdLen = (UINT16) AsciiStrLen (ISCSI_ROOT_PATH_ID);\r
+  IScsiRootPathIdLen = (UINT16)AsciiStrLen (ISCSI_ROOT_PATH_ID);\r
 \r
   if ((Length <= IScsiRootPathIdLen) ||\r
-      (CompareMem (RootPath, ISCSI_ROOT_PATH_ID, IScsiRootPathIdLen) != 0)) {\r
+      (CompareMem (RootPath, ISCSI_ROOT_PATH_ID, IScsiRootPathIdLen) != 0))\r
+  {\r
     return EFI_NOT_FOUND;\r
   }\r
+\r
   //\r
   // Skip the iSCSI RootPath ID "iscsi:".\r
   //\r
   RootPath = RootPath + IScsiRootPathIdLen;\r
-  Length   = (UINT16) (Length - IScsiRootPathIdLen);\r
+  Length   = (UINT16)(Length - IScsiRootPathIdLen);\r
 \r
-  TmpStr   = (CHAR8 *) AllocatePool (Length + 1);\r
+  TmpStr = (CHAR8 *)AllocatePool (Length + 1);\r
   if (TmpStr == NULL) {\r
     return EFI_OUT_OF_RESOURCES;\r
   }\r
 \r
   CopyMem (TmpStr, RootPath, Length);\r
-  TmpStr[Length]  = '\0';\r
+  TmpStr[Length] = '\0';\r
 \r
-  Index           = 0;\r
-  FieldIndex      = 0;\r
+  Index      = 0;\r
+  FieldIndex = 0;\r
   ZeroMem (&Fields[0], sizeof (Fields));\r
 \r
   //\r
   // Extract SERVERNAME field in the Root Path option.\r
   //\r
   if (TmpStr[Index] != ISCSI_ROOT_PATH_ADDR_START_DELIMITER) {\r
-    Status = EFI_INVALID_PARAMETER;\r
-    goto ON_EXIT;\r
+    //\r
+    // The servername is expressed as domain name.\r
+    //\r
+    ConfigNvData->DnsMode = TRUE;\r
   } else {\r
     Index++;\r
   }\r
 \r
   Fields[RP_FIELD_IDX_SERVERNAME].Str = &TmpStr[Index];\r
 \r
-  while ((TmpStr[Index] != ISCSI_ROOT_PATH_ADDR_END_DELIMITER) && (Index < Length)) {\r
-    Index++;\r
-  }\r
+  if (!ConfigNvData->DnsMode) {\r
+    while ((TmpStr[Index] != ISCSI_ROOT_PATH_ADDR_END_DELIMITER) && (Index < Length)) {\r
+      Index++;\r
+    }\r
 \r
-  //\r
-  // Skip ']' and ':'.\r
-  //\r
-  TmpStr[Index] = '\0';\r
-  Index += 2;\r
+    //\r
+    // Skip ']' and ':'.\r
+    //\r
+    TmpStr[Index] = '\0';\r
+    Index        += 2;\r
+  } else {\r
+    while ((TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) && (Index < Length)) {\r
+      Index++;\r
+    }\r
+\r
+    //\r
+    // Skip ':'.\r
+    //\r
+    TmpStr[Index] = '\0';\r
+    Index        += 1;\r
+  }\r
 \r
-  Fields[RP_FIELD_IDX_SERVERNAME].Len = (UINT8) AsciiStrLen (Fields[RP_FIELD_IDX_SERVERNAME].Str);\r
+  Fields[RP_FIELD_IDX_SERVERNAME].Len = (UINT8)AsciiStrLen (Fields[RP_FIELD_IDX_SERVERNAME].Str);\r
 \r
   //\r
   // Extract others fields in the Root Path option string.\r
   //\r
   for (FieldIndex = 1; (FieldIndex < RP_FIELD_IDX_MAX) && (Index < Length); FieldIndex++) {\r
-\r
     if (TmpStr[Index] != ISCSI_ROOT_PATH_FIELD_DELIMITER) {\r
       Fields[FieldIndex].Str = &TmpStr[Index];\r
     }\r
@@ -122,7 +130,7 @@ IScsiDhcp6ExtractRootPath (
       }\r
 \r
       if (Fields[FieldIndex].Str != NULL) {\r
-        Fields[FieldIndex].Len = (UINT8) AsciiStrLen (Fields[FieldIndex].Str);\r
+        Fields[FieldIndex].Len = (UINT8)AsciiStrLen (Fields[FieldIndex].Str);\r
       }\r
     }\r
   }\r
@@ -135,28 +143,42 @@ IScsiDhcp6ExtractRootPath (
   if ((Fields[RP_FIELD_IDX_SERVERNAME].Str == NULL) ||\r
       (Fields[RP_FIELD_IDX_TARGETNAME].Str == NULL) ||\r
       (Fields[RP_FIELD_IDX_PROTOCOL].Len > 1)\r
-      ) {\r
-\r
+      )\r
+  {\r
     Status = EFI_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
+\r
   //\r
   // Get the IP address of the target.\r
   //\r
-  Field   = &Fields[RP_FIELD_IDX_SERVERNAME];  \r
+  Field = &Fields[RP_FIELD_IDX_SERVERNAME];\r
   if (ConfigNvData->IpMode < IP_MODE_AUTOCONFIG) {\r
     IpMode = ConfigNvData->IpMode;\r
   } else {\r
     IpMode = ConfigData->AutoConfigureMode;\r
   }\r
 \r
-  Status = IScsiAsciiStrToIp (Field->Str, IpMode, &Ip);\r
-  CopyMem (&ConfigNvData->TargetIp, &Ip, sizeof (EFI_IP_ADDRESS));\r
+  //\r
+  // Server name is expressed as domain name, just save it.\r
+  //\r
+  if (ConfigNvData->DnsMode) {\r
+    if ((Field->Len + 2) > sizeof (ConfigNvData->TargetUrl)) {\r
+      return EFI_INVALID_PARAMETER;\r
+    }\r
 \r
+    CopyMem (&ConfigNvData->TargetUrl, Field->Str, Field->Len);\r
+    ConfigNvData->TargetUrl[Field->Len + 1] = '\0';\r
+  } else {\r
+    ZeroMem (&ConfigNvData->TargetUrl, sizeof (ConfigNvData->TargetUrl));\r
+    Status = IScsiAsciiStrToIp (Field->Str, IpMode, &Ip);\r
+    CopyMem (&ConfigNvData->TargetIp, &Ip, sizeof (EFI_IP_ADDRESS));\r
 \r
-  if (EFI_ERROR (Status)) {\r
-    goto ON_EXIT;\r
+    if (EFI_ERROR (Status)) {\r
+      goto ON_EXIT;\r
+    }\r
   }\r
+\r
   //\r
   // Check the protocol type.\r
   //\r
@@ -165,15 +187,17 @@ IScsiDhcp6ExtractRootPath (
     Status = EFI_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
+\r
   //\r
   // Get the port of the iSCSI target.\r
   //\r
   Field = &Fields[RP_FIELD_IDX_PORT];\r
   if (Field->Str != NULL) {\r
-    ConfigNvData->TargetPort = (UINT16) AsciiStrDecimalToUintn (Field->Str);\r
+    ConfigNvData->TargetPort = (UINT16)AsciiStrDecimalToUintn (Field->Str);\r
   } else {\r
     ConfigNvData->TargetPort = ISCSI_WELL_KNOWN_PORT;\r
   }\r
+\r
   //\r
   // Get the LUN.\r
   //\r
@@ -186,6 +210,7 @@ IScsiDhcp6ExtractRootPath (
   } else {\r
     ZeroMem (ConfigNvData->BootLun, sizeof (ConfigNvData->BootLun));\r
   }\r
+\r
   //\r
   // Get the target iSCSI Name.\r
   //\r
@@ -195,6 +220,7 @@ IScsiDhcp6ExtractRootPath (
     Status = EFI_INVALID_PARAMETER;\r
     goto ON_EXIT;\r
   }\r
+\r
   //\r
   // Validate the iSCSI name.\r
   //\r
@@ -203,7 +229,7 @@ IScsiDhcp6ExtractRootPath (
     goto ON_EXIT;\r
   }\r
 \r
-  AsciiStrCpy (ConfigNvData->TargetName, Field->Str);\r
+  AsciiStrCpyS (ConfigNvData->TargetName, ISCSI_NAME_MAX_SIZE, Field->Str);\r
 \r
 ON_EXIT:\r
 \r
@@ -213,11 +239,11 @@ ON_EXIT:
 }\r
 \r
 /**\r
-  EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol \r
+  EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol\r
   instance to intercept events that occurs in the DHCPv6 Information Request\r
   exchange process.\r
 \r
-  @param[in]  This              Pointer to the EFI_DHCP6_PROTOCOL instance that \r
+  @param[in]  This              Pointer to the EFI_DHCP6_PROTOCOL instance that\r
                                 is used to configure this  callback function.\r
   @param[in]  Context           Pointer to the context that is initialized in\r
                                 the EFI_DHCP6_PROTOCOL.InfoRequest().\r
@@ -239,22 +265,23 @@ ON_EXIT:
 EFI_STATUS\r
 EFIAPI\r
 IScsiDhcp6ParseReply (\r
-  IN EFI_DHCP6_PROTOCOL          *This,\r
-  IN VOID                        *Context,\r
-  IN EFI_DHCP6_PACKET            *Packet\r
+  IN EFI_DHCP6_PROTOCOL  *This,\r
+  IN VOID                *Context,\r
+  IN EFI_DHCP6_PACKET    *Packet\r
   )\r
 {\r
-  EFI_STATUS                  Status;\r
-  UINT32                      Index;\r
-  UINT32                      OptionCount;\r
-  EFI_DHCP6_PACKET_OPTION     *BootFileOpt;\r
-  EFI_DHCP6_PACKET_OPTION     **OptionList;\r
-  ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData;\r
\r
+  EFI_STATUS                   Status;\r
+  UINT32                       Index;\r
+  UINT32                       OptionCount;\r
+  EFI_DHCP6_PACKET_OPTION      *BootFileOpt;\r
+  EFI_DHCP6_PACKET_OPTION      **OptionList;\r
+  ISCSI_ATTEMPT_CONFIG_NVDATA  *ConfigData;\r
+  UINT16                       ParaLen;\r
+\r
   OptionCount = 0;\r
   BootFileOpt = NULL;\r
-  \r
-  Status      = This->Parse (This, Packet, &OptionCount, NULL);\r
+\r
+  Status = This->Parse (This, Packet, &OptionCount, NULL);\r
   if (Status != EFI_BUFFER_TOO_SMALL) {\r
     return EFI_NOT_READY;\r
   }\r
@@ -270,7 +297,7 @@ IScsiDhcp6ParseReply (
     goto Exit;\r
   }\r
 \r
-  ConfigData = (ISCSI_ATTEMPT_CONFIG_NVDATA *) Context;\r
+  ConfigData = (ISCSI_ATTEMPT_CONFIG_NVDATA *)Context;\r
 \r
   for (Index = 0; Index < OptionCount; Index++) {\r
     OptionList[Index]->OpCode = NTOHS (OptionList[Index]->OpCode);\r
@@ -280,11 +307,11 @@ IScsiDhcp6ParseReply (
     // Get DNS server addresses from this reply packet.\r
     //\r
     if (OptionList[Index]->OpCode == DHCP6_OPT_DNS_SERVERS) {\r
-\r
       if (((OptionList[Index]->OpLen & 0xf) != 0) || (OptionList[Index]->OpLen == 0)) {\r
-        Status = EFI_INVALID_PARAMETER;\r
+        Status = EFI_UNSUPPORTED;\r
         goto Exit;\r
       }\r
+\r
       //\r
       // Primary DNS server address.\r
       //\r
@@ -296,12 +323,30 @@ IScsiDhcp6ParseReply (
         //\r
         CopyMem (&ConfigData->SecondaryDns, &OptionList[Index]->Data[16], sizeof (EFI_IPv6_ADDRESS));\r
       }\r
-\r
     } else if (OptionList[Index]->OpCode == DHCP6_OPT_BOOT_FILE_URL) {\r
       //\r
       // The server sends this option to inform the client about an URL to a boot file.\r
       //\r
       BootFileOpt = OptionList[Index];\r
+    } else if (OptionList[Index]->OpCode == DHCP6_OPT_BOOT_FILE_PARAM) {\r
+      //\r
+      // The server sends this option to inform the client about DHCP6 server address.\r
+      //\r
+      if (OptionList[Index]->OpLen < 18) {\r
+        Status = EFI_UNSUPPORTED;\r
+        goto Exit;\r
+      }\r
+\r
+      //\r
+      // Check param-len 1, should be 16 bytes.\r
+      //\r
+      CopyMem (&ParaLen, &OptionList[Index]->Data[0], sizeof (UINT16));\r
+      if (NTOHS (ParaLen) != 16) {\r
+        Status = EFI_UNSUPPORTED;\r
+        goto Exit;\r
+      }\r
+\r
+      CopyMem (&ConfigData->DhcpServer, &OptionList[Index]->Data[2], sizeof (EFI_IPv6_ADDRESS));\r
     }\r
   }\r
 \r
@@ -309,12 +354,12 @@ IScsiDhcp6ParseReply (
     Status = EFI_UNSUPPORTED;\r
     goto Exit;\r
   }\r
-  \r
+\r
   //\r
   // Get iSCSI root path from Boot File Uniform Resource Locator (URL) Option\r
   //\r
   Status = IScsiDhcp6ExtractRootPath (\r
-             (CHAR8 *) BootFileOpt->Data,\r
+             (CHAR8 *)BootFileOpt->Data,\r
              BootFileOpt->OpLen,\r
              ConfigData\r
              );\r
@@ -325,7 +370,6 @@ Exit:
   return Status;\r
 }\r
 \r
-\r
 /**\r
   Parse the DHCP ACK to get the address configuration and DNS information.\r
 \r
@@ -345,9 +389,9 @@ Exit:
 **/\r
 EFI_STATUS\r
 IScsiDoDhcp6 (\r
-  IN     EFI_HANDLE                  Image,\r
-  IN     EFI_HANDLE                  Controller,\r
-  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData\r
+  IN     EFI_HANDLE                   Image,\r
+  IN     EFI_HANDLE                   Controller,\r
+  IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA  *ConfigData\r
   )\r
 {\r
   EFI_HANDLE                Dhcp6Handle;\r
@@ -357,14 +401,15 @@ IScsiDoDhcp6 (
   EFI_DHCP6_PACKET_OPTION   *Oro;\r
   EFI_DHCP6_RETRANSMISSION  InfoReqReXmit;\r
   EFI_EVENT                 Timer;\r
-  BOOLEAN                   MediaPresent;\r
+  EFI_STATUS                MediaStatus;\r
 \r
   //\r
   // Check media status before doing DHCP.\r
   //\r
-  MediaPresent = TRUE;\r
-  NetLibDetectMedia (Controller, &MediaPresent);\r
-  if (!MediaPresent) {\r
+  MediaStatus = EFI_SUCCESS;\r
+  NetLibDetectMediaWaitTimeout (Controller, ISCSI_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus);\r
+  if (MediaStatus != EFI_SUCCESS) {\r
+    AsciiPrint ("\n  Error: Could not detect network connection.\n");\r
     return EFI_NO_MEDIA;\r
   }\r
 \r
@@ -396,7 +441,7 @@ IScsiDoDhcp6 (
   Status = gBS->OpenProtocol (\r
                   Dhcp6Handle,\r
                   &gEfiDhcp6ProtocolGuid,\r
-                  (VOID **) &Dhcp6,\r
+                  (VOID **)&Dhcp6,\r
                   Image,\r
                   Controller,\r
                   EFI_OPEN_PROTOCOL_BY_DRIVER\r
@@ -405,7 +450,7 @@ IScsiDoDhcp6 (
     goto ON_EXIT;\r
   }\r
 \r
-  Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 3);\r
+  Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 5);\r
   if (Oro == NULL) {\r
     Status = EFI_OUT_OF_RESOURCES;\r
     goto ON_EXIT;\r
@@ -415,10 +460,11 @@ IScsiDoDhcp6 (
   // Ask the server to reply with DNS and Boot File URL options by info request.\r
   // All members in EFI_DHCP6_PACKET_OPTION are in network order.\r
   //\r
-  Oro->OpCode  = HTONS (DHCP6_OPT_REQUEST_OPTION);\r
-  Oro->OpLen   = HTONS (2 * 2);\r
+  Oro->OpCode  = HTONS (DHCP6_OPT_ORO);\r
+  Oro->OpLen   = HTONS (2 * 3);\r
   Oro->Data[1] = DHCP6_OPT_DNS_SERVERS;\r
   Oro->Data[3] = DHCP6_OPT_BOOT_FILE_URL;\r
+  Oro->Data[5] = DHCP6_OPT_BOOT_FILE_PARAM;\r
 \r
   InfoReqReXmit.Irt = 4;\r
   InfoReqReXmit.Mrc = 1;\r
@@ -453,7 +499,6 @@ IScsiDoDhcp6 (
     }\r
 \r
     do {\r
-\r
       TimerStatus = gBS->CheckEvent (Timer);\r
 \r
       if (!EFI_ERROR (TimerStatus)) {\r
@@ -469,16 +514,14 @@ IScsiDoDhcp6 (
                           ConfigData\r
                           );\r
       }\r
-\r
     } while (TimerStatus == EFI_NOT_READY);\r
-\r
   }\r
 \r
 ON_EXIT:\r
 \r
   if (Oro != NULL) {\r
     FreePool (Oro);\r
-  }  \r
+  }\r
 \r
   if (Timer != NULL) {\r
     gBS->CloseEvent (Timer);\r
@@ -502,4 +545,3 @@ ON_EXIT:
 \r
   return Status;\r
 }\r
-\r