EFI_EVENT TimeOutEvt;\r
EFI_EVENT MappedEvt;\r
EFI_STATUS Status;\r
+ UINT64 DadTriggerTime;\r
+ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;\r
\r
Status = EFI_SUCCESS;\r
TimeOutEvt = NULL;\r
goto ON_EXIT;\r
}\r
\r
+ //\r
+ // Get Duplicate Address Detection Transmits count.\r
+ //\r
+ DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+ &DataSize,\r
+ &DadXmits\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto ON_EXIT;\r
+ }\r
+\r
//\r
// Create a timer as setting address timeout event since DAD in IP6 driver.\r
//\r
// Start the 5 secondes timer to wait for setting address.\r
//\r
Status = EFI_NO_MAPPING;\r
- gBS->SetTimer (TimeOutEvt, TimerRelative, PXEBC_DHCP6_MAPPING_TIMEOUT);\r
+ DadTriggerTime = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;\r
+ gBS->SetTimer (TimeOutEvt, TimerRelative, DadTriggerTime);\r
\r
while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {\r
Ip6->Poll (Ip6);\r
UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE];\r
UINT32 OptCount;\r
EFI_STATUS Status;\r
+ EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;\r
+ EFI_STATUS TimerStatus;\r
+ EFI_EVENT Timer;\r
+ UINT64 GetMappingTimeOut;\r
+ UINTN DataSize;\r
+ EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;\r
\r
Status = EFI_SUCCESS;\r
PxeMode = Private->PxeBc.Mode;\r
+ Ip6Cfg = Private->Ip6Cfg;\r
+ Timer = NULL;\r
\r
//\r
// Build option list for the request packet.\r
// Configure the DHCPv6 instance for PXE boot.\r
//\r
Status = Dhcp6->Configure (Dhcp6, &Config);\r
+ FreePool (Retransmit);\r
if (EFI_ERROR (Status)) {\r
- FreePool (Retransmit);\r
return Status;\r
}\r
\r
// Start DHCPv6 S.A.R.R. process to acquire IPv6 address.\r
//\r
Status = Dhcp6->Start (Dhcp6);\r
+ if (Status == EFI_NO_MAPPING) {\r
+ //\r
+ // IP6 Linklocal address is not available for use, so stop current Dhcp process\r
+ // and wait for duplicate address detection to finish.\r
+ //\r
+ Dhcp6->Stop (Dhcp6);\r
+\r
+ //\r
+ // Get Duplicate Address Detection Transmits count.\r
+ //\r
+ DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);\r
+ Status = Ip6Cfg->GetData (\r
+ Ip6Cfg,\r
+ Ip6ConfigDataTypeDupAddrDetectTransmits,\r
+ &DataSize,\r
+ &DadXmits\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ Dhcp6->Configure (Dhcp6, NULL);\r
+ return Status;\r
+ }\r
+\r
+ Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);\r
+ if (EFI_ERROR (Status)) {\r
+ Dhcp6->Configure (Dhcp6, NULL);\r
+ return Status;\r
+ }\r
+\r
+ GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;\r
+ Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);\r
+ if (EFI_ERROR (Status)) {\r
+ gBS->CloseEvent (Timer);\r
+ Dhcp6->Configure (Dhcp6, NULL);\r
+ return Status;\r
+ }\r
+\r
+ do {\r
+ \r
+ TimerStatus = gBS->CheckEvent (Timer);\r
+ if (!EFI_ERROR (TimerStatus)) {\r
+ Status = Dhcp6->Start (Dhcp6);\r
+ }\r
+ } while (TimerStatus == EFI_NOT_READY);\r
+ \r
+ gBS->CloseEvent (Timer);\r
+ }\r
if (EFI_ERROR (Status)) {\r
if (Status == EFI_ICMP_ERROR) {\r
PxeMode->IcmpErrorReceived = TRUE;\r