/** Release all the resource used the HTTP service binding instance. @param[in] HttpService The HTTP private instance. @param[in] UsingIpv6 Indicate use TCP4 protocol or TCP6 protocol. if TRUE, use Tcp6 protocol. if FALSE, use Tcp4 protocl. **/ VOID HttpCleanService ( IN HTTP_SERVICE *HttpService, IN BOOLEAN UsingIpv6 ) { if (HttpService == NULL) { return ; } if (!UsingIpv6) { if (HttpService->Tcp4ChildHandle != NULL) { gBS->CloseProtocol ( HttpService->Tcp4ChildHandle, &gEfiTcp4ProtocolGuid, HttpService->ImageHandle, HttpService->ControllerHandle ); NetLibDestroyServiceChild ( HttpService->ControllerHandle, HttpService->ImageHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpService->Tcp4ChildHandle ); HttpService->Tcp4ChildHandle = NULL; } } else { if (HttpService->Tcp6ChildHandle != NULL) { gBS->CloseProtocol ( HttpService->Tcp6ChildHandle, &gEfiTcp6ProtocolGuid, HttpService->ImageHandle, HttpService->ControllerHandle ); NetLibDestroyServiceChild ( HttpService->ControllerHandle, HttpService->ImageHandle, &gEfiTcp6ServiceBindingProtocolGuid, HttpService->Tcp6ChildHandle ); HttpService->Tcp6ChildHandle = NULL; } } }
/** Destroy the socket. @param[in] Tcp4Io The Tcp4Io which wraps the socket to be destroyeds. **/ VOID Tcp4IoDestroySocket ( IN TCP4_IO *Tcp4Io ) { EFI_TCP4_PROTOCOL *Tcp4; Tcp4 = Tcp4Io->Tcp4; Tcp4->Configure (Tcp4, NULL); gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event); gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event); gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event); gBS->CloseProtocol ( Tcp4Io->Handle, &gEfiTcp4ProtocolGuid, Tcp4Io->Image, Tcp4Io->Controller ); NetLibDestroyServiceChild ( Tcp4Io->Controller, Tcp4Io->Image, &gEfiTcp4ServiceBindingProtocolGuid, Tcp4Io->Handle ); }
/** Release all the resource used the HTTP service binding instance. @param HttpService The HTTP private instance. **/ VOID HttpCleanService ( IN HTTP_SERVICE *HttpService ) { if (HttpService == NULL) { return ; } if (HttpService->TcpChildHandle != NULL) { gBS->CloseProtocol ( HttpService->TcpChildHandle, &gEfiTcp4ProtocolGuid, HttpService->ImageHandle, HttpService->ControllerHandle ); NetLibDestroyServiceChild ( HttpService->ControllerHandle, HttpService->ImageHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpService->TcpChildHandle ); } }
/** Clean up the HTTP child, release all the resources used by it. @param[in] HttpInstance The HTTP child to clean up. **/ VOID HttpCleanProtocol ( IN HTTP_PROTOCOL *HttpInstance ) { HttpCloseConnection (HttpInstance); HttpCloseTcp4ConnCloseEvent (HttpInstance); if (HttpInstance->CacheBody != NULL) { FreePool (HttpInstance->CacheBody); HttpInstance->CacheBody = NULL; HttpInstance->NextMsg = NULL; } if (HttpInstance->RemoteHost != NULL) { FreePool (HttpInstance->RemoteHost); HttpInstance->RemoteHost = NULL; } if (HttpInstance->MsgParser != NULL) { HttpFreeMsgParser (HttpInstance->MsgParser); HttpInstance->MsgParser = NULL; } if (HttpInstance->Url != NULL) { FreePool (HttpInstance->Url); HttpInstance->Url = NULL; } NetMapClean (&HttpInstance->TxTokens); NetMapClean (&HttpInstance->RxTokens); if (HttpInstance->TcpChildHandle != NULL) { gBS->CloseProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, HttpInstance->Service->ImageHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, HttpInstance->Service->ImageHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, HttpInstance->Service->ImageHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpInstance->TcpChildHandle ); } }
/** Destroy the HTTP child based on IPv4 stack. @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. @param[in] Private Pointer to HTTP_BOOT_PRIVATE_DATA. **/ VOID HttpBootDestroyIp4Children ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN HTTP_BOOT_PRIVATE_DATA *Private ) { ASSERT (This != NULL); ASSERT (Private != NULL); ASSERT (Private->UsingIpv6 == FALSE); if (Private->Dhcp4Child != NULL) { gBS->CloseProtocol ( Private->Dhcp4Child, &gEfiDhcp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiDhcp4ServiceBindingProtocolGuid, Private->Dhcp4Child ); } if (Private->HttpCreated) { HttpIoDestroyIo (&Private->HttpIo); Private->HttpCreated = FALSE; } gBS->CloseProtocol ( Private->Controller, &gEfiCallerIdGuid, This->DriverBindingHandle, Private->ChildHandle ); gBS->UninstallMultipleProtocolInterfaces ( Private->ChildHandle, &gEfiLoadFileProtocolGuid, &Private->LoadFile, &gEfiDevicePathProtocolGuid, Private->DevicePath, NULL ); if (Private->DevicePath != NULL) { FreePool (Private->DevicePath); Private->DevicePath = NULL; } }
/** Destroy the HTTP_IO and release the resouces. @param[in] HttpIo The HTTP_IO which wraps the HTTP service to be destroyed. **/ VOID HttpIoDestroyIo ( IN HTTP_IO *HttpIo ) { EFI_HTTP_PROTOCOL *Http; EFI_EVENT Event; if (HttpIo == NULL) { return; } Event = HttpIo->ReqToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = HttpIo->RspToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = HttpIo->TimeoutEvent; if (Event != NULL) { gBS->CloseEvent (Event); } Http = HttpIo->Http; if (Http != NULL) { Http->Configure (Http, NULL); gBS->CloseProtocol ( HttpIo->Handle, &gEfiHttpProtocolGuid, HttpIo->Image, HttpIo->Controller ); } NetLibDestroyServiceChild ( HttpIo->Controller, HttpIo->Image, &gEfiHttpServiceBindingProtocolGuid, HttpIo->Handle ); }
/** Create a child for the service identified by its service binding protocol GUID and get from the child the interface of the protocol identified by its GUID. @param[in] ControllerHandle Controller handle. @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the service to be created. @param[in] ProtocolGuid GUID of the protocol to be open. @param[out] ChildHandle Address where the handler of the created child is returned. NULL is returned in case of error. @param[out] Interface Address where a pointer to the protocol interface is returned in case of success. @return EFI_SUCCESS The child was created and the protocol opened. @return Others Either the creation of the child or the opening of the protocol failed. **/ STATIC EFI_STATUS CreateServiceChildAndOpenProtocol ( IN EFI_HANDLE ControllerHandle, IN EFI_GUID *ServiceBindingProtocolGuid, IN EFI_GUID *ProtocolGuid, OUT EFI_HANDLE *ChildHandle, OUT VOID **Interface ) { EFI_STATUS Status; *ChildHandle = NULL; Status = NetLibCreateServiceChild ( ControllerHandle, gImageHandle, ServiceBindingProtocolGuid, ChildHandle ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( *ChildHandle, ProtocolGuid, Interface, gImageHandle, ControllerHandle, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { NetLibDestroyServiceChild ( ControllerHandle, gImageHandle, ServiceBindingProtocolGuid, *ChildHandle ); *ChildHandle = NULL; } } return Status; }
/** Close the protocol identified by its GUID on the child handle of the service identified by its service binding protocol GUID, then destroy the child handle. @param[in] ControllerHandle Controller handle. @param[in] ServiceBindingProtocolGuid Service binding protocol GUID of the service to be destroyed. @param[in] ProtocolGuid GUID of the protocol to be closed. @param[in] ChildHandle Handle of the child to be destroyed. **/ STATIC VOID CloseProtocolAndDestroyServiceChild ( IN EFI_HANDLE ControllerHandle, IN EFI_GUID *ServiceBindingProtocolGuid, IN EFI_GUID *ProtocolGuid, IN EFI_HANDLE ChildHandle ) { gBS->CloseProtocol ( ChildHandle, ProtocolGuid, gImageHandle, ControllerHandle ); NetLibDestroyServiceChild ( ControllerHandle, gImageHandle, ServiceBindingProtocolGuid, ChildHandle ); }
/** Intiialize the HTTP_PROTOCOL structure to the unconfigured state. @param[in] HttpSb The HTTP service private instance. @param[in, out] HttpInstance Pointer to HTTP_PROTOCOL structure. @retval EFI_SUCCESS HTTP_PROTOCOL structure is initialized successfully. @retval Others Other error as indicated. **/ EFI_STATUS HttpInitProtocol ( IN HTTP_SERVICE *HttpSb, IN OUT HTTP_PROTOCOL *HttpInstance ) { EFI_STATUS Status; VOID *Interface; ASSERT ((HttpSb != NULL) && (HttpInstance != NULL)); HttpInstance->Signature = HTTP_PROTOCOL_SIGNATURE; CopyMem (&HttpInstance->Http, &mEfiHttpTemplate, sizeof (HttpInstance->Http)); HttpInstance->Service = HttpSb; // // Create TCP child. // Status = NetLibCreateServiceChild ( HttpInstance->Service->ControllerHandle, HttpInstance->Service->ImageHandle, &gEfiTcp4ServiceBindingProtocolGuid, &HttpInstance->TcpChildHandle ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, (VOID **) &Interface, HttpInstance->Service->ImageHandle, HttpInstance->Service->ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->OpenProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, (VOID **) &HttpInstance->Tcp4, HttpInstance->Service->ImageHandle, HttpInstance->Handle, EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER ); if (EFI_ERROR(Status)) { goto ON_ERROR; } HttpInstance->Url = AllocateZeroPool (HTTP_URL_BUFFER_LEN); if (HttpInstance->Url == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_ERROR; } NetMapInit (&HttpInstance->TxTokens); NetMapInit (&HttpInstance->RxTokens); return EFI_SUCCESS; ON_ERROR: if (HttpInstance->TcpChildHandle != NULL) { gBS->CloseProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, HttpInstance->Service->ImageHandle, HttpInstance->Service->ControllerHandle ); gBS->CloseProtocol ( HttpInstance->TcpChildHandle, &gEfiTcp4ProtocolGuid, HttpInstance->Service->ImageHandle, HttpInstance->Handle ); NetLibDestroyServiceChild ( HttpInstance->Service->ControllerHandle, HttpInstance->Service->ImageHandle, &gEfiTcp4ServiceBindingProtocolGuid, HttpInstance->TcpChildHandle ); } 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; }
/** Parse the DHCP ACK to get Dns6 server information. @param Image The handle of the driver image. @param Controller The handle of the controller. @param DnsServerCount Retrieved Dns6 server Ip count. @param DnsServerList Retrieved Dns6 server Ip list. @retval EFI_SUCCESS The Dns6 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 GetDns6ServerFromDhcp6 ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, OUT UINT32 *DnsServerCount, OUT EFI_IPv6_ADDRESS **DnsServerList ) { EFI_HANDLE Dhcp6Handle; EFI_DHCP6_PROTOCOL *Dhcp6; EFI_STATUS Status; EFI_STATUS TimerStatus; EFI_DHCP6_PACKET_OPTION *Oro; EFI_DHCP6_RETRANSMISSION InfoReqReXmit; EFI_EVENT Timer; EFI_STATUS MediaStatus; DNS6_SERVER_INFOR DnsServerInfor; Dhcp6Handle = NULL; Dhcp6 = NULL; Oro = NULL; Timer = NULL; ZeroMem (&DnsServerInfor, sizeof (DNS6_SERVER_INFOR)); DnsServerInfor.ServerCount = DnsServerCount; // // Check media status before doing DHCP. // MediaStatus = EFI_SUCCESS; NetLibDetectMediaWaitTimeout (Controller, DNS_CHECK_MEDIA_GET_DHCP_WAITING_TIME, &MediaStatus); if (MediaStatus != EFI_SUCCESS) { return EFI_NO_MEDIA; } // // Create a DHCP6 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDhcp6ServiceBindingProtocolGuid, &Dhcp6Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Dhcp6Handle, &gEfiDhcp6ProtocolGuid, (VOID **) &Dhcp6, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 1); if (Oro == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } // // Ask the server to reply with DNS options. // All members in EFI_DHCP6_PACKET_OPTION are in network order. // Oro->OpCode = HTONS (DHCP6_TAG_DNS_REQUEST); Oro->OpLen = HTONS (2); Oro->Data[1] = DHCP6_TAG_DNS_SERVER; InfoReqReXmit.Irt = 4; InfoReqReXmit.Mrc = 1; InfoReqReXmit.Mrt = 10; InfoReqReXmit.Mrd = 30; Status = Dhcp6->InfoRequest ( Dhcp6, TRUE, Oro, 0, NULL, &InfoReqReXmit, NULL, ParseDhcp6Ack, &DnsServerInfor ); if (Status == EFI_NO_MAPPING) { Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = gBS->SetTimer ( Timer, TimerRelative, DNS_TIME_TO_GETMAP * TICKS_PER_SECOND ); if (EFI_ERROR (Status)) { goto ON_EXIT; } do { TimerStatus = gBS->CheckEvent (Timer); if (!EFI_ERROR (TimerStatus)) { Status = Dhcp6->InfoRequest ( Dhcp6, TRUE, Oro, 0, NULL, &InfoReqReXmit, NULL, ParseDhcp6Ack, &DnsServerInfor ); } } while (TimerStatus == EFI_NOT_READY); } *DnsServerList = DnsServerInfor.ServerList; ON_EXIT: if (Oro != NULL) { FreePool (Oro); } if (Timer != NULL) { gBS->CloseEvent (Timer); } if (Dhcp6 != NULL) { gBS->CloseProtocol ( Dhcp6Handle, &gEfiDhcp6ProtocolGuid, Image, Controller ); } NetLibDestroyServiceChild ( Controller, Image, &gEfiDhcp6ServiceBindingProtocolGuid, Dhcp6Handle ); return Status; }
/** Create an IP child, use it to start the auto configuration, then destroy it. @param[in] Controller The controller which has the service installed. @param[in] Image The image handle used to open service. @retval EFI_SUCCESS The configuration is done. **/ EFI_STATUS EFIAPI IfConfigStartIp4( IN EFI_HANDLE Controller, IN EFI_HANDLE Image ) { EFI_IP4_PROTOCOL *Ip4; EFI_HANDLE Ip4Handle; EFI_IP4_CONFIG_DATA Ip4ConfigData; EFI_STATUS Status; // // Get the Ip4ServiceBinding Protocol // Ip4Handle = NULL; Ip4 = NULL; Status = NetLibCreateServiceChild ( Controller, Image, &gEfiIp4ServiceBindingProtocolGuid, &Ip4Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Ip4Handle, &gEfiIp4ProtocolGuid, (VOID **) &Ip4, Controller, Image, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP; Ip4ConfigData.AcceptAnyProtocol = FALSE; Ip4ConfigData.AcceptIcmpErrors = FALSE; Ip4ConfigData.AcceptBroadcast = FALSE; Ip4ConfigData.AcceptPromiscuous = FALSE; Ip4ConfigData.UseDefaultAddress = TRUE; ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS)); ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); Ip4ConfigData.TypeOfService = 0; Ip4ConfigData.TimeToLive = 1; Ip4ConfigData.DoNotFragment = FALSE; Ip4ConfigData.RawData = FALSE; Ip4ConfigData.ReceiveTimeout = 0; Ip4ConfigData.TransmitTimeout = 0; Ip4->Configure (Ip4, &Ip4ConfigData); ON_EXIT: NetLibDestroyServiceChild ( Controller, Image, &gEfiIp4ServiceBindingProtocolGuid, Ip4Handle ); return Status; }
/** Parse the DHCP ACK to get the address configuration and DNS information. @param[in] Image The handle of the driver image. @param[in] Controller The handle of the controller; @param[in, out] ConfigData The attempt configuration data. @retval EFI_SUCCESS The DNS information is got from the DHCP ACK. @retval EFI_NO_MAPPING DHCP failed to acquire address and other information. @retval EFI_INVALID_PARAMETER The DHCP ACK's DNS option is malformatted. @retval EFI_DEVICE_ERROR Some unexpected error occurred. @retval EFI_OUT_OF_RESOURCES There is no sufficient resource to finish the operation. @retval EFI_NO_MEDIA There was a media error. **/ EFI_STATUS IScsiDoDhcp6 ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN OUT ISCSI_ATTEMPT_CONFIG_NVDATA *ConfigData ) { EFI_HANDLE Dhcp6Handle; EFI_DHCP6_PROTOCOL *Dhcp6; EFI_STATUS Status; EFI_STATUS TimerStatus; EFI_DHCP6_PACKET_OPTION *Oro; EFI_DHCP6_RETRANSMISSION InfoReqReXmit; EFI_EVENT Timer; BOOLEAN MediaPresent; // // Check media status before doing DHCP. // MediaPresent = TRUE; NetLibDetectMedia (Controller, &MediaPresent); if (!MediaPresent) { return EFI_NO_MEDIA; } // // iSCSI will only request target info from DHCPv6 server. // if (!ConfigData->SessionConfigData.TargetInfoFromDhcp) { return EFI_SUCCESS; } Dhcp6Handle = NULL; Dhcp6 = NULL; Oro = NULL; Timer = NULL; // // Create a DHCP6 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDhcp6ServiceBindingProtocolGuid, &Dhcp6Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Dhcp6Handle, &gEfiDhcp6ProtocolGuid, (VOID **) &Dhcp6, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Oro = AllocateZeroPool (sizeof (EFI_DHCP6_PACKET_OPTION) + 5); if (Oro == NULL) { Status = EFI_OUT_OF_RESOURCES; goto ON_EXIT; } // // Ask the server to reply with DNS and Boot File URL options by info request. // All members in EFI_DHCP6_PACKET_OPTION are in network order. // Oro->OpCode = HTONS (DHCP6_OPT_ORO); Oro->OpLen = HTONS (2 * 3); Oro->Data[1] = DHCP6_OPT_DNS_SERVERS; Oro->Data[3] = DHCP6_OPT_BOOT_FILE_URL; Oro->Data[5] = DHCP6_OPT_BOOT_FILE_PARAM; InfoReqReXmit.Irt = 4; InfoReqReXmit.Mrc = 1; InfoReqReXmit.Mrt = 10; InfoReqReXmit.Mrd = 30; Status = Dhcp6->InfoRequest ( Dhcp6, TRUE, Oro, 0, NULL, &InfoReqReXmit, NULL, IScsiDhcp6ParseReply, ConfigData ); if (Status == EFI_NO_MAPPING) { Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = gBS->SetTimer ( Timer, TimerRelative, ISCSI_GET_MAPPING_TIMEOUT ); if (EFI_ERROR (Status)) { goto ON_EXIT; } do { TimerStatus = gBS->CheckEvent (Timer); if (!EFI_ERROR (TimerStatus)) { Status = Dhcp6->InfoRequest ( Dhcp6, TRUE, Oro, 0, NULL, &InfoReqReXmit, NULL, IScsiDhcp6ParseReply, ConfigData ); } } while (TimerStatus == EFI_NOT_READY); } ON_EXIT: if (Oro != NULL) { FreePool (Oro); } if (Timer != NULL) { gBS->CloseEvent (Timer); } if (Dhcp6 != NULL) { gBS->CloseProtocol ( Dhcp6Handle, &gEfiDhcp6ProtocolGuid, Image, Controller ); } NetLibDestroyServiceChild ( Controller, Image, &gEfiDhcp6ServiceBindingProtocolGuid, Dhcp6Handle ); return Status; }
/** Retrieve the host address using the EFI_DNS6_PROTOCOL. @param[in] Private The pointer to the driver's private data. @param[in] HostName Pointer to buffer containing hostname. @param[out] IpAddress On output, pointer to buffer containing IPv6 address. @retval EFI_SUCCESS Operation succeeded. @retval EFI_DEVICE_ERROR An unexpected network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS HttpBootDns ( IN HTTP_BOOT_PRIVATE_DATA *Private, IN CHAR16 *HostName, OUT EFI_IPv6_ADDRESS *IpAddress ) { EFI_STATUS Status; EFI_DNS6_PROTOCOL *Dns6; EFI_DNS6_CONFIG_DATA Dns6ConfigData; EFI_DNS6_COMPLETION_TOKEN Token; EFI_HANDLE Dns6Handle; EFI_IP6_CONFIG_PROTOCOL *Ip6Config; EFI_IPv6_ADDRESS *DnsServerList; UINTN DnsServerListCount; UINTN DataSize; BOOLEAN IsDone; DnsServerList = NULL; DnsServerListCount = 0; Dns6 = NULL; Dns6Handle = NULL; ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN)); // // Get DNS server list from EFI IPv6 Configuration protocol. // Status = gBS->HandleProtocol (Private->Controller, &gEfiIp6ConfigProtocolGuid, (VOID **) &Ip6Config); if (!EFI_ERROR (Status)) { // // Get the required size. // DataSize = 0; Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { DnsServerList = AllocatePool (DataSize); if (DnsServerList == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Ip6Config->GetData (Ip6Config, Ip6ConfigDataTypeDnsServer, &DataSize, DnsServerList); if (EFI_ERROR (Status)) { FreePool (DnsServerList); DnsServerList = NULL; } else { DnsServerListCount = DataSize / sizeof (EFI_IPv6_ADDRESS); } } } // // Create a DNSv6 child instance and get the protocol. // Status = NetLibCreateServiceChild ( Private->Controller, Private->Ip6Nic->ImageHandle, &gEfiDns6ServiceBindingProtocolGuid, &Dns6Handle ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->OpenProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, (VOID **) &Dns6, Private->Ip6Nic->ImageHandle, Private->Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Exit; } // // Configure DNS6 instance for the DNS server address and protocol. // ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA)); Dns6ConfigData.DnsServerCount = (UINT32)DnsServerListCount; Dns6ConfigData.DnsServerList = DnsServerList; Dns6ConfigData.EnableDnsCache = TRUE; Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP; IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp,&Private->StationIp.v6); Status = Dns6->Configure ( Dns6, &Dns6ConfigData ); if (EFI_ERROR (Status)) { goto Exit; } Token.Status = EFI_NOT_READY; IsDone = FALSE; // // Create event to set the IsDone flag when name resolution is finished. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, HttpBootCommonNotify, &IsDone, &Token.Event ); if (EFI_ERROR (Status)) { goto Exit; } // // Start asynchronous name resolution. // Status = Dns6->HostNameToIp (Dns6, HostName, &Token); if (EFI_ERROR (Status)) { goto Exit; } while (!IsDone) { Dns6->Poll (Dns6); } // // Name resolution is done, check result. // Status = Token.Status; if (!EFI_ERROR (Status)) { if (Token.RspData.H2AData == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } // // We just return the first IPv6 address from DNS protocol. // IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList); Status = EFI_SUCCESS; } Exit: if (Token.Event != NULL) { gBS->CloseEvent (Token.Event); } if (Token.RspData.H2AData != NULL) { if (Token.RspData.H2AData->IpList != NULL) { FreePool (Token.RspData.H2AData->IpList); } FreePool (Token.RspData.H2AData); } if (Dns6 != NULL) { Dns6->Configure (Dns6, NULL); gBS->CloseProtocol ( Dns6Handle, &gEfiDns6ProtocolGuid, Private->Ip6Nic->ImageHandle, Private->Controller ); } if (Dns6Handle != NULL) { NetLibDestroyServiceChild ( Private->Controller, Private->Ip6Nic->ImageHandle, &gEfiDns6ServiceBindingProtocolGuid, Dns6Handle ); } if (DnsServerList != NULL) { FreePool (DnsServerList); } return Status; }
/** Destroy the opened instances based on IPv4. @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. @param[in] Private Pointer to PXEBC_PRIVATE_DATA. **/ VOID PxeBcDestroyIp4Children ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN PXEBC_PRIVATE_DATA *Private ) { ASSERT(Private != NULL); if (Private->ArpChild != NULL) { // // Close Arp for PxeBc->Arp and destroy the instance. // gBS->CloseProtocol ( Private->ArpChild, &gEfiArpProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiArpServiceBindingProtocolGuid, Private->ArpChild ); } if (Private->Ip4Child != NULL) { // // Close Ip4 for background ICMP error message and destroy the instance. // gBS->CloseProtocol ( Private->Ip4Child, &gEfiIp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiIp4ServiceBindingProtocolGuid, Private->Ip4Child ); } if (Private->Udp4WriteChild != NULL) { // // Close Udp4 for PxeBc->UdpWrite and destroy the instance. // gBS->CloseProtocol ( Private->Udp4WriteChild, &gEfiUdp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiUdp4ServiceBindingProtocolGuid, Private->Udp4WriteChild ); } if (Private->Udp4ReadChild != NULL) { // // Close Udp4 for PxeBc->UdpRead and destroy the instance. // gBS->CloseProtocol ( Private->Udp4ReadChild, &gEfiUdp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiUdp4ServiceBindingProtocolGuid, Private->Udp4ReadChild ); } if (Private->Mtftp4Child != NULL) { // // Close Mtftp4 for PxeBc->Mtftp4 and destroy the instance. // gBS->CloseProtocol ( Private->Mtftp4Child, &gEfiMtftp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiMtftp4ServiceBindingProtocolGuid, Private->Mtftp4Child ); } if (Private->Dhcp4Child != NULL) { // // Close Dhcp4 for PxeBc->Dhcp4 and destroy the instance. // gBS->CloseProtocol ( Private->Dhcp4Child, &gEfiDhcp4ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiDhcp4ServiceBindingProtocolGuid, Private->Dhcp4Child ); } if (Private->Ip4Nic != NULL) { // // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle. // gBS->CloseProtocol ( Private->Controller, &gEfiCallerIdGuid, This->DriverBindingHandle, Private->Ip4Nic->Controller ); gBS->UninstallMultipleProtocolInterfaces ( Private->Ip4Nic->Controller, &gEfiDevicePathProtocolGuid, Private->Ip4Nic->DevicePath, &gEfiLoadFileProtocolGuid, &Private->Ip4Nic->LoadFile, &gEfiPxeBaseCodeProtocolGuid, &Private->PxeBc, NULL ); if (Private->Snp != NULL) { // // Close SNP from the child virtual handle // gBS->CloseProtocol ( Private->Ip4Nic->Controller, &gEfiSimpleNetworkProtocolGuid, This->DriverBindingHandle, Private->Ip4Nic->Controller ); gBS->UninstallProtocolInterface ( Private->Ip4Nic->Controller, &gEfiSimpleNetworkProtocolGuid, Private->Snp ); } FreePool (Private->Ip4Nic); } Private->ArpChild = NULL; Private->Ip4Child = NULL; Private->Udp4WriteChild = NULL; Private->Udp4ReadChild = NULL; Private->Mtftp4Child = NULL; Private->Dhcp4Child = NULL; Private->Ip4Nic = NULL; }
/** Download an image from a TFTP server @param[in] DevicePath Device path of the TFTP boot option @param[in] ControllerHandle Handle of the network controller @param[in] RemainingDevicePath Device path of the TFTP boot option but the first node that identifies the network controller @param[in] Type Type to allocate memory pages @param[out] Image Address of the bufer where the image is stored in case of success @param[out] ImageSize Size in number of bytes of the i;age in case of success @retval EFI_SUCCESS The image was returned. @retval !EFI_SUCCESS Something went wrong. **/ EFI_STATUS BdsTftpLoadImage ( IN OUT EFI_DEVICE_PATH **DevicePath, IN EFI_HANDLE ControllerHandle, IN EFI_DEVICE_PATH *RemainingDevicePath, IN EFI_ALLOCATE_TYPE Type, IN OUT EFI_PHYSICAL_ADDRESS *Image, OUT UINTN *ImageSize ) { EFI_STATUS Status; EFI_HANDLE Dhcp4ChildHandle; EFI_DHCP4_PROTOCOL *Dhcp4; BOOLEAN Dhcp4ToStop; EFI_HANDLE Mtftp4ChildHandle; EFI_MTFTP4_PROTOCOL *Mtftp4; DHCP4_OPTION ParaList; EFI_DHCP4_PACKET_OPTION *OptionList[2]; EFI_DHCP4_CONFIG_DATA Dhcp4CfgData; EFI_DHCP4_MODE_DATA Dhcp4Mode; EFI_MTFTP4_CONFIG_DATA Mtftp4CfgData; IPv4_DEVICE_PATH *IPv4DevicePathNode; FILEPATH_DEVICE_PATH *FilePathDevicePathNode; CHAR8 *AsciiFilePath; EFI_MTFTP4_TOKEN Mtftp4Token; UINT64 FileSize; UINT64 TftpBufferSize; BDS_TFTP_CONTEXT *TftpContext; ASSERT(IS_DEVICE_PATH_NODE (RemainingDevicePath, MESSAGING_DEVICE_PATH, MSG_IPv4_DP)); IPv4DevicePathNode = (IPv4_DEVICE_PATH*)RemainingDevicePath; Dhcp4ChildHandle = NULL; Dhcp4 = NULL; Dhcp4ToStop = FALSE; Mtftp4ChildHandle = NULL; Mtftp4 = NULL; AsciiFilePath = NULL; TftpContext = NULL; if (!IPv4DevicePathNode->StaticIpAddress) { // // Using the DHCP4 Service Binding Protocol, create a child handle of the DHCP4 service and // install the DHCP4 protocol on it. Then, open the DHCP protocol. // Status = NetLibCreateServiceChild ( ControllerHandle, gImageHandle, &gEfiDhcp4ServiceBindingProtocolGuid, &Dhcp4ChildHandle ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( Dhcp4ChildHandle, &gEfiDhcp4ProtocolGuid, (VOID **) &Dhcp4, gImageHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); } if (EFI_ERROR (Status)) { Print (L"Unable to open DHCP4 protocol\n"); goto Error; } } // // Using the MTFTP4 Service Binding Protocol, create a child handle of the MTFTP4 service and // install the MTFTP4 protocol on it. Then, open the MTFTP4 protocol. // Status = NetLibCreateServiceChild ( ControllerHandle, gImageHandle, &gEfiMtftp4ServiceBindingProtocolGuid, &Mtftp4ChildHandle ); if (!EFI_ERROR (Status)) { Status = gBS->OpenProtocol ( Mtftp4ChildHandle, &gEfiMtftp4ProtocolGuid, (VOID **) &Mtftp4, gImageHandle, ControllerHandle, EFI_OPEN_PROTOCOL_BY_DRIVER ); } if (EFI_ERROR (Status)) { Print (L"Unable to open MTFTP4 protocol\n"); goto Error; } if (!IPv4DevicePathNode->StaticIpAddress) { // // Configure the DHCP4, all default settings. It is acceptable for the configuration to // fail if the return code is equal to EFI_ACCESS_DENIED which means that the configuration // has been done by another instance of the DHCP4 protocol or that the DHCP configuration // process has been started but is not completed yet. // ZeroMem (&Dhcp4CfgData, sizeof (EFI_DHCP4_CONFIG_DATA)); ParaList.Head.OpCode = DHCP_TAG_PARA_LIST; ParaList.Head.Length = 2; ParaList.Head.Data[0] = DHCP_TAG_NETMASK; ParaList.Route = DHCP_TAG_ROUTER; OptionList[0] = &ParaList.Head; Dhcp4CfgData.OptionCount = 1; Dhcp4CfgData.OptionList = OptionList; Status = Dhcp4->Configure (Dhcp4, &Dhcp4CfgData); if (EFI_ERROR (Status)) { if (Status != EFI_ACCESS_DENIED) { Print (L"Error while configuring the DHCP4 protocol\n"); goto Error; } } // // Start the DHCP configuration. This may have already been done thus do not leave in error // if the return code is EFI_ALREADY_STARTED. // Status = Dhcp4->Start (Dhcp4, NULL); if (EFI_ERROR (Status)) { if (Status != EFI_ALREADY_STARTED) { Print (L"DHCP configuration failed\n"); goto Error; } } else { Dhcp4ToStop = TRUE; } Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode); if (EFI_ERROR (Status)) { goto Error; } if (Dhcp4Mode.State != Dhcp4Bound) { Status = EFI_TIMEOUT; Print (L"DHCP configuration failed\n"); goto Error; } } // // Configure the TFTP4 protocol // ZeroMem (&Mtftp4CfgData, sizeof (EFI_MTFTP4_CONFIG_DATA)); Mtftp4CfgData.UseDefaultSetting = FALSE; Mtftp4CfgData.TimeoutValue = 4; Mtftp4CfgData.TryCount = 6; if (IPv4DevicePathNode->StaticIpAddress) { CopyMem (&Mtftp4CfgData.StationIp , &IPv4DevicePathNode->LocalIpAddress, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Mtftp4CfgData.SubnetMask, &IPv4DevicePathNode->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Mtftp4CfgData.GatewayIp , &IPv4DevicePathNode->GatewayIpAddress, sizeof (EFI_IPv4_ADDRESS)); } else { CopyMem (&Mtftp4CfgData.StationIp , &Dhcp4Mode.ClientAddress, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Mtftp4CfgData.SubnetMask, &Dhcp4Mode.SubnetMask , sizeof (EFI_IPv4_ADDRESS)); CopyMem (&Mtftp4CfgData.GatewayIp , &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS)); } CopyMem (&Mtftp4CfgData.ServerIp , &IPv4DevicePathNode->RemoteIpAddress, sizeof (EFI_IPv4_ADDRESS)); Status = Mtftp4->Configure (Mtftp4, &Mtftp4CfgData); if (EFI_ERROR (Status)) { Print (L"Error while configuring the MTFTP4 protocol\n"); goto Error; } // // Convert the Unicode path of the file to Ascii // FilePathDevicePathNode = (FILEPATH_DEVICE_PATH*)(IPv4DevicePathNode + 1); AsciiFilePath = AllocatePool ((StrLen (FilePathDevicePathNode->PathName) + 1) * sizeof (CHAR8)); if (AsciiFilePath == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } UnicodeStrToAsciiStr (FilePathDevicePathNode->PathName, AsciiFilePath); // // Try to get the size of the file in bytes from the server. If it fails, // start with a 8MB buffer to download the file. // FileSize = 0; if (Mtftp4GetFileSize (Mtftp4, AsciiFilePath, &FileSize) == EFI_SUCCESS) { TftpBufferSize = FileSize; } else { TftpBufferSize = SIZE_8MB; } TftpContext = AllocatePool (sizeof (BDS_TFTP_CONTEXT)); if (TftpContext == NULL) { Status = EFI_OUT_OF_RESOURCES; goto Error; } TftpContext->FileSize = FileSize; for (; TftpBufferSize <= FixedPcdGet32 (PcdMaxTftpFileSize); TftpBufferSize = (TftpBufferSize + SIZE_8MB) & (~(SIZE_8MB-1))) { // // Allocate a buffer to hold the whole file. // Status = gBS->AllocatePages ( Type, EfiBootServicesCode, EFI_SIZE_TO_PAGES (TftpBufferSize), Image ); if (EFI_ERROR (Status)) { Print (L"Failed to allocate space for image\n"); goto Error; } TftpContext->DownloadedNbOfBytes = 0; TftpContext->LastReportedNbOfBytes = 0; ZeroMem (&Mtftp4Token, sizeof (EFI_MTFTP4_TOKEN)); Mtftp4Token.Filename = (UINT8*)AsciiFilePath; Mtftp4Token.BufferSize = TftpBufferSize; Mtftp4Token.Buffer = (VOID *)(UINTN)*Image; Mtftp4Token.CheckPacket = Mtftp4CheckPacket; Mtftp4Token.Context = (VOID*)TftpContext; Print (L"Downloading the file <%s> from the TFTP server\n", FilePathDevicePathNode->PathName); Status = Mtftp4->ReadFile (Mtftp4, &Mtftp4Token); Print (L"\n"); if (EFI_ERROR (Status)) { gBS->FreePages (*Image, EFI_SIZE_TO_PAGES (TftpBufferSize)); if (Status == EFI_BUFFER_TOO_SMALL) { Print (L"Downloading failed, file larger than expected.\n"); continue; } else { goto Error; } } *ImageSize = Mtftp4Token.BufferSize; break; } Error: if (Dhcp4ChildHandle != NULL) { if (Dhcp4 != NULL) { if (Dhcp4ToStop) { Dhcp4->Stop (Dhcp4); } gBS->CloseProtocol ( Dhcp4ChildHandle, &gEfiDhcp4ProtocolGuid, gImageHandle, ControllerHandle ); } NetLibDestroyServiceChild ( ControllerHandle, gImageHandle, &gEfiDhcp4ServiceBindingProtocolGuid, Dhcp4ChildHandle ); } if (Mtftp4ChildHandle != NULL) { if (Mtftp4 != NULL) { if (AsciiFilePath != NULL) { FreePool (AsciiFilePath); } if (TftpContext != NULL) { FreePool (TftpContext); } gBS->CloseProtocol ( Mtftp4ChildHandle, &gEfiMtftp4ProtocolGuid, gImageHandle, ControllerHandle ); } NetLibDestroyServiceChild ( ControllerHandle, gImageHandle, &gEfiMtftp4ServiceBindingProtocolGuid, Mtftp4ChildHandle ); } if (EFI_ERROR (Status)) { Print (L"Failed to download the file - Error=%r\n", Status); } return Status; }
STATIC VOID ArpCleanService ( IN ARP_SERVICE_DATA *ArpService ) /*++ Routine Description: Clean the arp service context data. Arguments: ArpService - Pointer to the buffer containing the arp service context data. Returns: None. --*/ { NET_CHECK_SIGNATURE (ArpService, ARP_SERVICE_DATA_SIGNATURE); if (ArpService->PeriodicTimer != NULL) { // // Cancle and close the PeriodicTimer. // gBS->SetTimer (ArpService->PeriodicTimer, TimerCancel, 0); gBS->CloseEvent (ArpService->PeriodicTimer); } if (ArpService->RxToken.Event != NULL) { // // Cancle the RxToken and close the event in the RxToken. // ArpService->Mnp->Cancel (ArpService->Mnp, NULL); gBS->CloseEvent (ArpService->RxToken.Event); } if (ArpService->Mnp != NULL) { // // Reset the Mnp child and close the Mnp protocol. // ArpService->Mnp->Configure (ArpService->Mnp, NULL); gBS->CloseProtocol ( ArpService->MnpChildHandle, &gEfiManagedNetworkProtocolGuid, ArpService->ImageHandle, ArpService->ControllerHandle ); } if (ArpService->MnpChildHandle != NULL) { // // Destroy the mnp child. // NetLibDestroyServiceChild( ArpService->ControllerHandle, ArpService->ImageHandle, &gEfiManagedNetworkServiceBindingProtocolGuid, ArpService->MnpChildHandle ); } }
/** Destroy the socket. @param[in] TcpIo The TcpIo which wraps the socket to be destroyed. **/ VOID EFIAPI TcpIoDestroySocket ( IN TCP_IO *TcpIo ) { EFI_EVENT Event; EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP6_PROTOCOL *Tcp6; UINT8 TcpVersion; EFI_GUID *ServiceBindingGuid; EFI_GUID *ProtocolGuid; EFI_HANDLE ChildHandle; if (TcpIo == NULL) { return ; } TcpVersion = TcpIo->TcpVersion; if ((TcpVersion != TCP_VERSION_4) && (TcpVersion != TCP_VERSION_6)) { return ; } Event = TcpIo->ConnToken.Tcp4Token.CompletionToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = TcpIo->ListenToken.Tcp4Token.CompletionToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = TcpIo->TxToken.Tcp4Token.CompletionToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = TcpIo->RxToken.Tcp4Token.CompletionToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } Event = TcpIo->CloseToken.Tcp4Token.CompletionToken.Event; if (Event != NULL) { gBS->CloseEvent (Event); } if (TcpIo->RxToken.Tcp4Token.Packet.RxData != NULL) { FreePool (TcpIo->RxToken.Tcp4Token.Packet.RxData); } Tcp4 = NULL; Tcp6 = NULL; if (TcpVersion == TCP_VERSION_4) { ServiceBindingGuid = &gEfiTcp4ServiceBindingProtocolGuid; ProtocolGuid = &gEfiTcp4ProtocolGuid; Tcp4 = TcpIo->Tcp.Tcp4; if (Tcp4 != NULL) { Tcp4->Configure (Tcp4, NULL); } } else { ServiceBindingGuid = &gEfiTcp6ServiceBindingProtocolGuid; ProtocolGuid = &gEfiTcp6ProtocolGuid; Tcp6 = TcpIo->Tcp.Tcp6; if (Tcp6 != NULL) { Tcp6->Configure (Tcp6, NULL); } } if ((Tcp4 != NULL) || (Tcp6 != NULL)) { gBS->CloseProtocol ( TcpIo->Handle, ProtocolGuid, TcpIo->Image, TcpIo->Controller ); } ChildHandle = NULL; if (TcpIo->IsListenDone) { if (TcpVersion == TCP_VERSION_4) { Tcp4 = TcpIo->NewTcp.Tcp4; if (Tcp4 != NULL) { Tcp4->Configure (Tcp4, NULL); ChildHandle = TcpIo->ListenToken.Tcp4Token.NewChildHandle; } } else { Tcp6 = TcpIo->NewTcp.Tcp6; if (Tcp6 != NULL) { Tcp6->Configure (Tcp6, NULL); ChildHandle = TcpIo->ListenToken.Tcp6Token.NewChildHandle; } } if (ChildHandle != NULL) { gBS->CloseProtocol ( ChildHandle, ProtocolGuid, TcpIo->Image, TcpIo->Controller ); } } NetLibDestroyServiceChild ( TcpIo->Controller, TcpIo->Image, ServiceBindingGuid, TcpIo->Handle ); }
/** Retrieve the host address using the EFI_DNS4_PROTOCOL. @param[in] Image The handle of the driver image. @param[in] Controller The handle of the controller. @param[in, out] NvData The Session config data structure. @retval EFI_SUCCESS Operation succeeded. @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources. @retval EFI_DEVICE_ERROR An unexpected network error occurred. @retval Others Other errors as indicated. **/ EFI_STATUS IScsiDns4 ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN OUT ISCSI_SESSION_CONFIG_NVDATA *NvData ) { EFI_STATUS Status; EFI_DNS4_PROTOCOL *Dns4; EFI_DNS4_CONFIG_DATA Dns4CfgData; EFI_DNS4_COMPLETION_TOKEN Token; BOOLEAN IsDone; EFI_HANDLE Dns4Handle; EFI_IP4_CONFIG2_PROTOCOL *Ip4Config2; EFI_IPv4_ADDRESS *DnsServerList; UINTN DnsServerListCount; UINTN DataSize; CHAR16 *HostName; DnsServerList = NULL; DnsServerListCount = 0; Dns4Handle = NULL; Dns4 = NULL; ZeroMem (&Token, sizeof (EFI_DNS4_COMPLETION_TOKEN)); // // Get DNS server list from EFI IPv4 Configuration II protocol. // Status = gBS->HandleProtocol (Controller, &gEfiIp4Config2ProtocolGuid, (VOID **) &Ip4Config2); if (!EFI_ERROR (Status)) { // // Get the required size. // DataSize = 0; Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, NULL); if (Status == EFI_BUFFER_TOO_SMALL) { DnsServerList = AllocatePool (DataSize); if (DnsServerList == NULL) { return EFI_OUT_OF_RESOURCES; } Status = Ip4Config2->GetData (Ip4Config2, Ip4Config2DataTypeDnsServer, &DataSize, DnsServerList); if (EFI_ERROR (Status)) { FreePool (DnsServerList); DnsServerList = NULL; } else { DnsServerListCount = DataSize / sizeof (EFI_IPv4_ADDRESS); } } } // // Create a DNS child instance and get the protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiDns4ServiceBindingProtocolGuid, &Dns4Handle ); if (EFI_ERROR (Status)) { goto Exit; } Status = gBS->OpenProtocol ( Dns4Handle, &gEfiDns4ProtocolGuid, (VOID **) &Dns4, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto Exit; } // // Configure DNS4 instance for the DNS server address and protocol. // ZeroMem (&Dns4CfgData, sizeof (Dns4CfgData)); Dns4CfgData.DnsServerListCount = DnsServerListCount; Dns4CfgData.DnsServerList = DnsServerList; Dns4CfgData.EnableDnsCache = TRUE; IP4_COPY_ADDRESS (&Dns4CfgData.StationIp, &NvData->LocalIp); IP4_COPY_ADDRESS (&Dns4CfgData.SubnetMask, &NvData->SubnetMask); Dns4CfgData.Protocol = EFI_IP_PROTO_UDP; Status = Dns4->Configure ( Dns4, &Dns4CfgData ); if (EFI_ERROR (Status)) { goto Exit; } // // Create event to set the is done flag when name resolution is finished. // ZeroMem (&Token, sizeof (Token)); Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, IScsiCommonNotify, &IsDone, &Token.Event ); if (EFI_ERROR (Status)) { goto Exit; } // // Start asynchronous name resolution. // Token.Status = EFI_NOT_READY; IsDone = FALSE; HostName = (CHAR16 *) AllocateZeroPool (ISCSI_NAME_MAX_SIZE); if (HostName == NULL) { return EFI_OUT_OF_RESOURCES; } AsciiStrToUnicodeStrS ( NvData->TargetUrl, HostName, ISCSI_NAME_MAX_SIZE ); Status = Dns4->HostNameToIp (Dns4, HostName, &Token); if (EFI_ERROR (Status)) { goto Exit; } while (!IsDone) { Dns4->Poll (Dns4); } // // Name resolution is done, check result. // Status = Token.Status; if (!EFI_ERROR (Status)) { if (Token.RspData.H2AData == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } if (Token.RspData.H2AData->IpCount == 0 || Token.RspData.H2AData->IpList == NULL) { Status = EFI_DEVICE_ERROR; goto Exit; } // // We just return the first IP address from DNS protocol. // IP4_COPY_ADDRESS (&NvData->TargetIp.v4, Token.RspData.H2AData->IpList); Status = EFI_SUCCESS; } Exit: if (Token.Event != NULL) { gBS->CloseEvent (Token.Event); } if (Token.RspData.H2AData != NULL) { if (Token.RspData.H2AData->IpList != NULL) { FreePool (Token.RspData.H2AData->IpList); } FreePool (Token.RspData.H2AData); } if (Dns4 != NULL) { Dns4->Configure (Dns4, NULL); gBS->CloseProtocol ( Dns4Handle, &gEfiDns4ProtocolGuid, Image, Controller ); } if (Dns4Handle != NULL) { NetLibDestroyServiceChild ( Controller, Image, &gEfiDns4ServiceBindingProtocolGuid, Dns4Handle ); } return Status; }
/** Create a TCP socket with the specified configuration data. @param[in] Image The handle of the driver image. @param[in] Controller The handle of the controller. @param[in] ConfigData The Tcp4 configuration data. @param[in] Tcp4Io The Tcp4Io. @retval EFI_SUCCESS The TCP socket is created and configured. @retval Others Failed to create the TCP socket or configure it. **/ EFI_STATUS Tcp4IoCreateSocket ( IN EFI_HANDLE Image, IN EFI_HANDLE Controller, IN TCP4_IO_CONFIG_DATA *ConfigData, IN TCP4_IO *Tcp4Io ) { EFI_STATUS Status; EFI_TCP4_PROTOCOL *Tcp4; EFI_TCP4_CONFIG_DATA Tcp4ConfigData; EFI_TCP4_OPTION ControlOption; EFI_TCP4_ACCESS_POINT *AccessPoint; Tcp4Io->Handle = NULL; Tcp4Io->ConnToken.CompletionToken.Event = NULL; Tcp4Io->TxToken.CompletionToken.Event = NULL; Tcp4Io->RxToken.CompletionToken.Event = NULL; Tcp4Io->CloseToken.CompletionToken.Event = NULL; Tcp4 = NULL; // // Create the TCP4 child instance and get the TCP4 protocol. // Status = NetLibCreateServiceChild ( Controller, Image, &gEfiTcp4ServiceBindingProtocolGuid, &Tcp4Io->Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Tcp4Io->Handle, &gEfiTcp4ProtocolGuid, (VOID **)&Tcp4Io->Tcp4, Image, Controller, EFI_OPEN_PROTOCOL_BY_DRIVER ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Tcp4Io->Image = Image; Tcp4Io->Controller = Controller; Tcp4 = Tcp4Io->Tcp4; // // Set the configuration parameters. // ControlOption.ReceiveBufferSize = 0x200000; ControlOption.SendBufferSize = 0x200000; ControlOption.MaxSynBackLog = 0; ControlOption.ConnectionTimeout = 0; ControlOption.DataRetries = 6; ControlOption.FinTimeout = 0; ControlOption.TimeWaitTimeout = 0; ControlOption.KeepAliveProbes = 4; ControlOption.KeepAliveTime = 0; ControlOption.KeepAliveInterval = 0; ControlOption.EnableNagle = FALSE; ControlOption.EnableTimeStamp = FALSE; ControlOption.EnableWindowScaling = TRUE; ControlOption.EnableSelectiveAck = FALSE; ControlOption.EnablePathMtuDiscovery = FALSE; Tcp4ConfigData.TypeOfService = 8; Tcp4ConfigData.TimeToLive = 255; Tcp4ConfigData.ControlOption = &ControlOption; AccessPoint = &Tcp4ConfigData.AccessPoint; AccessPoint->UseDefaultAddress = FALSE; AccessPoint->StationPort = 0; AccessPoint->RemotePort = ConfigData->RemotePort; AccessPoint->ActiveFlag = TRUE; CopyMem (&AccessPoint->StationAddress, &ConfigData->LocalIp, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&AccessPoint->SubnetMask, &ConfigData->SubnetMask, sizeof (EFI_IPv4_ADDRESS)); CopyMem (&AccessPoint->RemoteAddress, &ConfigData->RemoteIp, sizeof (EFI_IPv4_ADDRESS)); // // Configure the TCP4 protocol. // Status = Tcp4->Configure (Tcp4, &Tcp4ConfigData); if (EFI_ERROR (Status)) { goto ON_ERROR; } if (!EFI_IP4_EQUAL (&ConfigData->Gateway, &mZeroIp4Addr)) { // // the gateway is not zero, add the default route by hand // Status = Tcp4->Routes (Tcp4, FALSE, &mZeroIp4Addr, &mZeroIp4Addr, &ConfigData->Gateway); if (EFI_ERROR (Status)) { goto ON_ERROR; } } // // Create events for variuos asynchronous operations. // Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, Tcp4IoCommonNotify, &Tcp4Io->IsConnDone, &Tcp4Io->ConnToken.CompletionToken.Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, Tcp4IoCommonNotify, &Tcp4Io->IsTxDone, &Tcp4Io->TxToken.CompletionToken.Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, Tcp4IoCommonNotify, &Tcp4Io->IsRxDone, &Tcp4Io->RxToken.CompletionToken.Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL, TPL_NOTIFY, Tcp4IoCommonNotify, &Tcp4Io->IsCloseDone, &Tcp4Io->CloseToken.CompletionToken.Event ); if (EFI_ERROR (Status)) { goto ON_ERROR; } Tcp4Io->IsTxDone = FALSE; Tcp4Io->IsRxDone = FALSE; return EFI_SUCCESS; ON_ERROR: if (Tcp4Io->RxToken.CompletionToken.Event != NULL) { gBS->CloseEvent (Tcp4Io->RxToken.CompletionToken.Event); } if (Tcp4Io->TxToken.CompletionToken.Event != NULL) { gBS->CloseEvent (Tcp4Io->TxToken.CompletionToken.Event); } if (Tcp4Io->ConnToken.CompletionToken.Event != NULL) { gBS->CloseEvent (Tcp4Io->ConnToken.CompletionToken.Event); } if (Tcp4 != NULL) { Tcp4->Configure (Tcp4, NULL); gBS->CloseProtocol ( Tcp4Io->Handle, &gEfiTcp4ProtocolGuid, Image, Controller ); } NetLibDestroyServiceChild ( Controller, Image, &gEfiTcp4ServiceBindingProtocolGuid, Tcp4Io->Handle ); return Status; }
/** Destroy the opened instances based on IPv6. @param[in] This Pointer to the EFI_DRIVER_BINDING_PROTOCOL. @param[in] Private Pointer to PXEBC_PRIVATE_DATA. **/ VOID PxeBcDestroyIp6Children ( IN EFI_DRIVER_BINDING_PROTOCOL *This, IN PXEBC_PRIVATE_DATA *Private ) { ASSERT(Private != NULL); if (Private->Ip6Child != NULL) { // // Close Ip6 for Ip6->Ip6Config and destroy the instance. // gBS->CloseProtocol ( Private->Ip6Child, &gEfiIp6ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiIp6ServiceBindingProtocolGuid, Private->Ip6Child ); } if (Private->Udp6WriteChild != NULL) { // // Close Udp6 for PxeBc->UdpWrite and destroy the instance. // gBS->CloseProtocol ( Private->Udp6WriteChild, &gEfiUdp6ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiUdp6ServiceBindingProtocolGuid, Private->Udp6WriteChild ); } if (Private->Udp6ReadChild != NULL) { // // Close Udp6 for PxeBc->UdpRead and destroy the instance. // gBS->CloseProtocol ( Private->Udp6ReadChild, &gEfiUdp6ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiUdp6ServiceBindingProtocolGuid, Private->Udp6ReadChild ); } if (Private->Mtftp6Child != NULL) { // // Close Mtftp6 for PxeBc->Mtftp and destroy the instance. // gBS->CloseProtocol ( Private->Mtftp6Child, &gEfiMtftp6ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiMtftp6ServiceBindingProtocolGuid, Private->Mtftp6Child ); } if (Private->Dhcp6Child != NULL) { // // Close Dhcp6 for PxeBc->Dhcp and destroy the instance. // gBS->CloseProtocol ( Private->Dhcp6Child, &gEfiDhcp6ProtocolGuid, This->DriverBindingHandle, Private->Controller ); NetLibDestroyServiceChild ( Private->Controller, This->DriverBindingHandle, &gEfiDhcp6ServiceBindingProtocolGuid, Private->Dhcp6Child ); } if (Private->Ip6Nic != NULL) { // // Close PxeBcPrivate from the parent Nic handle and destroy the virtual handle. // gBS->CloseProtocol ( Private->Controller, &gEfiCallerIdGuid, This->DriverBindingHandle, Private->Ip6Nic->Controller ); gBS->UninstallMultipleProtocolInterfaces ( Private->Ip6Nic->Controller, &gEfiDevicePathProtocolGuid, Private->Ip6Nic->DevicePath, &gEfiLoadFileProtocolGuid, &Private->Ip6Nic->LoadFile, &gEfiPxeBaseCodeProtocolGuid, &Private->PxeBc, NULL ); if (Private->Snp != NULL) { // // Close SNP from the child virtual handle // gBS->CloseProtocol ( Private->Ip6Nic->Controller, &gEfiSimpleNetworkProtocolGuid, This->DriverBindingHandle, Private->Ip6Nic->Controller ); gBS->UninstallProtocolInterface ( Private->Ip6Nic->Controller, &gEfiSimpleNetworkProtocolGuid, Private->Snp ); } FreePool (Private->Ip6Nic); } Private->Ip6Child = NULL; Private->Udp6WriteChild = NULL; Private->Udp6ReadChild = NULL; Private->Mtftp6Child = NULL; Private->Dhcp6Child = NULL; Private->Ip6Nic = NULL; Private->Mode.Ipv6Available = FALSE; }
/** Create an IP child, use it to start the auto configuration, then destroy it. @param[in] Controller The controller which has the service installed. @param[in] Image The image handle used to open service. @retval EFI_SUCCESS The configuration is done. @retval Others Other errors as indicated. **/ EFI_STATUS EFIAPI DnsStartIp4( IN EFI_HANDLE Controller, IN EFI_HANDLE Image ) { EFI_IP4_PROTOCOL *Ip4; EFI_HANDLE Ip4Handle; EFI_EVENT TimerToGetMap; EFI_IP4_CONFIG_DATA Ip4ConfigData; EFI_IP4_MODE_DATA Ip4Mode; EFI_STATUS Status; BOOLEAN Timeout; // // Get the Ip4ServiceBinding Protocol // Ip4Handle = NULL; Ip4 = NULL; TimerToGetMap = NULL; Timeout = FALSE; Status = NetLibCreateServiceChild ( Controller, Image, &gEfiIp4ServiceBindingProtocolGuid, &Ip4Handle ); if (EFI_ERROR (Status)) { return Status; } Status = gBS->OpenProtocol ( Ip4Handle, &gEfiIp4ProtocolGuid, (VOID **) &Ip4, Controller, Image, EFI_OPEN_PROTOCOL_GET_PROTOCOL ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Ip4ConfigData.DefaultProtocol = EFI_IP_PROTO_ICMP; Ip4ConfigData.AcceptAnyProtocol = FALSE; Ip4ConfigData.AcceptIcmpErrors = FALSE; Ip4ConfigData.AcceptBroadcast = FALSE; Ip4ConfigData.AcceptPromiscuous = FALSE; Ip4ConfigData.UseDefaultAddress = TRUE; ZeroMem (&Ip4ConfigData.StationAddress, sizeof (EFI_IPv4_ADDRESS)); ZeroMem (&Ip4ConfigData.SubnetMask, sizeof (EFI_IPv4_ADDRESS)); Ip4ConfigData.TypeOfService = 0; Ip4ConfigData.TimeToLive = 1; Ip4ConfigData.DoNotFragment = FALSE; Ip4ConfigData.RawData = FALSE; Ip4ConfigData.ReceiveTimeout = 0; Ip4ConfigData.TransmitTimeout = 0; Status = Ip4->Configure (Ip4, &Ip4ConfigData); if (Status == EFI_NO_MAPPING) { Status = gBS->CreateEvent ( EVT_NOTIFY_SIGNAL | EVT_TIMER, TPL_CALLBACK, TimeoutToGetMap, &Timeout, &TimerToGetMap ); if (EFI_ERROR (Status)) { goto ON_EXIT; } Status = gBS->SetTimer ( TimerToGetMap, TimerRelative, MultU64x32 (10000000, 5) ); if (EFI_ERROR (Status)) { goto ON_EXIT; } while (!Timeout) { Ip4->Poll (Ip4); if (!EFI_ERROR (Ip4->GetModeData (Ip4, &Ip4Mode, NULL, NULL)) && Ip4Mode.IsConfigured) { break; } } if (Timeout) { Status = EFI_DEVICE_ERROR; } } ON_EXIT: if (TimerToGetMap != NULL) { gBS->SetTimer (TimerToGetMap, TimerCancel, 0); gBS->CloseEvent (TimerToGetMap); } NetLibDestroyServiceChild ( Controller, Image, &gEfiIp4ServiceBindingProtocolGuid, Ip4Handle ); return Status; }