diff --git a/NetworkPkg/IScsiDxe/IScsiConfig.c b/NetworkPkg/IScsiDxe/IScsiConfig.c index f20f590464..3ce37c59e0 100644 --- a/NetworkPkg/IScsiDxe/IScsiConfig.c +++ b/NetworkPkg/IScsiDxe/IScsiConfig.c @@ -3421,6 +3421,9 @@ IScsiFormCallback ( ISCSI_CONFIG_IFR_NVDATA OldIfrNvData; EFI_STATUS Status; EFI_INPUT_KEY Key; + ISCSI_NIC_INFO *NicInfo; + + NicInfo = NULL; if ((Action == EFI_BROWSER_ACTION_FORM_OPEN) || (Action == EFI_BROWSER_ACTION_FORM_CLOSE)) { // @@ -3591,6 +3594,21 @@ IScsiFormCallback ( case KEY_IP_MODE: switch (Value->u8) { case IP_MODE_IP6: + NicInfo = IScsiGetNicInfoByIndex (Private->Current->NicIndex); + if(!NicInfo->Ipv6Available) { + // + // Current NIC doesn't Support IPv6, hence use IPv4. + // + IfrNvData->IpMode = IP_MODE_IP4; + + CreatePopUp ( + EFI_LIGHTGRAY | EFI_BACKGROUND_BLUE, + &Key, + L"Current NIC doesn't Support IPv6!", + NULL + ); + } + case IP_MODE_IP4: ZeroMem (IfrNvData->LocalIp, sizeof (IfrNvData->LocalIp)); ZeroMem (IfrNvData->SubnetMask, sizeof (IfrNvData->SubnetMask)); diff --git a/NetworkPkg/IScsiDxe/IScsiDriver.c b/NetworkPkg/IScsiDxe/IScsiDriver.c index 2249919e18..fbeef970ba 100644 --- a/NetworkPkg/IScsiDxe/IScsiDriver.c +++ b/NetworkPkg/IScsiDxe/IScsiDriver.c @@ -440,7 +440,7 @@ IScsiStart ( // // Record the incoming NIC info. // - Status = IScsiAddNic (ControllerHandle); + Status = IScsiAddNic (ControllerHandle, Image); if (EFI_ERROR (Status)) { return Status; } diff --git a/NetworkPkg/IScsiDxe/IScsiDriver.h b/NetworkPkg/IScsiDxe/IScsiDriver.h index 6c6e11b0d2..2db93c5d01 100644 --- a/NetworkPkg/IScsiDxe/IScsiDriver.h +++ b/NetworkPkg/IScsiDxe/IScsiDriver.h @@ -81,6 +81,7 @@ typedef struct { UINTN BusNumber; UINTN DeviceNumber; UINTN FunctionNumber; + BOOLEAN Ipv6Available; } ISCSI_NIC_INFO; typedef struct _ISCSI_PRIVATE_PROTOCOL { diff --git a/NetworkPkg/IScsiDxe/IScsiDxe.inf b/NetworkPkg/IScsiDxe/IScsiDxe.inf index 01998a0d28..319c7fe79a 100644 --- a/NetworkPkg/IScsiDxe/IScsiDxe.inf +++ b/NetworkPkg/IScsiDxe/IScsiDxe.inf @@ -117,6 +117,7 @@ gEfiAuthenticationInfoProtocolGuid ## SOMETIMES_CONSUMES gEfiAdapterInformationProtocolGuid + gEfiNetworkInterfaceIdentifierProtocolGuid_31 ## SOMETIMES_CONSUMES [Guids] gEfiEventExitBootServicesGuid ## SOMETIMES_CONSUMES ## Event @@ -125,6 +126,7 @@ gEfiAcpi10TableGuid ## SOMETIMES_CONSUMES ## SystemTable gEfiAcpi20TableGuid ## SOMETIMES_CONSUMES ## SystemTable gEfiAdapterInfoNetworkBootGuid ## SOMETIMES_CONSUMES ## UNDEFINED + gEfiAdapterInfoUndiIpv6SupportGuid ## SOMETIMES_CONSUMES ## GUID ## SOMETIMES_PRODUCES ## Variable:L"AttemptOrder" ## SOMETIMES_CONSUMES ## Variable:L"AttemptOrder" diff --git a/NetworkPkg/IScsiDxe/IScsiImpl.h b/NetworkPkg/IScsiDxe/IScsiImpl.h index 741c49784a..9e36da0203 100644 --- a/NetworkPkg/IScsiDxe/IScsiImpl.h +++ b/NetworkPkg/IScsiDxe/IScsiImpl.h @@ -39,6 +39,7 @@ WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. #include #include #include +#include #include #include diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.c b/NetworkPkg/IScsiDxe/IScsiMisc.c index 0a0a3f53e1..9e4164c986 100644 --- a/NetworkPkg/IScsiDxe/IScsiMisc.c +++ b/NetworkPkg/IScsiDxe/IScsiMisc.c @@ -465,10 +465,115 @@ IScsiGenRandom ( } +/** + Check whether UNDI protocol supports IPv6. + + @param[in] ControllerHandle Controller handle. + @param[in] Image Handle of the image. + @param[out] Ipv6Support TRUE if UNDI supports IPv6. + + @retval EFI_SUCCESS Get the result whether UNDI supports IPv6 by NII or AIP protocol successfully. + @retval EFI_NOT_FOUND Don't know whether UNDI supports IPv6 since NII or AIP is not available. + +**/ +EFI_STATUS +IScsiCheckIpv6Support ( + IN EFI_HANDLE ControllerHandle, + IN EFI_HANDLE Image, + OUT BOOLEAN *Ipv6Support + ) +{ + EFI_HANDLE Handle; + EFI_ADAPTER_INFORMATION_PROTOCOL *Aip; + EFI_STATUS Status; + EFI_GUID *InfoTypesBuffer; + UINTN InfoTypeBufferCount; + UINTN TypeIndex; + BOOLEAN Supported; + VOID *InfoBlock; + UINTN InfoBlockSize; + + EFI_NETWORK_INTERFACE_IDENTIFIER_PROTOCOL *Nii; + + ASSERT (Ipv6Support != NULL); + + // + // Check whether the UNDI supports IPv6 by NII protocol. + // + Status = gBS->OpenProtocol ( + ControllerHandle, + &gEfiNetworkInterfaceIdentifierProtocolGuid_31, + (VOID **) &Nii, + Image, + ControllerHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (Status == EFI_SUCCESS) { + *Ipv6Support = Nii->Ipv6Supported; + return EFI_SUCCESS; + } + + // + // Get the NIC handle by SNP protocol. + // + Handle = NetLibGetSnpHandle (ControllerHandle, NULL); + if (Handle == NULL) { + return EFI_NOT_FOUND; + } + + Aip = NULL; + Status = gBS->HandleProtocol ( + Handle, + &gEfiAdapterInformationProtocolGuid, + (VOID *) &Aip + ); + if (EFI_ERROR (Status) || Aip == NULL) { + return EFI_NOT_FOUND; + } + + InfoTypesBuffer = NULL; + InfoTypeBufferCount = 0; + Status = Aip->GetSupportedTypes (Aip, &InfoTypesBuffer, &InfoTypeBufferCount); + if (EFI_ERROR (Status) || InfoTypesBuffer == NULL) { + FreePool (InfoTypesBuffer); + return EFI_NOT_FOUND; + } + + Supported = FALSE; + for (TypeIndex = 0; TypeIndex < InfoTypeBufferCount; TypeIndex++) { + if (CompareGuid (&InfoTypesBuffer[TypeIndex], &gEfiAdapterInfoUndiIpv6SupportGuid)) { + Supported = TRUE; + break; + } + } + + FreePool (InfoTypesBuffer); + if (!Supported) { + return EFI_NOT_FOUND; + } + + // + // We now have adapter information block. + // + InfoBlock = NULL; + InfoBlockSize = 0; + Status = Aip->GetInformation (Aip, &gEfiAdapterInfoUndiIpv6SupportGuid, &InfoBlock, &InfoBlockSize); + if (EFI_ERROR (Status) || InfoBlock == NULL) { + FreePool (InfoBlock); + return EFI_NOT_FOUND; + } + + *Ipv6Support = ((EFI_ADAPTER_INFO_UNDI_IPV6_SUPPORT *) InfoBlock)->Ipv6Support; + FreePool (InfoBlock); + + return EFI_SUCCESS; +} + /** Record the NIC info in global structure. @param[in] Controller The handle of the controller. + @param[in] Image Handle of the image. @retval EFI_SUCCESS The operation is completed. @retval EFI_OUT_OF_RESOURCES Do not have sufficient resources to finish this @@ -477,7 +582,8 @@ IScsiGenRandom ( **/ EFI_STATUS IScsiAddNic ( - IN EFI_HANDLE Controller + IN EFI_HANDLE Controller, + IN EFI_HANDLE Image ) { EFI_STATUS Status; @@ -509,6 +615,19 @@ IScsiAddNic ( CompareMem (&NicInfo->PermanentAddress, MacAddr.Addr, HwAddressSize) == 0 && NicInfo->VlanId == VlanId) { mPrivate->CurrentNic = NicInfo->NicIndex; + + // + // Set IPv6 available flag. + // + Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available); + if (EFI_ERROR (Status)) { + // + // Fail to get the data whether UNDI supports IPv6. + // Set default value to TRUE. + // + NicInfo->Ipv6Available = TRUE; + } + return EFI_SUCCESS; } @@ -530,7 +649,19 @@ IScsiAddNic ( NicInfo->VlanId = VlanId; NicInfo->NicIndex = (UINT8) (mPrivate->MaxNic + 1); mPrivate->MaxNic = NicInfo->NicIndex; - + + // + // Set IPv6 available flag. + // + Status = IScsiCheckIpv6Support (Controller, Image, &NicInfo->Ipv6Available); + if (EFI_ERROR (Status)) { + // + // Fail to get the data whether UNDI supports IPv6. + // Set default value to TRUE. + // + NicInfo->Ipv6Available = TRUE; + } + // // Get the PCI location. // diff --git a/NetworkPkg/IScsiDxe/IScsiMisc.h b/NetworkPkg/IScsiDxe/IScsiMisc.h index caa2f94bb1..659c0268b5 100644 --- a/NetworkPkg/IScsiDxe/IScsiMisc.h +++ b/NetworkPkg/IScsiDxe/IScsiMisc.h @@ -217,6 +217,7 @@ IScsiGenRandom ( Record the NIC information in a global structure. @param[in] Controller The handle of the controller. + @param[in] Image Handle of the image. @retval EFI_SUCCESS The operation is completed. @retval EFI_OUT_OF_RESOURCES Do not have sufficient resource to finish this @@ -225,7 +226,8 @@ IScsiGenRandom ( **/ EFI_STATUS IScsiAddNic ( - IN EFI_HANDLE Controller + IN EFI_HANDLE Controller, + IN EFI_HANDLE Image ); /**