/** The entry point for Tcp driver, which is used to install Tcp driver on the ImageHandle. @param[in] ImageHandle The firmware allocated handle for this driver image. @param[in] SystemTable Pointer to the EFI system table. @retval EFI_SUCCESS The driver loaded. @retval other The driver did not load. **/ EFI_STATUS EFIAPI TcpDriverEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINT32 Seed; // // Install the TCP Driver Binding Protocol // Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &gTcp4DriverBinding, ImageHandle, &gTcpComponentName, &gTcpComponentName2 ); if (EFI_ERROR (Status)) { return Status; } // // Install the TCP Driver Binding Protocol // Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &gTcp6DriverBinding, NULL, &gTcpComponentName, &gTcpComponentName2 ); if (EFI_ERROR (Status)) { gBS->UninstallMultipleProtocolInterfaces ( ImageHandle, &gEfiDriverBindingProtocolGuid, &gTcp4DriverBinding, &gEfiComponentName2ProtocolGuid, &gTcpComponentName2, &gEfiComponentNameProtocolGuid, &gTcpComponentName, NULL ); return Status; } // // Initialize ISS and random port. // Seed = NetRandomInitSeed (); mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss; mTcp4RandomPort = (UINT16) (TCP_PORT_KNOWN + (NET_RANDOM (Seed) % TCP_PORT_KNOWN)); mTcp6RandomPort = mTcp4RandomPort; return EFI_SUCCESS; }
/** The entry point for Tcp4 driver, used to install Tcp4 driver on the ImageHandle. @param ImageHandle The firmware allocated handle for this driver image. @param SystemTable Pointer to the EFI system table. @retval EFI_SUCCESS Driver loaded. @retval other Driver not loaded. **/ EFI_STATUS EFIAPI Tcp4DriverEntryPoint ( IN EFI_HANDLE ImageHandle, IN EFI_SYSTEM_TABLE *SystemTable ) { EFI_STATUS Status; UINT32 Seed; // // Install the TCP4 Driver Binding Protocol // Status = EfiLibInstallDriverBindingComponentName2 ( ImageHandle, SystemTable, &mTcp4DriverBinding, ImageHandle, &gTcp4ComponentName, &gTcp4ComponentName2 ); ASSERT_EFI_ERROR (Status); // // Initialize ISS and random port. // Seed = NetRandomInitSeed (); mTcpGlobalIss = NET_RANDOM (Seed) % mTcpGlobalIss; mTcp4RandomPort = (UINT16) (TCP4_PORT_KNOWN + (UINT16) (NET_RANDOM(Seed) % TCP4_PORT_KNOWN)); return Status; }
/** Create the opened instances based on IPv6. @param[in] This Pointer to EFI_DRIVER_BINDING_PROTOCOL. @param[in] ControllerHandle Handle of the child to destroy. @param[in] Private Handle Pointer to PXEBC_PRIVATE_DATA. @retval EFI_SUCCESS The instances based on IPv6 were all created successfully. @retval Others An unexpected error occurred. **/ EFI_STATUS PxeBcCreateIp6Children ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN EFI_HANDLE ControllerHandle, IN PXEBC_PRIVATE_DATA *Private ) { EFI_STATUS Status; IPv6_DEVICE_PATH Ip6Node; EFI_UDP6_CONFIG_DATA *Udp6CfgData; EFI_IP6_CONFIG_DATA *Ip6CfgData; EFI_IP6_MODE_DATA Ip6ModeData; PXEBC_PRIVATE_PROTOCOL *Id; EFI_SIMPLE_NETWORK_PROTOCOL *Snp; UINTN Index; if (Private->Ip6Nic != NULL) { // // Already created before. // return EFI_SUCCESS; } Private->Ip6Nic = AllocateZeroPool (sizeof (PXEBC_VIRTUAL_NIC)); if (Private->Ip6Nic == NULL) { return EFI_OUT_OF_RESOURCES; } Private->Ip6Nic->Private = Private; Private->Ip6Nic->Signature = PXEBC_VIRTUAL_NIC_SIGNATURE; // // Create Dhcp6 child and open Dhcp6 protocol for PxeBc->Dhcp. // Status = NetLibCreateServiceChild ( ControllerHandle, This->DriverBindingHandle, &gEfiDhcp6ServiceBindingProtocolGuid, &Private->Dhcp6Child ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( Private->Dhcp6Child, &gEfiDhcp6ProtocolGuid, (VOID **) &Private->Dhcp6, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Generate a random IAID for the Dhcp6 assigned address. // Private->IaId = NET_RANDOM (NetRandomInitSeed ()); if (Private->Snp != NULL) { for (Index = 0; Index < Private->Snp->Mode->HwAddressSize; Index++) { Private->IaId |= (Private->Snp->Mode->CurrentAddress.Addr[Index] << ((Index << 3) & 31)); } } // // Create Mtftp6 child and open Mtftp6 protocol for PxeBc->Mtftp. // Status = NetLibCreateServiceChild ( ControllerHandle, This->DriverBindingHandle, &gEfiMtftp6ServiceBindingProtocolGuid, &Private->Mtftp6Child ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( Private->Mtftp6Child, &gEfiMtftp6ProtocolGuid, (VOID **) &Private->Mtftp6, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Create Udp6 child and open Udp6 protocol for PxeBc->UdpRead. // Status = NetLibCreateServiceChild ( ControllerHandle, This->DriverBindingHandle, &gEfiUdp6ServiceBindingProtocolGuid, &Private->Udp6ReadChild ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( Private->Udp6ReadChild, &gEfiUdp6ProtocolGuid, (VOID **) &Private->Udp6Read, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Create Udp6 child and open Udp6 protocol for PxeBc->UdpWrite. // Status = NetLibCreateServiceChild ( ControllerHandle, This->DriverBindingHandle, &gEfiUdp6ServiceBindingProtocolGuid, &Private->Udp6WriteChild ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( Private->Udp6WriteChild, &gEfiUdp6ProtocolGuid, (VOID **) &Private->Udp6Write, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Create Ip6 child and open Ip6 protocol for background ICMP6 packets. // Status = NetLibCreateServiceChild ( ControllerHandle, This->DriverBindingHandle, &gEfiIp6ServiceBindingProtocolGuid, &Private->Ip6Child ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( Private->Ip6Child, &gEfiIp6ProtocolGuid, (VOID **) &Private->Ip6, This->DriverBindingHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Get max packet size from Ip6 to calculate block size for Tftp later. // Status = Private->Ip6->GetModeData (Private->Ip6, &Ip6ModeData, NULL, NULL); if (EFI_ERROR (Status)) { goto ON_ERROR; } Private->Ip6MaxPacketSize = Ip6ModeData.MaxPacketSize; // // Locate Ip6->Ip6Config and store it for set IPv6 address. // Status = gBS->HandleProtocol ( ControllerHandle, &gEfiIp6ConfigProtocolGuid, (VOID **) &Private->Ip6Cfg ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Create a device path node for Ipv6 virtual nic, and append it. // ZeroMem (&Ip6Node, sizeof (IPv6_DEVICE_PATH)); Ip6Node.Header.Type = MESSAGING_DEVICE_PATH; Ip6Node.Header.SubType = MSG_IPv6_DP; Ip6Node.PrefixLength = IP6_PREFIX_LENGTH; SetDevicePathNodeLength (&Ip6Node.Header, sizeof (Ip6Node)); Private->Ip6Nic->DevicePath = AppendDevicePathNode (Private->DevicePath, &Ip6Node.Header); if (Private->Ip6Nic->DevicePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_ERROR; } CopyMem ( &Private->Ip6Nic->LoadFile, &gLoadFileProtocolTemplate, sizeof (EFI_LOAD_FILE_PROTOCOL) ); // // Create a new handle for IPv6 virtual nic, // and install PxeBaseCode, LoadFile and DevicePath protocols. // Status = gBS->InstallMultipleProtocolInterfaces ( &Private->Ip6Nic->Controller, &gEfiDevicePathProtocolGuid, Private->Ip6Nic->DevicePath, &gEfiLoadFileProtocolGuid, &Private->Ip6Nic->LoadFile, &gEfiPxeBaseCodeProtocolGuid, &Private->PxeBc, NULL ); if (EFI_ERROR (Status)) { goto ON_ERROR; } if (Private->Snp != NULL) { // // Install SNP protocol on purpose is for some OS loader backward // compatibility consideration. // Status = gBS->InstallProtocolInterface ( &Private->Ip6Nic->Controller, &gEfiSimpleNetworkProtocolGuid, EFI_NATIVE_INTERFACE, Private->Snp ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Open SNP on the child handle BY_DRIVER. It will prevent any additionally // layering to perform the experiment. // Status = gBS->OpenProtocol ( Private->Ip6Nic->Controller, &gEfiSimpleNetworkProtocolGuid, (VOID **) &Snp, This->DriverBindingHandle, Private->Ip6Nic->Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } } // // Open PxeBaseCodePrivate protocol by child to setup a parent-child relationship between // real NIC handle and the virtual IPv6 NIC handle. // Status = gBS->OpenProtocol ( ControllerHandle, &gEfiCallerIdGuid, (VOID **) &Id, This->DriverBindingHandle, Private->Ip6Nic->Controller, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } // // Set IPv6 avaiable flag and set default configure data for // Udp6Read and Ip6 instance. // Private->Mode.Ipv6Available = TRUE; Udp6CfgData = &Private->Udp6CfgData; Ip6CfgData = &Private->Ip6CfgData; Udp6CfgData->AcceptAnyPort = TRUE; Udp6CfgData->AllowDuplicatePort = TRUE; Udp6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT; Udp6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; Udp6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; Ip6CfgData->AcceptIcmpErrors = TRUE; Ip6CfgData->DefaultProtocol = IP6_ICMP; Ip6CfgData->HopLimit = PXEBC_DEFAULT_HOPLIMIT; Ip6CfgData->ReceiveTimeout = PXEBC_DEFAULT_LIFETIME; Ip6CfgData->TransmitTimeout = PXEBC_DEFAULT_LIFETIME; return EFI_SUCCESS; ON_ERROR: PxeBcDestroyIp6Children (This, Private); return Status; }
/** Parse the DHCP ACK to get Dns4 server information. @param Instance The DNS instance. @param DnsServerCount Retrieved Dns4 server Ip count. @param DnsServerList Retrieved Dns4 server Ip list. @retval EFI_SUCCESS The Dns4 information is got from the DHCP ACK. @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. @retval EFI_NO_MEDIA There was a media error. @retval Others Other errors as indicated. **/ EFI_STATUS GetDns4ServerFromDhcp4 ( IN DNS_INSTANCE *Instance, OUT UINT32 *DnsServerCount, OUT EFI_IPv4_ADDRESS **DnsServerList ) { EFI_STATUS Status; EFI_HANDLE Image; EFI_HANDLE Controller; EFI_STATUS MediaStatus; EFI_HANDLE MnpChildHandle; EFI_MANAGED_NETWORK_PROTOCOL *Mnp; EFI_MANAGED_NETWORK_CONFIG_DATA MnpConfigData; EFI_HANDLE Dhcp4Handle; EFI_DHCP4_PROTOCOL *Dhcp4; EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; UINTN DataSize; VOID *Data; EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo; EFI_DHCP4_PACKET SeedPacket; EFI_DHCP4_PACKET_OPTION *ParaList[2]; DNS4_SERVER_INFOR DnsServerInfor; EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN Token; BOOLEAN IsDone; UINTN Index; Image = Instance->Service->ImageHandle; Controller = Instance->Service->ControllerHandle; MnpChildHandle = NULL; Mnp = NULL; Dhcp4Handle = NULL; Dhcp4 = NULL; Ip4Config2 = NULL; DataSize = 0; Data = NULL; InterfaceInfo = NULL; ZeroMem ((UINT8 *) ParaList, sizeof (ParaList)); ZeroMem (&MnpConfigData, sizeof (EFI_MANAGED_NETWORK_CONFIG_DATA)); ZeroMem (&DnsServerInfor, sizeof (DNS4_SERVER_INFOR)); ZeroMem (&Token, sizeof (EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN)); DnsServerInfor.ServerCount = DnsServerCount; IsDone = FALSE; // // Check media. // MediaStatus = EFI_SUCCESS; NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus); if (MediaStatus != EFI_SUCCESS) { return EFI_NO_MEDIA; } // // Create a Mnp child instance, get the protocol and config for it. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiManagedNetworkServiceBindingProtocolGuid, &MnpChildHandle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( MnpChildHandle, &gEfiManagedNetworkProtocolGuid, (VOID **) &Mnp, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } MnpConfigData.ReceivedQueueTimeoutValue = 0; MnpConfigData.TransmitQueueTimeoutValue = 0; MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO; MnpConfigData.EnableUnicastReceive = TRUE; MnpConfigData.EnableMulticastReceive = TRUE; MnpConfigData.EnableBroadcastReceive = TRUE; MnpConfigData.EnablePromiscuousReceive = FALSE; MnpConfigData.FlushQueuesOnReset = TRUE; MnpConfigData.EnableReceiveTimestamps = FALSE; MnpConfigData.DisableBackgroundPolling = FALSE; Status = Mnp->Configure(Mnp, &MnpConfigData); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Create a DHCP4 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDhcp4ServiceBindingProtocolGuid, &Dhcp4Handle ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = gBS->OpenProtocol ( Dhcp4Handle, &gEfiDhcp4ProtocolGuid, (VOID **) &Dhcp4, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Get Ip4Config2 instance info. // Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data); if (EFI_ERROR (Status) && Status != EFI_BUFFER_TOO_SMALL) { goto ON_EXIT; } Data = AllocateZeroPool (DataSize); if (Data == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeInterfaceInfo, &DataSize, Data); if (EFI_ERROR (Status)) { goto ON_EXIT; } InterfaceInfo = (EFI_IP4_CONFIG2_INTERFACE_INFO *)Data; // // Build required Token. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, DhcpCommonNotify, &IsDone, &Token.CompletionEvent ); if (EFI_ERROR (Status)) { goto ON_EXIT; } SetMem (&Token.RemoteAddress, sizeof (EFI_IPv4_ADDRESS), 0xff); Token.RemotePort = 67; Token.ListenPointCount = 1; Token.ListenPoints = AllocateZeroPool (Token.ListenPointCount * sizeof (EFI_DHCP4_LISTEN_POINT)); if (Token.ListenPoints == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } if (Instance->Dns4CfgData.UseDefaultSetting) { CopyMem (&(Token.ListenPoints[0].ListenAddress), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS)); CopyMem (&(Token.ListenPoints[0].SubnetMask), &(InterfaceInfo->SubnetMask), sizeof (EFI_IPv4_ADDRESS)); } else { CopyMem (&(Token.ListenPoints[0].ListenAddress), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS)); CopyMem (&(Token.ListenPoints[0].SubnetMask), &(Instance->Dns4CfgData.SubnetMask), sizeof (EFI_IPv4_ADDRESS)); } Token.ListenPoints[0].ListenPort = 68; Token.TimeoutValue = DNS_TIME_TO_GETMAP; DnsInitSeedPacket (&SeedPacket, InterfaceInfo); ParaList[0] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION)); if (ParaList[0] == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } ParaList[0]->OpCode = DHCP4_TAG_TYPE; ParaList[0]->Length = 1; ParaList[0]->Data[0] = DHCP4_MSG_REQUEST; ParaList[1] = AllocateZeroPool (sizeof (EFI_DHCP4_PACKET_OPTION)); if (ParaList[1] == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } ParaList[1]->OpCode = DHCP4_TAG_PARA_LIST; ParaList[1]->Length = 1; ParaList[1]->Data[0] = DHCP4_TAG_DNS_SERVER; Status = Dhcp4->Build (Dhcp4, &SeedPacket, 0, NULL, 2, ParaList, &Token.Packet); Token.Packet->Dhcp4.Header.Xid = HTONL(NET_RANDOM (NetRandomInitSeed ())); Token.Packet->Dhcp4.Header.Reserved = HTONS ((UINT16)0x8000); if (Instance->Dns4CfgData.UseDefaultSetting) { CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(InterfaceInfo->StationAddress), sizeof (EFI_IPv4_ADDRESS)); } else { CopyMem (&(Token.Packet->Dhcp4.Header.ClientAddr), &(Instance->Dns4CfgData.StationIp), sizeof (EFI_IPv4_ADDRESS)); } CopyMem (Token.Packet->Dhcp4.Header.ClientHwAddr, &(InterfaceInfo->HwAddress), InterfaceInfo->HwAddressSize); Token.Packet->Dhcp4.Header.HwAddrLen = (UINT8)(InterfaceInfo->HwAddressSize); // // TransmitReceive Token // Status = Dhcp4->TransmitReceive (Dhcp4, &Token); if (EFI_ERROR (Status)) { goto ON_EXIT; } // // Poll the packet // do { Status = Mnp->Poll (Mnp); } while (!IsDone); // // Parse the ACK to get required information if received done. // if (IsDone && !EFI_ERROR (Token.Status)) { for (Index = 0; Index < Token.ResponseCount; Index++) { Status = ParseDhcp4Ack (Dhcp4, &Token.ResponseList[Index], &DnsServerInfor); if (!EFI_ERROR (Status)) { break; } } *DnsServerList = DnsServerInfor.ServerList; } else { Status = Token.Status; } ON_EXIT: if (Data != NULL) { FreePool (Data); } for (Index = 0; Index < 2; Index++) { if (ParaList[Index] != NULL) { FreePool (ParaList[Index]); } } if (Token.ListenPoints) { FreePool (Token.ListenPoints); } if (Token.Packet) { FreePool (Token.Packet); } if (Token.ResponseList != NULL) { FreePool (Token.ResponseList); } if (Token.CompletionEvent != NULL) { gBS->CloseEvent (Token.CompletionEvent); } if (Dhcp4 != NULL) { Dhcp4->Stop (Dhcp4); Dhcp4->Configure (Dhcp4, NULL); gBS->CloseProtocol ( Dhcp4Handle, &gEfiDhcp4ProtocolGuid, Image, Controller ); } if (Dhcp4Handle != NULL) { NetLibDestroyServiceChild ( Controller, Image, &gEfiDhcp4ServiceBindingProtocolGuid, Dhcp4Handle ); } if (Mnp != NULL) { Mnp->Configure (Mnp, NULL); gBS->CloseProtocol ( MnpChildHandle, &gEfiManagedNetworkProtocolGuid, Image, Controller ); } NetLibDestroyServiceChild ( Controller, Image, &gEfiManagedNetworkServiceBindingProtocolGuid, MnpChildHandle ); return Status; }