]> git.proxmox.com Git - mirror_edk2.git/blobdiff - NetworkPkg/IScsiDxe/IScsiProto.c
Fix a bug about iSCSI initiator(based on NetworkPkg-IPv4 network stack) cannot reinst...
[mirror_edk2.git] / NetworkPkg / IScsiDxe / IScsiProto.c
index acb7876ab54b6480a5bc9058d387719e3186eb71..29b3c24997ea7231c8ea06005ffebf0e0a534820 100644 (file)
@@ -1,7 +1,7 @@
 /** @file\r
   The implementation of iSCSI protocol based on RFC3720.\r
 \r
-Copyright (c) 2004 - 2012, Intel Corporation. All rights reserved.<BR>\r
+Copyright (c) 2004 - 2013, 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
@@ -228,7 +228,7 @@ IScsiCreateConnection (
   Conn->PartialRspRcvd  = FALSE;\r
   Conn->ParamNegotiated = FALSE;\r
   Conn->Cid             = Session->NextCid++;\r
-  Conn->Ipv6Flag        = mPrivate->Ipv6Flag;\r
+  Conn->Ipv6Flag        = NvData->IpMode == IP_MODE_IP6 || Session->ConfigData->AutoConfigureMode == IP_MODE_AUTOCONFIG_IP6;\r
 \r
   Status = gBS->CreateEvent (\r
                   EVT_TIMER,\r
@@ -259,15 +259,16 @@ IScsiCreateConnection (
     CopyMem (&Tcp4IoConfig->Gateway, &NvData->Gateway, sizeof (EFI_IPv4_ADDRESS));\r
     CopyMem (&Tcp4IoConfig->RemoteIp, &NvData->TargetIp, sizeof (EFI_IPv4_ADDRESS));\r
 \r
-    Tcp4IoConfig->RemotePort = NvData->TargetPort;\r
-    Tcp4IoConfig->ActiveFlag = TRUE;\r
-\r
+    Tcp4IoConfig->RemotePort  = NvData->TargetPort;\r
+    Tcp4IoConfig->ActiveFlag  = TRUE;\r
+    Tcp4IoConfig->StationPort = 0;\r
   } else {\r
     Tcp6IoConfig = &TcpIoConfig.Tcp6IoConfigData;\r
   \r
     CopyMem (&Tcp6IoConfig->RemoteIp, &NvData->TargetIp, sizeof (EFI_IPv6_ADDRESS));\r
-    Tcp6IoConfig->RemotePort = NvData->TargetPort;\r
-    Tcp6IoConfig->ActiveFlag = TRUE;\r
+    Tcp6IoConfig->RemotePort  = NvData->TargetPort;\r
+    Tcp6IoConfig->ActiveFlag  = TRUE;\r
+    Tcp6IoConfig->StationPort = 0;\r
   }\r
 \r
   //\r
@@ -308,6 +309,98 @@ IScsiDestroyConnection (
   FreePool (Conn);\r
 }\r
 \r
+/**\r
+  Retrieve the IPv6 Address/Prefix/Gateway from the established TCP connection, these informations\r
+  will be filled in the iSCSI Boot Firmware Table.\r
+\r
+  @param[in]  Conn             The connection used in the iSCSI login phase.\r
+\r
+  @retval     EFI_SUCCESS      Get the NIC information successfully.\r
+  @retval     Others           Other errors as indicated.\r
+  \r
+**/\r
+EFI_STATUS\r
+IScsiGetIp6NicInfo (\r
+  IN ISCSI_CONNECTION  *Conn\r
+  )\r
+{\r
+  ISCSI_SESSION_CONFIG_NVDATA  *NvData;\r
+  EFI_TCP6_PROTOCOL            *Tcp6;\r
+  EFI_IP6_MODE_DATA            Ip6ModeData;\r
+  EFI_STATUS                   Status;\r
+  EFI_IPv6_ADDRESS             *TargetIp;\r
+  UINTN                        Index;\r
+  UINT8                        SubnetPrefixLength;\r
+  UINTN                        RouteEntry;\r
+\r
+  NvData   = &Conn->Session->ConfigData->SessionConfigData;\r
+  TargetIp = &NvData->TargetIp.v6;\r
+  Tcp6     = Conn->TcpIo.Tcp.Tcp6;\r
+\r
+  ZeroMem (&Ip6ModeData, sizeof (EFI_IP6_MODE_DATA));\r
+  Status = Tcp6->GetModeData (\r
+                   Tcp6,\r
+                   NULL,\r
+                   NULL,\r
+                   &Ip6ModeData,\r
+                   NULL,\r
+                   NULL\r
+                   );\r
+  if (EFI_ERROR (Status)) {\r
+    return Status;\r
+  }\r
+\r
+  if (!Ip6ModeData.IsConfigured) {\r
+    Status = EFI_ABORTED;\r
+    goto ON_EXIT;\r
+  }\r
+\r
+  IP6_COPY_ADDRESS (&NvData->LocalIp, &Ip6ModeData.ConfigData.StationAddress);\r
+\r
+  NvData->PrefixLength = 0;\r
+  for (Index = 0; Index < Ip6ModeData.AddressCount; Index++) {\r
+    if (EFI_IP6_EQUAL (&NvData->LocalIp.v6, &Ip6ModeData.AddressList[Index].Address)) {\r
+      NvData->PrefixLength = Ip6ModeData.AddressList[Index].PrefixLength;\r
+      break;\r
+    }\r
+  }\r
+\r
+  SubnetPrefixLength = 0;\r
+  RouteEntry = Ip6ModeData.RouteCount;\r
+  for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) {\r
+    if (NetIp6IsNetEqual (TargetIp, &Ip6ModeData.RouteTable[Index].Destination, Ip6ModeData.RouteTable[Index].PrefixLength)) {\r
+      if (SubnetPrefixLength < Ip6ModeData.RouteTable[Index].PrefixLength) {\r
+        SubnetPrefixLength = Ip6ModeData.RouteTable[Index].PrefixLength;\r
+        RouteEntry = Index;\r
+      }\r
+    }\r
+  }\r
+  if (RouteEntry != Ip6ModeData.RouteCount) {\r
+    IP6_COPY_ADDRESS (&NvData->Gateway, &Ip6ModeData.RouteTable[RouteEntry].Gateway);\r
+  }\r
+\r
+ON_EXIT:\r
+  if (Ip6ModeData.AddressList != NULL) {\r
+    FreePool (Ip6ModeData.AddressList);\r
+  }\r
+  if (Ip6ModeData.GroupTable!= NULL) {\r
+    FreePool (Ip6ModeData.GroupTable);\r
+  }\r
+  if (Ip6ModeData.RouteTable!= NULL) {\r
+    FreePool (Ip6ModeData.RouteTable);\r
+  }\r
+  if (Ip6ModeData.NeighborCache!= NULL) {\r
+    FreePool (Ip6ModeData.NeighborCache);\r
+  }\r
+  if (Ip6ModeData.PrefixTable!= NULL) {\r
+    FreePool (Ip6ModeData.PrefixTable);\r
+  }\r
+  if (Ip6ModeData.IcmpTypeList!= NULL) {\r
+    FreePool (Ip6ModeData.IcmpTypeList);\r
+  }\r
+\r
+  return Status;\r
+}\r
 \r
 /**\r
   Login the iSCSI session.\r
@@ -379,7 +472,7 @@ IScsiSessionLogin (
   if (!EFI_ERROR (Status)) {\r
     Session->State = SESSION_STATE_LOGGED_IN;\r
 \r
-    if (!mPrivate->Ipv6Flag) {\r
+    if (!Conn->Ipv6Flag) {\r
       ProtocolGuid = &gEfiTcp4ProtocolGuid;      \r
     } else {\r
       ProtocolGuid = &gEfiTcp6ProtocolGuid;\r
@@ -395,6 +488,10 @@ IScsiSessionLogin (
                     );\r
 \r
     ASSERT_EFI_ERROR (Status);\r
+\r
+    if (Conn->Ipv6Flag) {\r
+      Status = IScsiGetIp6NicInfo (Conn);\r
+    }\r
   }\r
 \r
   return Status;\r
@@ -1291,7 +1388,7 @@ ON_EXIT:
 \r
 \r
 /**\r
-  Check and get the result of the prameter negotiation.\r
+  Check and get the result of the parameter negotiation.\r
 \r
   @param[in, out]  Conn          The connection in iSCSI login.\r
 \r
@@ -1539,6 +1636,12 @@ IScsiCheckOpParams (
   IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_PDU_IN_ORDER);\r
   IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_DATA_SEQUENCE_IN_ORDER);\r
 \r
+  //\r
+  // Remove irrelevant parameter, if any.\r
+  //\r
+  if (Session->InitialR2T && !Session->ImmediateData) {\r
+    IScsiGetValueByKeyFromList (KeyValueList, ISCSI_KEY_FIRST_BURST_LENGTH);\r
+  }\r
 \r
   if (IsListEmpty (KeyValueList)) {\r
     //\r
@@ -1558,7 +1661,7 @@ ON_ERROR:
 \r
 \r
 /**\r
-  Fill the oprational parameters.\r
+  Fill the operational parameters.\r
 \r
   @param[in]       Conn    The connection in iSCSI login.\r
   @param[in, out]  Pdu     The iSCSI login request PDU to fill the parameters.\r
@@ -2749,7 +2852,8 @@ IScsiExecuteScsiCommand (
   Timeout       = 0;\r
 \r
   if (Session->State != SESSION_STATE_LOGGED_IN) {\r
-    return EFI_DEVICE_ERROR;\r
+    Status = EFI_DEVICE_ERROR;\r
+    goto ON_EXIT;\r
   }\r
 \r
   Conn = NET_LIST_USER_STRUCT_S (\r
@@ -2923,7 +3027,7 @@ IScsiSessionReinstatement (
 {\r
   EFI_STATUS    Status;\r
 \r
-  ASSERT (Session->State == SESSION_STATE_LOGGED_IN);\r
+  ASSERT (Session->State != SESSION_STATE_FREE);\r
 \r
   //\r
   // Abort the session and re-init it.\r