From 216f79703b8cb8dc65abdd768bedb2bcdbc1a1f8 Mon Sep 17 00:00:00 2001 From: sfu5 Date: Thu, 13 Dec 2012 06:47:06 +0000 Subject: 1. Add EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName() support. 2. Fix the driver binding Stop() hang issue in the network stack. 3. Add Ip4 raw data support. 4. Add iSCSI Dhcp option 60 support. Signed-off-by: Fu Siyuan Reviewed-by: Ye Ting Reviewed-by: Ouyang Qian git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@13995 6f19259b-4bc3-4df7-8a09-765794883524 --- MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c | 208 ++++++++++++++++++------ 1 file changed, 156 insertions(+), 52 deletions(-) (limited to 'MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c') diff --git a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c index f4ce3ea025..74bf7f76eb 100644 --- a/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c +++ b/MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Impl.c @@ -868,6 +868,7 @@ Ip4ConfigProtocol ( EFI_STATUS Status; IP4_ADDR Ip; IP4_ADDR Netmask; + EFI_ARP_PROTOCOL *Arp; IpSb = IpInstance->Service; @@ -972,6 +973,20 @@ Ip4ConfigProtocol ( } IpInstance->Interface = IpIf; + if (IpIf->Arp != NULL) { + Arp = NULL; + Status = gBS->OpenProtocol ( + IpIf->ArpHandle, + &gEfiArpProtocolGuid, + (VOID **) &Arp, + gIp4DriverBinding.DriverBindingHandle, + IpInstance->Handle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + goto ON_ERROR; + } + } InsertTailList (&IpIf->IpInstances, &IpInstance->AddrLink); CopyMem (&IpInstance->ConfigData, Config, sizeof (IpInstance->ConfigData)); @@ -1028,6 +1043,14 @@ Ip4CleanProtocol ( if (IpInstance->Interface != NULL) { RemoveEntryList (&IpInstance->AddrLink); + if (IpInstance->Interface->Arp != NULL) { + gBS->CloseProtocol ( + IpInstance->Interface->ArpHandle, + &gEfiArpProtocolGuid, + gIp4DriverBinding.DriverBindingHandle, + IpInstance->Handle + ); + } Ip4FreeInterface (IpInstance->Interface, IpInstance); IpInstance->Interface = NULL; } @@ -1193,14 +1216,6 @@ EfiIp4Configure ( // Validate the configuration first. // if (IpConfigData != NULL) { - // - // This implementation doesn't support RawData - // - if (IpConfigData->RawData) { - Status = EFI_UNSUPPORTED; - goto ON_EXIT; - } - CopyMem (&IpAddress, &IpConfigData->StationAddress, sizeof (IP4_ADDR)); CopyMem (&SubnetMask, &IpConfigData->SubnetMask, sizeof (IP4_ADDR)); @@ -1620,22 +1635,23 @@ Ip4TokenExist ( return EFI_SUCCESS; } - /** Validate the user's token against current station address. - @param[in] Token User's token to validate - @param[in] IpIf The IP4 child's interface. + @param[in] Token User's token to validate. + @param[in] IpIf The IP4 child's interface. + @param[in] RawData Set to TRUE to send unformatted packets. - @retval EFI_INVALID_PARAMETER Some parameters are invalid + @retval EFI_INVALID_PARAMETER Some parameters are invalid. @retval EFI_BAD_BUFFER_SIZE The user's option/data is too long. - @retval EFI_SUCCESS The token is OK + @retval EFI_SUCCESS The token is valid. **/ EFI_STATUS Ip4TxTokenValid ( IN EFI_IP4_COMPLETION_TOKEN *Token, - IN IP4_INTERFACE *IpIf + IN IP4_INTERFACE *IpIf, + IN BOOLEAN RawData ) { EFI_IP4_TRANSMIT_DATA *TxData; @@ -1653,20 +1669,7 @@ Ip4TxTokenValid ( TxData = Token->Packet.TxData; // - // Check the IP options: no more than 40 bytes and format is OK - // - if (TxData->OptionsLength != 0) { - if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) { - return EFI_INVALID_PARAMETER; - } - - if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) { - return EFI_INVALID_PARAMETER; - } - } - - // - // Check the fragment table: no empty fragment, and length isn't bogus + // Check the fragment table: no empty fragment, and length isn't bogus. // if ((TxData->TotalDataLength == 0) || (TxData->FragmentCount == 0)) { return EFI_INVALID_PARAMETER; @@ -1674,6 +1677,10 @@ Ip4TxTokenValid ( Offset = TxData->TotalDataLength; + if (Offset > IP4_MAX_PACKET_SIZE) { + return EFI_BAD_BUFFER_SIZE; + } + for (Index = 0; Index < TxData->FragmentCount; Index++) { if ((TxData->FragmentTable[Index].FragmentBuffer == NULL) || (TxData->FragmentTable[Index].FragmentLength == 0)) { @@ -1688,6 +1695,27 @@ Ip4TxTokenValid ( return EFI_INVALID_PARAMETER; } + // + // NOTE that OptionsLength/OptionsBuffer/OverrideData are ignored if RawData + // is TRUE. + // + if (RawData) { + return EFI_SUCCESS; + } + + // + // Check the IP options: no more than 40 bytes and format is OK + // + if (TxData->OptionsLength != 0) { + if ((TxData->OptionsLength > 40) || (TxData->OptionsBuffer == NULL)) { + return EFI_INVALID_PARAMETER; + } + + if (!Ip4OptionIsValid (TxData->OptionsBuffer, TxData->OptionsLength, FALSE)) { + return EFI_INVALID_PARAMETER; + } + } + // // Check the source and gateway: they must be a valid unicast. // Gateway must also be on the connected network. @@ -1888,6 +1916,10 @@ EfiIp4Transmit ( EFI_TPL OldTpl; BOOLEAN DontFragment; UINT32 HeadLen; + UINT8 RawHdrLen; + UINT32 OptionsLength; + UINT8 *OptionsBuffer; + VOID *FirstFragment; if (This == NULL) { return EFI_INVALID_PARAMETER; @@ -1913,7 +1945,7 @@ EfiIp4Transmit ( // // make sure that token is properly formated // - Status = Ip4TxTokenValid (Token, IpIf); + Status = Ip4TxTokenValid (Token, IpIf, Config->RawData); if (EFI_ERROR (Status)) { goto ON_EXIT; @@ -1933,32 +1965,82 @@ EfiIp4Transmit ( // TxData = Token->Packet.TxData; - CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR)); - Head.Dst = NTOHL (Head.Dst); + FirstFragment = NULL; - if (TxData->OverrideData != NULL) { - Override = TxData->OverrideData; - Head.Protocol = Override->Protocol; - Head.Tos = Override->TypeOfService; - Head.Ttl = Override->TimeToLive; - DontFragment = Override->DoNotFragment; + if (Config->RawData) { + // + // When RawData is TRUE, first buffer in FragmentTable points to a raw + // IPv4 fragment including IPv4 header and options. + // + FirstFragment = TxData->FragmentTable[0].FragmentBuffer; + CopyMem (&RawHdrLen, FirstFragment, sizeof (UINT8)); - CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR)); - CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR)); + RawHdrLen = (UINT8) (RawHdrLen & 0x0f); + if (RawHdrLen < 5) { + return EFI_INVALID_PARAMETER; + } + + RawHdrLen = (UINT8) (RawHdrLen << 2); + + CopyMem (&Head, FirstFragment, IP4_MIN_HEADLEN); + + Ip4NtohHead (&Head); + HeadLen = 0; + DontFragment = IP4_DO_NOT_FRAGMENT (Head.Fragment); - Head.Src = NTOHL (Head.Src); - GateWay = NTOHL (GateWay); + if (!DontFragment) { + return EFI_INVALID_PARAMETER; + } + + GateWay = IP4_ALLZERO_ADDRESS; + + // + // Get IPv4 options from first fragment. + // + if (RawHdrLen == IP4_MIN_HEADLEN) { + OptionsLength = 0; + OptionsBuffer = NULL; + } else { + OptionsLength = RawHdrLen - IP4_MIN_HEADLEN; + OptionsBuffer = (UINT8 *) FirstFragment + IP4_MIN_HEADLEN; + } + + // + // Trim off IPv4 header and options from first fragment. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment + RawHdrLen; + TxData->FragmentTable[0].FragmentLength = TxData->FragmentTable[0].FragmentLength - RawHdrLen; } else { - Head.Src = IpIf->Ip; - GateWay = IP4_ALLZERO_ADDRESS; - Head.Protocol = Config->DefaultProtocol; - Head.Tos = Config->TypeOfService; - Head.Ttl = Config->TimeToLive; - DontFragment = Config->DoNotFragment; - } + CopyMem (&Head.Dst, &TxData->DestinationAddress, sizeof (IP4_ADDR)); + Head.Dst = NTOHL (Head.Dst); - Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0); - HeadLen = (TxData->OptionsLength + 3) & (~0x03); + if (TxData->OverrideData != NULL) { + Override = TxData->OverrideData; + Head.Protocol = Override->Protocol; + Head.Tos = Override->TypeOfService; + Head.Ttl = Override->TimeToLive; + DontFragment = Override->DoNotFragment; + + CopyMem (&Head.Src, &Override->SourceAddress, sizeof (IP4_ADDR)); + CopyMem (&GateWay, &Override->GatewayAddress, sizeof (IP4_ADDR)); + + Head.Src = NTOHL (Head.Src); + GateWay = NTOHL (GateWay); + } else { + Head.Src = IpIf->Ip; + GateWay = IP4_ALLZERO_ADDRESS; + Head.Protocol = Config->DefaultProtocol; + Head.Tos = Config->TypeOfService; + Head.Ttl = Config->TimeToLive; + DontFragment = Config->DoNotFragment; + } + + Head.Fragment = IP4_HEAD_FRAGMENT_FIELD (DontFragment, FALSE, 0); + HeadLen = (TxData->OptionsLength + 3) & (~0x03); + + OptionsLength = TxData->OptionsLength; + OptionsBuffer = (UINT8 *) (TxData->OptionsBuffer); + } // // If don't fragment and fragment needed, return error @@ -2004,6 +2086,13 @@ EfiIp4Transmit ( // free the IP4_TXTOKEN_WRAP. Now, the token wrap hasn't been // enqueued. // + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + NetbufFree (Wrap->Packet); goto ON_EXIT; } @@ -2019,8 +2108,8 @@ EfiIp4Transmit ( IpInstance, Wrap->Packet, &Head, - TxData->OptionsBuffer, - TxData->OptionsLength, + OptionsBuffer, + OptionsLength, GateWay, Ip4OnPacketSent, Wrap @@ -2028,9 +2117,24 @@ EfiIp4Transmit ( if (EFI_ERROR (Status)) { Wrap->Sent = FALSE; + + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + NetbufFree (Wrap->Packet); } + if (Config->RawData) { + // + // Restore pointer of first fragment in RawData mode. + // + TxData->FragmentTable[0].FragmentBuffer = (UINT8 *) FirstFragment; + } + ON_EXIT: gBS->RestoreTPL (OldTpl); return Status; -- cgit v1.2.3