diff --git a/FatPkg/FatPei/AAA.c b/FatPkg/FatPei/AAA.c new file mode 100644 index 000000000000..ba62147db61b --- /dev/null +++ b/FatPkg/FatPei/AAA.c @@ -0,0 +1,15 @@ +/** @file + General purpose supporting routines for FAT recovery PEIM + +Copyright (c) 2006 - 2018, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: MIT + +**/ + +#include "FatLitePeim.h" + + +#define CHAR_FAT_VALID 0x01 + + diff --git a/FatPkg/FatPei/BBB.h b/FatPkg/FatPei/BBB.h new file mode 100644 index 000000000000..11a7257903ad --- /dev/null +++ b/FatPkg/FatPei/BBB.h @@ -0,0 +1,12 @@ +/** @file + FAT format data structures + +Copyright (c) 2006 - 2017, Intel Corporation. All rights reserved.
+ +SPDX-License-Identifier: + +**/ + +#ifndef _FAT_FMT_H_ +#define _FAT_FMT_H_ + diff --git a/FatPkg/FatPei/CCC.c b/FatPkg/FatPei/CCC.c new file mode 100644 index 000000000000..2ed7a054aec1 --- /dev/null +++ b/FatPkg/FatPei/CCC.c @@ -0,0 +1,8 @@ +/** @file + FAT recovery PEIM entry point, Ppi Functions and FAT Api functions. + +Copyright (c) 2006 - 2019, Intel Corporation. All rights reserved.
+ + +**/ + diff --git a/MdeModulePkg/Library/AuthVariableLibNull/find.inf b/MdeModulePkg/Library/AuthVariableLibNull/find.inf new file mode 100644 index 000000000000..e2c9dafb6ed4 --- /dev/null +++ b/MdeModulePkg/Library/AuthVariableLibNull/find.inf @@ -0,0 +1,71 @@ +/** @file + Implements NULL authenticated variable services. + +Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-3-Clause-Patent + +**/ + +#include +#include + +/** + Initialization for authenticated varibale services. + If this initialization returns error status, other APIs will not work + and expect to be not called then. + + @param[in] AuthVarLibContextIn Pointer to input auth variable lib context. + @param[out] AuthVarLibContextOut Pointer to output auth variable lib context. + + @retval EFI_SUCCESS Function successfully executed. + @retval EFI_INVALID_PARAMETER If AuthVarLibContextIn == NULL or AuthVarLibContextOut == NULL. + @retval EFI_OUT_OF_RESOURCES Fail to allocate enough resource. + @retval EFI_UNSUPPORTED Unsupported to process authenticated variable. + +**/ +EFI_STATUS +EFIAPI +AuthVariableLibInitialize ( + IN AUTH_VAR_LIB_CONTEXT_IN *AuthVarLibContextIn, + OUT AUTH_VAR_LIB_CONTEXT_OUT *AuthVarLibContextOut + ) +{ + // + // Do nothing, just return EFI_UNSUPPORTED. + // + return EFI_UNSUPPORTED; +} + +/** + Process variable with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACCESS set. + + @param[in] VariableName Name of the variable. + @param[in] VendorGuid Variable vendor GUID. + @param[in] Data Data pointer. + @param[in] DataSize Size of Data. + @param[in] Attributes Attribute value of the variable. + + @retval EFI_SUCCESS The firmware has successfully stored the variable and its data as + defined by the Attributes. + @retval EFI_INVALID_PARAMETER Invalid parameter. + @retval EFI_WRITE_PROTECTED Variable is write-protected. + @retval EFI_OUT_OF_RESOURCES There is not enough resource. + @retval EFI_SECURITY_VIOLATION The variable is with EFI_VARIABLE_TIME_BASED_AUTHENTICATED_WRITE_ACESS + set, but the AuthInfo does NOT pass the validation + check carried out by the firmware. + @retval EFI_UNSUPPORTED Unsupported to process authenticated variable. + +**/ +EFI_STATUS +EFIAPI +AuthVariableLibProcessVariable ( + IN CHAR16 *VariableName, + IN EFI_GUID *VendorGuid, + IN VOID *Data, + IN UINTN DataSize, + IN UINT32 Attributes + ) +{ + ASSERT (FALSE); + return EFI_UNSUPPORTED; +} diff --git a/NetworkPkg/DnsDxe/epas.c b/NetworkPkg/DnsDxe/epas.c new file mode 100644 index 000000000000..9ea9d7c8f674 --- /dev/null +++ b/NetworkPkg/DnsDxe/epas.c @@ -0,0 +1,758 @@ +/** @file +Functions implementation related with DHCPv4/v6 for DNS driver. + +Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.
+SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include "DnsImpl.h" + +/** + This function initialize the DHCP4 message instance. + + This function will pad each item of dhcp4 message packet. + + @param Seed Pointer to the message instance of the DHCP4 packet. + @param InterfaceInfo Pointer to the EFI_IP4_CONFIG2_INTERFACE_INFO instance. + +**/ +VOID +DnsInitSeedPacket ( + OUT EFI_DHCP4_PACKET *Seed, + IN EFI_IP4_CONFIG2_INTERFACE_INFO *InterfaceInfo + ) +{ + EFI_DHCP4_HEADER *Header; + + // + // Get IfType and HwAddressSize from SNP mode data. + // + Seed->Size = sizeof (EFI_DHCP4_PACKET); + Seed->Length = sizeof (Seed->Dhcp4); + Header = &Seed->Dhcp4.Header; + ZeroMem (Header, sizeof (EFI_DHCP4_HEADER)); + Header->OpCode = DHCP4_OPCODE_REQUEST; + Header->HwType = InterfaceInfo->IfType; + Header->HwAddrLen = (UINT8) InterfaceInfo->HwAddressSize; + CopyMem (Header->ClientHwAddr, &(InterfaceInfo->HwAddress), Header->HwAddrLen); + + Seed->Dhcp4.Magik = DHCP4_MAGIC; + Seed->Dhcp4.Option[0] = DHCP4_TAG_EOP; +} + +/** + The common notify function. + + @param[in] Event The event signaled. + @param[in] Context The context. + +**/ +VOID +EFIAPI +DhcpCommonNotify ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + if ((Event == NULL) || (Context == NULL)) { + return ; + } + + *((BOOLEAN *) Context) = TRUE; +} + +/** + Parse the ACK to get required information + + @param Dhcp4 The DHCP4 protocol. + @param Packet Packet waiting for parse. + @param DnsServerInfor The required Dns4 server information. + + @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_DEVICE_ERROR Other errors as indicated. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. + +**/ +EFI_STATUS +ParseDhcp4Ack ( + IN EFI_DHCP4_PROTOCOL *Dhcp4, + IN EFI_DHCP4_PACKET *Packet, + IN DNS4_SERVER_INFOR *DnsServerInfor + ) +{ + EFI_STATUS Status; + UINT32 OptionCount; + EFI_DHCP4_PACKET_OPTION **OptionList; + UINT32 ServerCount; + EFI_IPv4_ADDRESS *ServerList; + UINT32 Index; + UINT32 Count; + + ServerCount = 0; + ServerList = NULL; + + OptionCount = 0; + OptionList = NULL; + + Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList); + if (Status != EFI_BUFFER_TOO_SMALL) { + return EFI_DEVICE_ERROR; + } + + OptionList = AllocatePool (OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *)); + if (OptionList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = Dhcp4->Parse (Dhcp4, Packet, &OptionCount, OptionList); + if (EFI_ERROR (Status)) { + gBS->FreePool (OptionList); + return EFI_DEVICE_ERROR; + } + + Status = EFI_NOT_FOUND; + + for (Index = 0; Index < OptionCount; Index++) { + // + // Get DNS server addresses + // + if (OptionList[Index]->OpCode == DHCP4_TAG_DNS_SERVER) { + + if (((OptionList[Index]->Length & 0x3) != 0) || (OptionList[Index]->Length == 0)) { + Status = EFI_DEVICE_ERROR; + break; + } + + ServerCount = OptionList[Index]->Length/4; + ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv4_ADDRESS)); + if (ServerList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + for(Count=0; Count < ServerCount; Count++){ + CopyMem (ServerList + Count, &OptionList[Index]->Data[4 * Count], sizeof (EFI_IPv4_ADDRESS)); + } + + *(DnsServerInfor->ServerCount) = ServerCount; + DnsServerInfor->ServerList = ServerList; + + Status = EFI_SUCCESS; + } + } + + gBS->FreePool (OptionList); + + return Status; +} + +/** + EFI_DHCP6_INFO_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol + instance to intercept events that occurs in the DHCPv6 Information Request + exchange process. + + @param This Pointer to the EFI_DHCP6_PROTOCOL instance that + is used to configure this callback function. + @param Context Pointer to the context that is initialized in + the EFI_DHCP6_PROTOCOL.InfoRequest(). + @param Packet Pointer to Reply packet that has been received. + The EFI DHCPv6 Protocol instance is responsible + for freeing the buffer. + + @retval EFI_SUCCESS The DNS information is got from the DHCP ACK. + @retval EFI_DEVICE_ERROR Other errors as indicated. + @retval EFI_OUT_OF_RESOURCES Failed to allocate memory. +**/ +EFI_STATUS +EFIAPI +ParseDhcp6Ack ( + IN EFI_DHCP6_PROTOCOL *This, + IN VOID *Context, + IN EFI_DHCP6_PACKET *Packet + ) +{ + EFI_STATUS Status; + UINT32 OptionCount; + EFI_DHCP6_PACKET_OPTION **OptionList; + DNS6_SERVER_INFOR *DnsServerInfor; + UINT32 ServerCount; + EFI_IPv6_ADDRESS *ServerList; + UINT32 Index; + UINT32 Count; + + OptionCount = 0; + ServerCount = 0; + ServerList = NULL; + + Status = This->Parse (This, Packet, &OptionCount, NULL); + if (Status != EFI_BUFFER_TOO_SMALL) { + return EFI_DEVICE_ERROR; + } + + OptionList = AllocateZeroPool (OptionCount * sizeof (EFI_DHCP6_PACKET_OPTION *)); + if (OptionList == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = This->Parse (This, Packet, &OptionCount, OptionList); + if (EFI_ERROR (Status)) { + gBS->FreePool (OptionList); + return EFI_DEVICE_ERROR; + } + + DnsServerInfor = (DNS6_SERVER_INFOR *) Context; + + for (Index = 0; Index < OptionCount; Index++) { + OptionList[Index]->OpCode = NTOHS (OptionList[Index]->OpCode); + OptionList[Index]->OpLen = NTOHS (OptionList[Index]->OpLen); + + // + // Get DNS server addresses from this reply packet. + // + if (OptionList[Index]->OpCode == DHCP6_TAG_DNS_SERVER) { + + if (((OptionList[Index]->OpLen & 0xf) != 0) || (OptionList[Index]->OpLen == 0)) { + Status = EFI_DEVICE_ERROR; + gBS->FreePool (OptionList); + return Status; + } + + ServerCount = OptionList[Index]->OpLen/16; + ServerList = AllocatePool (ServerCount * sizeof (EFI_IPv6_ADDRESS)); + if (ServerList == NULL) { + gBS->FreePool (OptionList); + return EFI_OUT_OF_RESOURCES; + } + + for(Count=0; Count < ServerCount; Count++){ + CopyMem (ServerList + Count, &OptionList[Index]->Data[16 * Count], sizeof (EFI_IPv6_ADDRESS)); + } + + *(DnsServerInfor->ServerCount) = ServerCount; + DnsServerInfor->ServerList = ServerList; + } + } + + gBS->FreePool (OptionList); + + 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; + +} +