PxeBcDhcp6.c 70 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187118811891190119111921193119411951196119711981199120012011202120312041205120612071208120912101211121212131214121512161217121812191220122112221223122412251226122712281229123012311232123312341235123612371238123912401241124212431244124512461247124812491250125112521253125412551256125712581259126012611262126312641265126612671268126912701271127212731274127512761277127812791280128112821283128412851286128712881289129012911292129312941295129612971298129913001301130213031304130513061307130813091310131113121313131413151316131713181319132013211322132313241325132613271328132913301331133213331334133513361337133813391340134113421343134413451346134713481349135013511352135313541355135613571358135913601361136213631364136513661367136813691370137113721373137413751376137713781379138013811382138313841385138613871388138913901391139213931394139513961397139813991400140114021403140414051406140714081409141014111412141314141415141614171418141914201421142214231424142514261427142814291430143114321433143414351436143714381439144014411442144314441445144614471448144914501451145214531454145514561457145814591460146114621463146414651466146714681469147014711472147314741475147614771478147914801481148214831484148514861487148814891490149114921493149414951496149714981499150015011502150315041505150615071508150915101511151215131514151515161517151815191520152115221523152415251526152715281529153015311532153315341535153615371538153915401541154215431544154515461547154815491550155115521553155415551556155715581559156015611562156315641565156615671568156915701571157215731574157515761577157815791580158115821583158415851586158715881589159015911592159315941595159615971598159916001601160216031604160516061607160816091610161116121613161416151616161716181619162016211622162316241625162616271628162916301631163216331634163516361637163816391640164116421643164416451646164716481649165016511652165316541655165616571658165916601661166216631664166516661667166816691670167116721673167416751676167716781679168016811682168316841685168616871688168916901691169216931694169516961697169816991700170117021703170417051706170717081709171017111712171317141715171617171718171917201721172217231724172517261727172817291730173117321733173417351736173717381739174017411742174317441745174617471748174917501751175217531754175517561757175817591760176117621763176417651766176717681769177017711772177317741775177617771778177917801781178217831784178517861787178817891790179117921793179417951796179717981799180018011802180318041805180618071808180918101811181218131814181518161817181818191820182118221823182418251826182718281829183018311832183318341835183618371838183918401841184218431844184518461847184818491850185118521853185418551856185718581859186018611862186318641865186618671868186918701871187218731874187518761877187818791880188118821883188418851886188718881889189018911892189318941895189618971898189919001901190219031904190519061907190819091910191119121913191419151916191719181919192019211922192319241925192619271928192919301931193219331934193519361937193819391940194119421943194419451946194719481949195019511952195319541955195619571958195919601961196219631964196519661967196819691970197119721973197419751976197719781979198019811982198319841985198619871988198919901991199219931994199519961997199819992000200120022003200420052006200720082009201020112012201320142015201620172018201920202021202220232024202520262027202820292030203120322033203420352036203720382039204020412042204320442045204620472048204920502051205220532054205520562057205820592060206120622063206420652066206720682069207020712072207320742075207620772078207920802081208220832084208520862087208820892090209120922093209420952096209720982099210021012102210321042105210621072108210921102111211221132114211521162117211821192120212121222123212421252126212721282129213021312132213321342135213621372138213921402141214221432144214521462147214821492150215121522153215421552156215721582159216021612162216321642165216621672168216921702171217221732174217521762177217821792180218121822183218421852186218721882189219021912192219321942195219621972198219922002201220222032204220522062207220822092210221122122213221422152216221722182219222022212222222322242225222622272228222922302231223222332234223522362237223822392240224122422243224422452246224722482249225022512252225322542255225622572258225922602261226222632264226522662267226822692270227122722273227422752276227722782279228022812282228322842285228622872288228922902291229222932294229522962297229822992300230123022303230423052306230723082309231023112312231323142315231623172318231923202321232223232324232523262327232823292330233123322333233423352336233723382339234023412342234323442345234623472348234923502351235223532354235523562357235823592360236123622363236423652366236723682369237023712372237323742375237623772378237923802381238223832384238523862387238823892390239123922393
  1. /** @file
  2. Functions implementation related with DHCPv6 for UefiPxeBc Driver.
  3. (C) Copyright 2014 Hewlett-Packard Development Company, L.P.<BR>
  4. Copyright (c) 2009 - 2018, Intel Corporation. All rights reserved.<BR>
  5. SPDX-License-Identifier: BSD-2-Clause-Patent
  6. **/
  7. #include "PxeBcImpl.h"
  8. //
  9. // Well-known multi-cast address defined in section-24.1 of rfc-3315
  10. //
  11. // ALL_DHCP_Relay_Agents_and_Servers address: FF02::1:2
  12. //
  13. EFI_IPv6_ADDRESS mAllDhcpRelayAndServersAddress = {
  14. { 0xFF, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 0, 2 }
  15. };
  16. /**
  17. Parse out a DHCPv6 option by OptTag, and find the position in buffer.
  18. @param[in] Buffer The pointer to the option buffer.
  19. @param[in] Length Length of the option buffer.
  20. @param[in] OptTag The required option tag.
  21. @retval NULL Failed to parse the required option.
  22. @retval Others The position of the required option in buffer.
  23. **/
  24. EFI_DHCP6_PACKET_OPTION *
  25. PxeBcParseDhcp6Options (
  26. IN UINT8 *Buffer,
  27. IN UINT32 Length,
  28. IN UINT16 OptTag
  29. )
  30. {
  31. EFI_DHCP6_PACKET_OPTION *Option;
  32. UINT32 Offset;
  33. Option = (EFI_DHCP6_PACKET_OPTION *)Buffer;
  34. Offset = 0;
  35. //
  36. // OpLen and OpCode here are both stored in network order.
  37. //
  38. while (Offset < Length) {
  39. if (NTOHS (Option->OpCode) == OptTag) {
  40. return Option;
  41. }
  42. Offset += (NTOHS (Option->OpLen) + 4);
  43. Option = (EFI_DHCP6_PACKET_OPTION *)(Buffer + Offset);
  44. }
  45. return NULL;
  46. }
  47. /**
  48. Build the options buffer for the DHCPv6 request packet.
  49. @param[in] Private The pointer to PxeBc private data.
  50. @param[out] OptList The pointer to the option pointer array.
  51. @param[in] Buffer The pointer to the buffer to contain the option list.
  52. @return Index The count of the built-in options.
  53. **/
  54. UINT32
  55. PxeBcBuildDhcp6Options (
  56. IN PXEBC_PRIVATE_DATA *Private,
  57. OUT EFI_DHCP6_PACKET_OPTION **OptList,
  58. IN UINT8 *Buffer
  59. )
  60. {
  61. PXEBC_DHCP6_OPTION_ENTRY OptEnt;
  62. UINT32 Index;
  63. UINT16 Value;
  64. Index = 0;
  65. OptList[0] = (EFI_DHCP6_PACKET_OPTION *)Buffer;
  66. //
  67. // Append client option request option
  68. //
  69. OptList[Index]->OpCode = HTONS (DHCP6_OPT_ORO);
  70. OptList[Index]->OpLen = HTONS (8);
  71. OptEnt.Oro = (PXEBC_DHCP6_OPTION_ORO *)OptList[Index]->Data;
  72. OptEnt.Oro->OpCode[0] = HTONS (DHCP6_OPT_BOOT_FILE_URL);
  73. OptEnt.Oro->OpCode[1] = HTONS (DHCP6_OPT_BOOT_FILE_PARAM);
  74. OptEnt.Oro->OpCode[2] = HTONS (DHCP6_OPT_DNS_SERVERS);
  75. OptEnt.Oro->OpCode[3] = HTONS (DHCP6_OPT_VENDOR_CLASS);
  76. Index++;
  77. OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
  78. //
  79. // Append client network device interface option
  80. //
  81. OptList[Index]->OpCode = HTONS (DHCP6_OPT_UNDI);
  82. OptList[Index]->OpLen = HTONS ((UINT16)3);
  83. OptEnt.Undi = (PXEBC_DHCP6_OPTION_UNDI *)OptList[Index]->Data;
  84. if (Private->Nii != NULL) {
  85. OptEnt.Undi->Type = Private->Nii->Type;
  86. OptEnt.Undi->MajorVer = Private->Nii->MajorVer;
  87. OptEnt.Undi->MinorVer = Private->Nii->MinorVer;
  88. } else {
  89. OptEnt.Undi->Type = DEFAULT_UNDI_TYPE;
  90. OptEnt.Undi->MajorVer = DEFAULT_UNDI_MAJOR;
  91. OptEnt.Undi->MinorVer = DEFAULT_UNDI_MINOR;
  92. }
  93. Index++;
  94. OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
  95. //
  96. // Append client system architecture option
  97. //
  98. OptList[Index]->OpCode = HTONS (DHCP6_OPT_ARCH);
  99. OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_ARCH));
  100. OptEnt.Arch = (PXEBC_DHCP6_OPTION_ARCH *)OptList[Index]->Data;
  101. Value = HTONS (EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE);
  102. CopyMem (&OptEnt.Arch->Type, &Value, sizeof (UINT16));
  103. Index++;
  104. OptList[Index] = GET_NEXT_DHCP6_OPTION (OptList[Index - 1]);
  105. //
  106. // Append vendor class option to store the PXE class identifier.
  107. //
  108. OptList[Index]->OpCode = HTONS (DHCP6_OPT_VENDOR_CLASS);
  109. OptList[Index]->OpLen = HTONS ((UINT16)sizeof (PXEBC_DHCP6_OPTION_VENDOR_CLASS));
  110. OptEnt.VendorClass = (PXEBC_DHCP6_OPTION_VENDOR_CLASS *)OptList[Index]->Data;
  111. OptEnt.VendorClass->Vendor = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM);
  112. OptEnt.VendorClass->ClassLen = HTONS ((UINT16)sizeof (PXEBC_CLASS_ID));
  113. CopyMem (
  114. &OptEnt.VendorClass->ClassId,
  115. DEFAULT_CLASS_ID_DATA,
  116. sizeof (PXEBC_CLASS_ID)
  117. );
  118. PxeBcUintnToAscDecWithFormat (
  119. EFI_PXE_CLIENT_SYSTEM_ARCHITECTURE,
  120. OptEnt.VendorClass->ClassId.ArchitectureType,
  121. sizeof (OptEnt.VendorClass->ClassId.ArchitectureType)
  122. );
  123. if (Private->Nii != NULL) {
  124. CopyMem (
  125. OptEnt.VendorClass->ClassId.InterfaceName,
  126. Private->Nii->StringId,
  127. sizeof (OptEnt.VendorClass->ClassId.InterfaceName)
  128. );
  129. PxeBcUintnToAscDecWithFormat (
  130. Private->Nii->MajorVer,
  131. OptEnt.VendorClass->ClassId.UndiMajor,
  132. sizeof (OptEnt.VendorClass->ClassId.UndiMajor)
  133. );
  134. PxeBcUintnToAscDecWithFormat (
  135. Private->Nii->MinorVer,
  136. OptEnt.VendorClass->ClassId.UndiMinor,
  137. sizeof (OptEnt.VendorClass->ClassId.UndiMinor)
  138. );
  139. }
  140. Index++;
  141. return Index;
  142. }
  143. /**
  144. Cache the DHCPv6 packet.
  145. @param[in] Dst The pointer to the cache buffer for DHCPv6 packet.
  146. @param[in] Src The pointer to the DHCPv6 packet to be cached.
  147. @retval EFI_SUCCESS Packet is copied.
  148. @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet.
  149. **/
  150. EFI_STATUS
  151. PxeBcCacheDhcp6Packet (
  152. IN EFI_DHCP6_PACKET *Dst,
  153. IN EFI_DHCP6_PACKET *Src
  154. )
  155. {
  156. if (Dst->Size < Src->Length) {
  157. return EFI_BUFFER_TOO_SMALL;
  158. }
  159. CopyMem (&Dst->Dhcp6, &Src->Dhcp6, Src->Length);
  160. Dst->Length = Src->Length;
  161. return EFI_SUCCESS;
  162. }
  163. /**
  164. Retrieve the boot server address using the EFI_DNS6_PROTOCOL.
  165. @param[in] Private Pointer to PxeBc private data.
  166. @param[in] HostName Pointer to buffer containing hostname.
  167. @param[out] IpAddress On output, pointer to buffer containing IPv6 address.
  168. @retval EFI_SUCCESS Operation succeeded.
  169. @retval EFI_OUT_OF_RESOURCES Failed to allocate needed resources.
  170. @retval EFI_DEVICE_ERROR An unexpected network error occurred.
  171. @retval Others Other errors as indicated.
  172. **/
  173. EFI_STATUS
  174. PxeBcDns6 (
  175. IN PXEBC_PRIVATE_DATA *Private,
  176. IN CHAR16 *HostName,
  177. OUT EFI_IPv6_ADDRESS *IpAddress
  178. )
  179. {
  180. EFI_STATUS Status;
  181. EFI_DNS6_PROTOCOL *Dns6;
  182. EFI_DNS6_CONFIG_DATA Dns6ConfigData;
  183. EFI_DNS6_COMPLETION_TOKEN Token;
  184. EFI_HANDLE Dns6Handle;
  185. EFI_IPv6_ADDRESS *DnsServerList;
  186. BOOLEAN IsDone;
  187. Dns6 = NULL;
  188. Dns6Handle = NULL;
  189. DnsServerList = Private->DnsServer;
  190. ZeroMem (&Token, sizeof (EFI_DNS6_COMPLETION_TOKEN));
  191. //
  192. // Create a DNSv6 child instance and get the protocol.
  193. //
  194. Status = NetLibCreateServiceChild (
  195. Private->Controller,
  196. Private->Image,
  197. &gEfiDns6ServiceBindingProtocolGuid,
  198. &Dns6Handle
  199. );
  200. if (EFI_ERROR (Status)) {
  201. goto Exit;
  202. }
  203. Status = gBS->OpenProtocol (
  204. Dns6Handle,
  205. &gEfiDns6ProtocolGuid,
  206. (VOID **)&Dns6,
  207. Private->Image,
  208. Private->Controller,
  209. EFI_OPEN_PROTOCOL_BY_DRIVER
  210. );
  211. if (EFI_ERROR (Status)) {
  212. goto Exit;
  213. }
  214. //
  215. // Configure DNS6 instance for the DNS server address and protocol.
  216. //
  217. ZeroMem (&Dns6ConfigData, sizeof (EFI_DNS6_CONFIG_DATA));
  218. Dns6ConfigData.DnsServerCount = 1;
  219. Dns6ConfigData.DnsServerList = DnsServerList;
  220. Dns6ConfigData.EnableDnsCache = TRUE;
  221. Dns6ConfigData.Protocol = EFI_IP_PROTO_UDP;
  222. IP6_COPY_ADDRESS (&Dns6ConfigData.StationIp, &Private->TmpStationIp.v6);
  223. Status = Dns6->Configure (
  224. Dns6,
  225. &Dns6ConfigData
  226. );
  227. if (EFI_ERROR (Status)) {
  228. goto Exit;
  229. }
  230. Token.Status = EFI_NOT_READY;
  231. IsDone = FALSE;
  232. //
  233. // Create event to set the IsDone flag when name resolution is finished.
  234. //
  235. Status = gBS->CreateEvent (
  236. EVT_NOTIFY_SIGNAL,
  237. TPL_NOTIFY,
  238. PxeBcCommonNotify,
  239. &IsDone,
  240. &Token.Event
  241. );
  242. if (EFI_ERROR (Status)) {
  243. goto Exit;
  244. }
  245. //
  246. // Start asynchronous name resolution.
  247. //
  248. Status = Dns6->HostNameToIp (Dns6, HostName, &Token);
  249. if (EFI_ERROR (Status)) {
  250. goto Exit;
  251. }
  252. while (!IsDone) {
  253. Dns6->Poll (Dns6);
  254. }
  255. //
  256. // Name resolution is done, check result.
  257. //
  258. Status = Token.Status;
  259. if (!EFI_ERROR (Status)) {
  260. if (Token.RspData.H2AData == NULL) {
  261. Status = EFI_DEVICE_ERROR;
  262. goto Exit;
  263. }
  264. if ((Token.RspData.H2AData->IpCount == 0) || (Token.RspData.H2AData->IpList == NULL)) {
  265. Status = EFI_DEVICE_ERROR;
  266. goto Exit;
  267. }
  268. //
  269. // We just return the first IPv6 address from DNS protocol.
  270. //
  271. IP6_COPY_ADDRESS (IpAddress, Token.RspData.H2AData->IpList);
  272. Status = EFI_SUCCESS;
  273. }
  274. Exit:
  275. FreePool (HostName);
  276. if (Token.Event != NULL) {
  277. gBS->CloseEvent (Token.Event);
  278. }
  279. if (Token.RspData.H2AData != NULL) {
  280. if (Token.RspData.H2AData->IpList != NULL) {
  281. FreePool (Token.RspData.H2AData->IpList);
  282. }
  283. FreePool (Token.RspData.H2AData);
  284. }
  285. if (Dns6 != NULL) {
  286. Dns6->Configure (Dns6, NULL);
  287. gBS->CloseProtocol (
  288. Dns6Handle,
  289. &gEfiDns6ProtocolGuid,
  290. Private->Image,
  291. Private->Controller
  292. );
  293. }
  294. if (Dns6Handle != NULL) {
  295. NetLibDestroyServiceChild (
  296. Private->Controller,
  297. Private->Image,
  298. &gEfiDns6ServiceBindingProtocolGuid,
  299. Dns6Handle
  300. );
  301. }
  302. if (DnsServerList != NULL) {
  303. FreePool (DnsServerList);
  304. }
  305. return Status;
  306. }
  307. /**
  308. Parse the Boot File URL option.
  309. @param[in] Private Pointer to PxeBc private data.
  310. @param[out] FileName The pointer to the boot file name.
  311. @param[in, out] SrvAddr The pointer to the boot server address.
  312. @param[in] BootFile The pointer to the boot file URL option data.
  313. @param[in] Length The length of the boot file URL option data.
  314. @retval EFI_ABORTED User cancel operation.
  315. @retval EFI_SUCCESS Selected the boot menu successfully.
  316. @retval EFI_NOT_READY Read the input key from the keyboard has not finish.
  317. **/
  318. EFI_STATUS
  319. PxeBcExtractBootFileUrl (
  320. IN PXEBC_PRIVATE_DATA *Private,
  321. OUT UINT8 **FileName,
  322. IN OUT EFI_IPv6_ADDRESS *SrvAddr,
  323. IN CHAR8 *BootFile,
  324. IN UINT16 Length
  325. )
  326. {
  327. UINT16 PrefixLen;
  328. CHAR8 *BootFileNamePtr;
  329. CHAR8 *BootFileName;
  330. UINT16 BootFileNameLen;
  331. CHAR8 *TmpStr;
  332. CHAR8 TmpChar;
  333. CHAR8 *ServerAddressOption;
  334. CHAR8 *ServerAddress;
  335. CHAR8 *ModeStr;
  336. CHAR16 *HostName;
  337. BOOLEAN IpExpressedUrl;
  338. UINTN Len;
  339. EFI_STATUS Status;
  340. IpExpressedUrl = TRUE;
  341. //
  342. // The format of the Boot File URL option is:
  343. //
  344. // 0 1 2 3
  345. // 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
  346. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  347. // | OPT_BOOTFILE_URL | option-len |
  348. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  349. // | |
  350. // . bootfile-url (variable length) .
  351. // | |
  352. // +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
  353. //
  354. //
  355. // Based upon RFC 5970 and UEFI 2.6, bootfile-url format can be
  356. // tftp://[SERVER_ADDRESS]/BOOTFILE_NAME or tftp://domain_name/BOOTFILE_NAME
  357. // As an example where the BOOTFILE_NAME is the EFI loader and
  358. // SERVER_ADDRESS is the ASCII encoding of an IPV6 address.
  359. //
  360. PrefixLen = (UINT16)AsciiStrLen (PXEBC_DHCP6_BOOT_FILE_URL_PREFIX);
  361. if ((Length <= PrefixLen) ||
  362. (CompareMem (BootFile, PXEBC_DHCP6_BOOT_FILE_URL_PREFIX, PrefixLen) != 0))
  363. {
  364. return EFI_NOT_FOUND;
  365. }
  366. BootFile = BootFile + PrefixLen;
  367. Length = (UINT16)(Length - PrefixLen);
  368. TmpStr = (CHAR8 *)AllocateZeroPool (Length + 1);
  369. if (TmpStr == NULL) {
  370. return EFI_OUT_OF_RESOURCES;
  371. }
  372. CopyMem (TmpStr, BootFile, Length);
  373. TmpStr[Length] = '\0';
  374. //
  375. // Get the part of SERVER_ADDRESS string.
  376. //
  377. ServerAddressOption = TmpStr;
  378. if (*ServerAddressOption == PXEBC_ADDR_START_DELIMITER) {
  379. ServerAddressOption++;
  380. ServerAddress = ServerAddressOption;
  381. while (*ServerAddress != '\0' && *ServerAddress != PXEBC_ADDR_END_DELIMITER) {
  382. ServerAddress++;
  383. }
  384. if (*ServerAddress != PXEBC_ADDR_END_DELIMITER) {
  385. FreePool (TmpStr);
  386. return EFI_INVALID_PARAMETER;
  387. }
  388. *ServerAddress = '\0';
  389. //
  390. // Convert the string of server address to Ipv6 address format and store it.
  391. //
  392. Status = NetLibAsciiStrToIp6 (ServerAddressOption, SrvAddr);
  393. if (EFI_ERROR (Status)) {
  394. FreePool (TmpStr);
  395. return Status;
  396. }
  397. } else {
  398. IpExpressedUrl = FALSE;
  399. ServerAddress = ServerAddressOption;
  400. while (*ServerAddress != '\0' && *ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {
  401. ServerAddress++;
  402. }
  403. if (*ServerAddress != PXEBC_TFTP_URL_SEPARATOR) {
  404. FreePool (TmpStr);
  405. return EFI_INVALID_PARAMETER;
  406. }
  407. *ServerAddress = '\0';
  408. Len = AsciiStrSize (ServerAddressOption);
  409. HostName = AllocateZeroPool (Len * sizeof (CHAR16));
  410. if (HostName == NULL) {
  411. FreePool (TmpStr);
  412. return EFI_OUT_OF_RESOURCES;
  413. }
  414. AsciiStrToUnicodeStrS (
  415. ServerAddressOption,
  416. HostName,
  417. Len
  418. );
  419. //
  420. // Perform DNS resolution.
  421. //
  422. Status = PxeBcDns6 (Private, HostName, SrvAddr);
  423. if (EFI_ERROR (Status)) {
  424. FreePool (TmpStr);
  425. return Status;
  426. }
  427. }
  428. //
  429. // Get the part of BOOTFILE_NAME string.
  430. //
  431. BootFileNamePtr = (CHAR8 *)((UINTN)ServerAddress + 1);
  432. if (IpExpressedUrl) {
  433. if (*BootFileNamePtr != PXEBC_TFTP_URL_SEPARATOR) {
  434. FreePool (TmpStr);
  435. return EFI_INVALID_PARAMETER;
  436. }
  437. ++BootFileNamePtr;
  438. }
  439. BootFileNameLen = (UINT16)(Length - (UINT16)((UINTN)BootFileNamePtr - (UINTN)TmpStr) + 1);
  440. if ((BootFileNameLen != 0) || (FileName != NULL)) {
  441. //
  442. // Remove trailing mode=octet if present and ignore. All other modes are
  443. // invalid for netboot6, so reject them.
  444. //
  445. ModeStr = AsciiStrStr (BootFileNamePtr, ";mode=octet");
  446. if ((ModeStr != NULL) && (*(ModeStr + AsciiStrLen (";mode=octet")) == '\0')) {
  447. *ModeStr = '\0';
  448. } else if (AsciiStrStr (BootFileNamePtr, ";mode=") != NULL) {
  449. FreePool (TmpStr);
  450. return EFI_INVALID_PARAMETER;
  451. }
  452. //
  453. // Extract boot file name from URL.
  454. //
  455. BootFileName = (CHAR8 *)AllocateZeroPool (BootFileNameLen);
  456. if (BootFileName == NULL) {
  457. FreePool (TmpStr);
  458. return EFI_OUT_OF_RESOURCES;
  459. }
  460. *FileName = (UINT8 *)BootFileName;
  461. //
  462. // Decode percent-encoding in boot file name.
  463. //
  464. while (*BootFileNamePtr != '\0') {
  465. if (*BootFileNamePtr == '%') {
  466. TmpChar = *(BootFileNamePtr+ 3);
  467. *(BootFileNamePtr+ 3) = '\0';
  468. *BootFileName = (UINT8)AsciiStrHexToUintn ((CHAR8 *)(BootFileNamePtr + 1));
  469. BootFileName++;
  470. *(BootFileNamePtr+ 3) = TmpChar;
  471. BootFileNamePtr += 3;
  472. } else {
  473. *BootFileName = *BootFileNamePtr;
  474. BootFileName++;
  475. BootFileNamePtr++;
  476. }
  477. }
  478. *BootFileName = '\0';
  479. }
  480. FreePool (TmpStr);
  481. return EFI_SUCCESS;
  482. }
  483. /**
  484. Parse the Boot File Parameter option.
  485. @param[in] BootFilePara The pointer to boot file parameter option data.
  486. @param[out] BootFileSize The pointer to the parsed boot file size.
  487. @retval EFI_SUCCESS Successfully obtained the boot file size from parameter option.
  488. @retval EFI_NOT_FOUND Failed to extract the boot file size from parameter option.
  489. **/
  490. EFI_STATUS
  491. PxeBcExtractBootFileParam (
  492. IN CHAR8 *BootFilePara,
  493. OUT UINT16 *BootFileSize
  494. )
  495. {
  496. UINT16 Length;
  497. UINT8 Index;
  498. UINT8 Digit;
  499. UINT32 Size;
  500. CopyMem (&Length, BootFilePara, sizeof (UINT16));
  501. Length = NTOHS (Length);
  502. //
  503. // The BootFile Size should be 1~5 byte ASCII strings
  504. //
  505. if ((Length < 1) || (Length > 5)) {
  506. return EFI_NOT_FOUND;
  507. }
  508. //
  509. // Extract the value of BootFile Size.
  510. //
  511. BootFilePara = BootFilePara + sizeof (UINT16);
  512. Size = 0;
  513. for (Index = 0; Index < Length; Index++) {
  514. if (EFI_ERROR (PxeBcUniHexToUint8 (&Digit, *(BootFilePara + Index)))) {
  515. return EFI_NOT_FOUND;
  516. }
  517. Size = (Size + Digit) * 10;
  518. }
  519. Size = Size / 10;
  520. if (Size > PXEBC_DHCP6_MAX_BOOT_FILE_SIZE) {
  521. return EFI_NOT_FOUND;
  522. }
  523. *BootFileSize = (UINT16)Size;
  524. return EFI_SUCCESS;
  525. }
  526. /**
  527. Parse the cached DHCPv6 packet, including all the options.
  528. @param[in] Cache6 The pointer to a cached DHCPv6 packet.
  529. @retval EFI_SUCCESS Parsed the DHCPv6 packet successfully.
  530. @retval EFI_DEVICE_ERROR Failed to parse and invalid the packet.
  531. **/
  532. EFI_STATUS
  533. PxeBcParseDhcp6Packet (
  534. IN PXEBC_DHCP6_PACKET_CACHE *Cache6
  535. )
  536. {
  537. EFI_DHCP6_PACKET *Offer;
  538. EFI_DHCP6_PACKET_OPTION **Options;
  539. EFI_DHCP6_PACKET_OPTION *Option;
  540. PXEBC_OFFER_TYPE OfferType;
  541. BOOLEAN IsProxyOffer;
  542. BOOLEAN IsPxeOffer;
  543. UINT32 Offset;
  544. UINT32 Length;
  545. UINT32 EnterpriseNum;
  546. IsProxyOffer = TRUE;
  547. IsPxeOffer = FALSE;
  548. Offer = &Cache6->Packet.Offer;
  549. Options = Cache6->OptList;
  550. ZeroMem (Cache6->OptList, sizeof (Cache6->OptList));
  551. Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option);
  552. Offset = 0;
  553. Length = GET_DHCP6_OPTION_SIZE (Offer);
  554. //
  555. // OpLen and OpCode here are both stored in network order, since they are from original packet.
  556. //
  557. while (Offset < Length) {
  558. if (NTOHS (Option->OpCode) == DHCP6_OPT_IA_NA) {
  559. Options[PXEBC_DHCP6_IDX_IA_NA] = Option;
  560. } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_URL) {
  561. //
  562. // The server sends this option to inform the client about an URL to a boot file.
  563. //
  564. Options[PXEBC_DHCP6_IDX_BOOT_FILE_URL] = Option;
  565. } else if (NTOHS (Option->OpCode) == DHCP6_OPT_BOOT_FILE_PARAM) {
  566. Options[PXEBC_DHCP6_IDX_BOOT_FILE_PARAM] = Option;
  567. } else if (NTOHS (Option->OpCode) == DHCP6_OPT_VENDOR_CLASS) {
  568. Options[PXEBC_DHCP6_IDX_VENDOR_CLASS] = Option;
  569. } else if (NTOHS (Option->OpCode) == DHCP6_OPT_DNS_SERVERS) {
  570. Options[PXEBC_DHCP6_IDX_DNS_SERVER] = Option;
  571. }
  572. Offset += (NTOHS (Option->OpLen) + 4);
  573. Option = (EFI_DHCP6_PACKET_OPTION *)(Offer->Dhcp6.Option + Offset);
  574. }
  575. //
  576. // The offer with assigned client address is NOT a proxy offer.
  577. // An ia_na option, embedded with valid ia_addr option and a status_code of success.
  578. //
  579. Option = Options[PXEBC_DHCP6_IDX_IA_NA];
  580. if (Option != NULL) {
  581. Option = PxeBcParseDhcp6Options (
  582. Option->Data + 12,
  583. NTOHS (Option->OpLen),
  584. DHCP6_OPT_STATUS_CODE
  585. );
  586. if (((Option != NULL) && (Option->Data[0] == 0)) || (Option == NULL)) {
  587. IsProxyOffer = FALSE;
  588. }
  589. }
  590. //
  591. // The offer with "PXEClient" is a pxe offer.
  592. //
  593. Option = Options[PXEBC_DHCP6_IDX_VENDOR_CLASS];
  594. EnterpriseNum = HTONL (PXEBC_DHCP6_ENTERPRISE_NUM);
  595. if ((Option != NULL) &&
  596. (NTOHS (Option->OpLen) >= 13) &&
  597. (CompareMem (Option->Data, &EnterpriseNum, sizeof (UINT32)) == 0) &&
  598. (CompareMem (&Option->Data[6], DEFAULT_CLASS_ID_DATA, 9) == 0))
  599. {
  600. IsPxeOffer = TRUE;
  601. }
  602. //
  603. // Determine offer type of the dhcp6 packet.
  604. //
  605. if (IsPxeOffer) {
  606. //
  607. // It's a binl offer only with PXEClient.
  608. //
  609. OfferType = IsProxyOffer ? PxeOfferTypeProxyBinl : PxeOfferTypeDhcpBinl;
  610. } else {
  611. //
  612. // It's a dhcp only offer, which is a pure dhcp6 offer packet.
  613. //
  614. OfferType = PxeOfferTypeDhcpOnly;
  615. }
  616. Cache6->OfferType = OfferType;
  617. return EFI_SUCCESS;
  618. }
  619. /**
  620. Cache the DHCPv6 ack packet, and parse it on demand.
  621. @param[in] Private The pointer to PxeBc private data.
  622. @param[in] Ack The pointer to the DHCPv6 ack packet.
  623. @param[in] Verified If TRUE, parse the ACK packet and store info into mode data.
  624. @retval EFI_SUCCESS Cache and parse the packet successfully.
  625. @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet.
  626. **/
  627. EFI_STATUS
  628. PxeBcCopyDhcp6Ack (
  629. IN PXEBC_PRIVATE_DATA *Private,
  630. IN EFI_DHCP6_PACKET *Ack,
  631. IN BOOLEAN Verified
  632. )
  633. {
  634. EFI_PXE_BASE_CODE_MODE *Mode;
  635. EFI_STATUS Status;
  636. Mode = Private->PxeBc.Mode;
  637. Status = PxeBcCacheDhcp6Packet (&Private->DhcpAck.Dhcp6.Packet.Ack, Ack);
  638. if (EFI_ERROR (Status)) {
  639. return Status;
  640. }
  641. if (Verified) {
  642. //
  643. // Parse the ack packet and store it into mode data if needed.
  644. //
  645. PxeBcParseDhcp6Packet (&Private->DhcpAck.Dhcp6);
  646. CopyMem (&Mode->DhcpAck.Dhcpv6, &Ack->Dhcp6, Ack->Length);
  647. Mode->DhcpAckReceived = TRUE;
  648. }
  649. return EFI_SUCCESS;
  650. }
  651. /**
  652. Cache the DHCPv6 proxy offer packet according to the received order.
  653. @param[in] Private The pointer to PxeBc private data.
  654. @param[in] OfferIndex The received order of offer packets.
  655. @retval EFI_SUCCESS Cache and parse the packet successfully.
  656. @retval EFI_BUFFER_TOO_SMALL Cache buffer is not big enough to hold the packet.
  657. **/
  658. EFI_STATUS
  659. PxeBcCopyDhcp6Proxy (
  660. IN PXEBC_PRIVATE_DATA *Private,
  661. IN UINT32 OfferIndex
  662. )
  663. {
  664. EFI_PXE_BASE_CODE_MODE *Mode;
  665. EFI_DHCP6_PACKET *Offer;
  666. EFI_STATUS Status;
  667. ASSERT (OfferIndex < Private->OfferNum);
  668. ASSERT (OfferIndex < PXEBC_OFFER_MAX_NUM);
  669. Mode = Private->PxeBc.Mode;
  670. Offer = &Private->OfferBuffer[OfferIndex].Dhcp6.Packet.Offer;
  671. //
  672. // Cache the proxy offer packet and parse it.
  673. //
  674. Status = PxeBcCacheDhcp6Packet (&Private->ProxyOffer.Dhcp6.Packet.Offer, Offer);
  675. if (EFI_ERROR (Status)) {
  676. return Status;
  677. }
  678. PxeBcParseDhcp6Packet (&Private->ProxyOffer.Dhcp6);
  679. //
  680. // Store this packet into mode data.
  681. //
  682. CopyMem (&Mode->ProxyOffer.Dhcpv6, &Offer->Dhcp6, Offer->Length);
  683. Mode->ProxyOfferReceived = TRUE;
  684. return EFI_SUCCESS;
  685. }
  686. /**
  687. Seek the address of the first byte of the option header.
  688. @param[in] Buf The pointer to the buffer.
  689. @param[in] SeekLen The length to seek.
  690. @param[in] OptType The option type.
  691. @retval NULL If it failed to seek the option.
  692. @retval others The position to the option.
  693. **/
  694. UINT8 *
  695. PxeBcDhcp6SeekOption (
  696. IN UINT8 *Buf,
  697. IN UINT32 SeekLen,
  698. IN UINT16 OptType
  699. )
  700. {
  701. UINT8 *Cursor;
  702. UINT8 *Option;
  703. UINT16 DataLen;
  704. UINT16 OpCode;
  705. Option = NULL;
  706. Cursor = Buf;
  707. while (Cursor < Buf + SeekLen) {
  708. OpCode = ReadUnaligned16 ((UINT16 *)Cursor);
  709. if (OpCode == HTONS (OptType)) {
  710. Option = Cursor;
  711. break;
  712. }
  713. DataLen = NTOHS (ReadUnaligned16 ((UINT16 *)(Cursor + 2)));
  714. Cursor += (DataLen + 4);
  715. }
  716. return Option;
  717. }
  718. /**
  719. Build and send out the request packet for the bootfile, and parse the reply.
  720. @param[in] Private The pointer to PxeBc private data.
  721. @param[in] Index PxeBc option boot item type.
  722. @retval EFI_SUCCESS Successfully discovered the boot file.
  723. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
  724. @retval EFI_NOT_FOUND Can't get the PXE reply packet.
  725. @retval Others Failed to discover the boot file.
  726. **/
  727. EFI_STATUS
  728. PxeBcRequestBootService (
  729. IN PXEBC_PRIVATE_DATA *Private,
  730. IN UINT32 Index
  731. )
  732. {
  733. EFI_PXE_BASE_CODE_UDP_PORT SrcPort;
  734. EFI_PXE_BASE_CODE_UDP_PORT DestPort;
  735. EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
  736. EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover;
  737. UINTN DiscoverLen;
  738. EFI_DHCP6_PACKET *Request;
  739. UINTN RequestLen;
  740. EFI_DHCP6_PACKET *Reply;
  741. UINT8 *RequestOpt;
  742. UINT8 *DiscoverOpt;
  743. UINTN ReadSize;
  744. UINT16 OpFlags;
  745. UINT16 OpCode;
  746. UINT16 OpLen;
  747. EFI_STATUS Status;
  748. EFI_DHCP6_PACKET *IndexOffer;
  749. UINT8 *Option;
  750. PxeBc = &Private->PxeBc;
  751. Request = Private->Dhcp6Request;
  752. IndexOffer = &Private->OfferBuffer[Index].Dhcp6.Packet.Offer;
  753. SrcPort = PXEBC_BS_DISCOVER_PORT;
  754. DestPort = PXEBC_BS_DISCOVER_PORT;
  755. OpFlags = 0;
  756. if (Request == NULL) {
  757. return EFI_DEVICE_ERROR;
  758. }
  759. Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
  760. if (Discover == NULL) {
  761. return EFI_OUT_OF_RESOURCES;
  762. }
  763. //
  764. // Build the request packet by the cached request packet before.
  765. //
  766. Discover->TransactionId = IndexOffer->Dhcp6.Header.TransactionId;
  767. Discover->MessageType = Request->Dhcp6.Header.MessageType;
  768. RequestOpt = Request->Dhcp6.Option;
  769. DiscoverOpt = Discover->DhcpOptions;
  770. DiscoverLen = sizeof (EFI_DHCP6_HEADER);
  771. RequestLen = DiscoverLen;
  772. //
  773. // Find Server ID Option from ProxyOffer.
  774. //
  775. if (Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl) {
  776. Option = PxeBcDhcp6SeekOption (
  777. IndexOffer->Dhcp6.Option,
  778. IndexOffer->Length - 4,
  779. DHCP6_OPT_SERVER_ID
  780. );
  781. if (Option == NULL) {
  782. return EFI_NOT_FOUND;
  783. }
  784. //
  785. // Add Server ID Option.
  786. //
  787. OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)Option)->OpLen);
  788. CopyMem (DiscoverOpt, Option, OpLen + 4);
  789. DiscoverOpt += (OpLen + 4);
  790. DiscoverLen += (OpLen + 4);
  791. }
  792. while (RequestLen < Request->Length) {
  793. OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);
  794. OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);
  795. if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&
  796. (OpCode != EFI_DHCP6_IA_TYPE_TA) &&
  797. (OpCode != DHCP6_OPT_SERVER_ID)
  798. )
  799. {
  800. //
  801. // Copy all the options except IA option and Server ID
  802. //
  803. CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
  804. DiscoverOpt += (OpLen + 4);
  805. DiscoverLen += (OpLen + 4);
  806. }
  807. RequestOpt += (OpLen + 4);
  808. RequestLen += (OpLen + 4);
  809. }
  810. //
  811. // Update Elapsed option in the package
  812. //
  813. Option = PxeBcDhcp6SeekOption (
  814. Discover->DhcpOptions,
  815. (UINT32)(RequestLen - 4),
  816. DHCP6_OPT_ELAPSED_TIME
  817. );
  818. if (Option != NULL) {
  819. CalcElapsedTime (Private);
  820. WriteUnaligned16 ((UINT16 *)(Option + 4), HTONS ((UINT16)Private->ElapsedTime));
  821. }
  822. Status = PxeBc->UdpWrite (
  823. PxeBc,
  824. OpFlags,
  825. &Private->ServerIp,
  826. &DestPort,
  827. NULL,
  828. &Private->StationIp,
  829. &SrcPort,
  830. NULL,
  831. NULL,
  832. &DiscoverLen,
  833. (VOID *)Discover
  834. );
  835. if (EFI_ERROR (Status)) {
  836. goto ON_ERROR;
  837. }
  838. //
  839. // Cache the right PXE reply packet here, set valid flag later.
  840. // Especially for PXE discover packet, store it into mode data here.
  841. //
  842. Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer;
  843. ReadSize = (UINTN)Reply->Size;
  844. //
  845. // Start Udp6Read instance
  846. //
  847. Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
  848. if (EFI_ERROR (Status)) {
  849. goto ON_ERROR;
  850. }
  851. Status = PxeBc->UdpRead (
  852. PxeBc,
  853. EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_SRC_IP | EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP,
  854. NULL,
  855. &SrcPort,
  856. &Private->ServerIp,
  857. &DestPort,
  858. NULL,
  859. NULL,
  860. &ReadSize,
  861. (VOID *)&Reply->Dhcp6
  862. );
  863. //
  864. // Stop Udp6Read instance
  865. //
  866. Private->Udp6Read->Configure (Private->Udp6Read, NULL);
  867. if (EFI_ERROR (Status)) {
  868. goto ON_ERROR;
  869. }
  870. //
  871. // Update length
  872. //
  873. Reply->Length = (UINT32)ReadSize;
  874. return EFI_SUCCESS;
  875. ON_ERROR:
  876. if (Discover != NULL) {
  877. FreePool (Discover);
  878. }
  879. return Status;
  880. }
  881. /**
  882. Retry to request bootfile name by the BINL offer.
  883. @param[in] Private The pointer to PxeBc private data.
  884. @param[in] Index The received order of offer packets.
  885. @retval EFI_SUCCESS Successfully retried a request for the bootfile name.
  886. @retval EFI_DEVICE_ERROR Failed to retry the bootfile name.
  887. **/
  888. EFI_STATUS
  889. PxeBcRetryDhcp6Binl (
  890. IN PXEBC_PRIVATE_DATA *Private,
  891. IN UINT32 Index
  892. )
  893. {
  894. EFI_PXE_BASE_CODE_MODE *Mode;
  895. PXEBC_DHCP6_PACKET_CACHE *Offer;
  896. PXEBC_DHCP6_PACKET_CACHE *Cache6;
  897. EFI_STATUS Status;
  898. ASSERT (Index < PXEBC_OFFER_MAX_NUM);
  899. ASSERT (
  900. Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeDhcpBinl ||
  901. Private->OfferBuffer[Index].Dhcp6.OfferType == PxeOfferTypeProxyBinl
  902. );
  903. Mode = Private->PxeBc.Mode;
  904. Private->IsDoDiscover = FALSE;
  905. Offer = &Private->OfferBuffer[Index].Dhcp6;
  906. if (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL) {
  907. //
  908. // There is no BootFileUrl option in dhcp6 offer, so use servers multi-cast address instead.
  909. //
  910. CopyMem (
  911. &Private->ServerIp.v6,
  912. &mAllDhcpRelayAndServersAddress,
  913. sizeof (EFI_IPv6_ADDRESS)
  914. );
  915. } else {
  916. ASSERT (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL);
  917. //
  918. // Parse out the next server address from the last offer, and store it
  919. //
  920. Status = PxeBcExtractBootFileUrl (
  921. Private,
  922. &Private->BootFileName,
  923. &Private->ServerIp.v6,
  924. (CHAR8 *)(Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->Data),
  925. NTOHS (Offer->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL]->OpLen)
  926. );
  927. if (EFI_ERROR (Status)) {
  928. return Status;
  929. }
  930. }
  931. //
  932. // Retry Dhcp6Binl again for the bootfile, and the reply cached into Private->ProxyOffer.
  933. //
  934. Status = PxeBcRequestBootService (Private, Index);
  935. if (EFI_ERROR (Status)) {
  936. return Status;
  937. }
  938. Cache6 = &Private->ProxyOffer.Dhcp6;
  939. Status = PxeBcParseDhcp6Packet (Cache6);
  940. if (EFI_ERROR (Status)) {
  941. return Status;
  942. }
  943. if ((Cache6->OfferType != PxeOfferTypeProxyPxe10) &&
  944. (Cache6->OfferType != PxeOfferTypeProxyWfm11a) &&
  945. (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL))
  946. {
  947. //
  948. // This BINL ack doesn't have discovery option set or multicast option set
  949. // or bootfile name specified.
  950. //
  951. return EFI_DEVICE_ERROR;
  952. }
  953. Mode->ProxyOfferReceived = TRUE;
  954. CopyMem (
  955. &Mode->ProxyOffer.Dhcpv6,
  956. &Cache6->Packet.Offer.Dhcp6,
  957. Cache6->Packet.Offer.Length
  958. );
  959. return EFI_SUCCESS;
  960. }
  961. /**
  962. Cache all the received DHCPv6 offers, and set OfferIndex and OfferCount.
  963. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  964. @param[in] RcvdOffer The pointer to the received offer packet.
  965. @retval EFI_SUCCESS Cache and parse the packet successfully.
  966. @retval Others Operation failed.
  967. **/
  968. EFI_STATUS
  969. PxeBcCacheDhcp6Offer (
  970. IN PXEBC_PRIVATE_DATA *Private,
  971. IN EFI_DHCP6_PACKET *RcvdOffer
  972. )
  973. {
  974. PXEBC_DHCP6_PACKET_CACHE *Cache6;
  975. EFI_DHCP6_PACKET *Offer;
  976. PXEBC_OFFER_TYPE OfferType;
  977. EFI_STATUS Status;
  978. Cache6 = &Private->OfferBuffer[Private->OfferNum].Dhcp6;
  979. Offer = &Cache6->Packet.Offer;
  980. //
  981. // Cache the content of DHCPv6 packet firstly.
  982. //
  983. Status = PxeBcCacheDhcp6Packet (Offer, RcvdOffer);
  984. if (EFI_ERROR (Status)) {
  985. return Status;
  986. }
  987. //
  988. // Validate the DHCPv6 packet, and parse the options and offer type.
  989. //
  990. if (EFI_ERROR (PxeBcParseDhcp6Packet (Cache6))) {
  991. return EFI_ABORTED;
  992. }
  993. //
  994. // Determine whether cache the current offer by type, and record OfferIndex and OfferCount.
  995. //
  996. OfferType = Cache6->OfferType;
  997. ASSERT (OfferType < PxeOfferTypeMax);
  998. ASSERT (Private->OfferCount[OfferType] < PXEBC_OFFER_MAX_NUM);
  999. if (IS_PROXY_OFFER (OfferType)) {
  1000. //
  1001. // It's a proxy offer without yiaddr, including PXE10, WFM11a or BINL offer.
  1002. //
  1003. Private->IsProxyRecved = TRUE;
  1004. if (OfferType == PxeOfferTypeProxyBinl) {
  1005. //
  1006. // Cache all proxy BINL offers.
  1007. //
  1008. Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;
  1009. Private->OfferCount[OfferType]++;
  1010. } else if (((OfferType == PxeOfferTypeProxyPxe10) || (OfferType == PxeOfferTypeProxyWfm11a)) &&
  1011. (Private->OfferCount[OfferType] < 1))
  1012. {
  1013. //
  1014. // Only cache the first PXE10/WFM11a offer, and discard the others.
  1015. //
  1016. Private->OfferIndex[OfferType][0] = Private->OfferNum;
  1017. Private->OfferCount[OfferType] = 1;
  1018. } else {
  1019. return EFI_ABORTED;
  1020. }
  1021. } else {
  1022. //
  1023. // It's a DHCPv6 offer with yiaddr, and cache them all.
  1024. //
  1025. Private->OfferIndex[OfferType][Private->OfferCount[OfferType]] = Private->OfferNum;
  1026. Private->OfferCount[OfferType]++;
  1027. }
  1028. Private->OfferNum++;
  1029. return EFI_SUCCESS;
  1030. }
  1031. /**
  1032. Select an DHCPv6 offer, and record SelectIndex and SelectProxyType.
  1033. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1034. **/
  1035. VOID
  1036. PxeBcSelectDhcp6Offer (
  1037. IN PXEBC_PRIVATE_DATA *Private
  1038. )
  1039. {
  1040. UINT32 Index;
  1041. UINT32 OfferIndex;
  1042. PXEBC_OFFER_TYPE OfferType;
  1043. Private->SelectIndex = 0;
  1044. if (Private->IsOfferSorted) {
  1045. //
  1046. // Select offer by default policy.
  1047. //
  1048. if (Private->OfferCount[PxeOfferTypeDhcpPxe10] > 0) {
  1049. //
  1050. // 1. DhcpPxe10 offer
  1051. //
  1052. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpPxe10][0] + 1;
  1053. } else if (Private->OfferCount[PxeOfferTypeDhcpWfm11a] > 0) {
  1054. //
  1055. // 2. DhcpWfm11a offer
  1056. //
  1057. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpWfm11a][0] + 1;
  1058. } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&
  1059. (Private->OfferCount[PxeOfferTypeProxyPxe10] > 0))
  1060. {
  1061. //
  1062. // 3. DhcpOnly offer and ProxyPxe10 offer.
  1063. //
  1064. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;
  1065. Private->SelectProxyType = PxeOfferTypeProxyPxe10;
  1066. } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&
  1067. (Private->OfferCount[PxeOfferTypeProxyWfm11a] > 0))
  1068. {
  1069. //
  1070. // 4. DhcpOnly offer and ProxyWfm11a offer.
  1071. //
  1072. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;
  1073. Private->SelectProxyType = PxeOfferTypeProxyWfm11a;
  1074. } else if (Private->OfferCount[PxeOfferTypeDhcpBinl] > 0) {
  1075. //
  1076. // 5. DhcpBinl offer.
  1077. //
  1078. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpBinl][0] + 1;
  1079. } else if ((Private->OfferCount[PxeOfferTypeDhcpOnly] > 0) &&
  1080. (Private->OfferCount[PxeOfferTypeProxyBinl] > 0))
  1081. {
  1082. //
  1083. // 6. DhcpOnly offer and ProxyBinl offer.
  1084. //
  1085. Private->SelectIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][0] + 1;
  1086. Private->SelectProxyType = PxeOfferTypeProxyBinl;
  1087. } else {
  1088. //
  1089. // 7. DhcpOnly offer with bootfilename.
  1090. //
  1091. for (Index = 0; Index < Private->OfferCount[PxeOfferTypeDhcpOnly]; Index++) {
  1092. OfferIndex = Private->OfferIndex[PxeOfferTypeDhcpOnly][Index];
  1093. if (Private->OfferBuffer[OfferIndex].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL) {
  1094. Private->SelectIndex = OfferIndex + 1;
  1095. break;
  1096. }
  1097. }
  1098. }
  1099. } else {
  1100. //
  1101. // Select offer by received order.
  1102. //
  1103. for (Index = 0; Index < Private->OfferNum; Index++) {
  1104. OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType;
  1105. if (IS_PROXY_OFFER (OfferType)) {
  1106. //
  1107. // Skip proxy offers
  1108. //
  1109. continue;
  1110. }
  1111. if (!Private->IsProxyRecved &&
  1112. (OfferType == PxeOfferTypeDhcpOnly) &&
  1113. (Private->OfferBuffer[Index].Dhcp6.OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] == NULL))
  1114. {
  1115. //
  1116. // Skip if DhcpOnly offer without any other proxy offers or bootfilename.
  1117. //
  1118. continue;
  1119. }
  1120. Private->SelectIndex = Index + 1;
  1121. break;
  1122. }
  1123. }
  1124. }
  1125. /**
  1126. Handle the DHCPv6 offer packet.
  1127. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1128. @retval EFI_SUCCESS Handled the DHCPv6 offer packet successfully.
  1129. @retval EFI_NO_RESPONSE No response to the following request packet.
  1130. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
  1131. @retval EFI_BUFFER_TOO_SMALL Can't cache the offer pacet.
  1132. **/
  1133. EFI_STATUS
  1134. PxeBcHandleDhcp6Offer (
  1135. IN PXEBC_PRIVATE_DATA *Private
  1136. )
  1137. {
  1138. PXEBC_DHCP6_PACKET_CACHE *Cache6;
  1139. EFI_STATUS Status;
  1140. PXEBC_OFFER_TYPE OfferType;
  1141. UINT32 ProxyIndex;
  1142. UINT32 SelectIndex;
  1143. UINT32 Index;
  1144. ASSERT (Private->SelectIndex > 0);
  1145. SelectIndex = (UINT32)(Private->SelectIndex - 1);
  1146. ASSERT (SelectIndex < PXEBC_OFFER_MAX_NUM);
  1147. Cache6 = &Private->OfferBuffer[SelectIndex].Dhcp6;
  1148. Status = EFI_SUCCESS;
  1149. //
  1150. // First try to cache DNS server address if DHCP6 offer provides.
  1151. //
  1152. if (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER] != NULL) {
  1153. Private->DnsServer = AllocateZeroPool (NTOHS (Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->OpLen));
  1154. if (Private->DnsServer == NULL) {
  1155. return EFI_OUT_OF_RESOURCES;
  1156. }
  1157. CopyMem (Private->DnsServer, Cache6->OptList[PXEBC_DHCP6_IDX_DNS_SERVER]->Data, sizeof (EFI_IPv6_ADDRESS));
  1158. }
  1159. if (Cache6->OfferType == PxeOfferTypeDhcpBinl) {
  1160. //
  1161. // DhcpBinl offer is selected, so need try to request bootfilename by this offer.
  1162. //
  1163. if (EFI_ERROR (PxeBcRetryDhcp6Binl (Private, SelectIndex))) {
  1164. Status = EFI_NO_RESPONSE;
  1165. }
  1166. } else if (Cache6->OfferType == PxeOfferTypeDhcpOnly) {
  1167. if (Private->IsProxyRecved) {
  1168. //
  1169. // DhcpOnly offer is selected, so need try to request bootfilename.
  1170. //
  1171. ProxyIndex = 0;
  1172. if (Private->IsOfferSorted) {
  1173. //
  1174. // The proxy offer should be determined if select by default policy.
  1175. // IsOfferSorted means all offers are labeled by OfferIndex.
  1176. //
  1177. ASSERT (Private->OfferCount[Private->SelectProxyType] > 0);
  1178. if (Private->SelectProxyType == PxeOfferTypeProxyBinl) {
  1179. //
  1180. // Try all the cached ProxyBinl offer one by one to request bootfilename.
  1181. //
  1182. for (Index = 0; Index < Private->OfferCount[Private->SelectProxyType]; Index++) {
  1183. ProxyIndex = Private->OfferIndex[Private->SelectProxyType][Index];
  1184. if (!EFI_ERROR (PxeBcRetryDhcp6Binl (Private, ProxyIndex))) {
  1185. break;
  1186. }
  1187. }
  1188. if (Index == Private->OfferCount[Private->SelectProxyType]) {
  1189. Status = EFI_NO_RESPONSE;
  1190. }
  1191. } else {
  1192. //
  1193. // For other proxy offers (pxe10 or wfm11a), only one is buffered.
  1194. //
  1195. ProxyIndex = Private->OfferIndex[Private->SelectProxyType][0];
  1196. }
  1197. } else {
  1198. //
  1199. // The proxy offer should not be determined if select by received order.
  1200. //
  1201. Status = EFI_NO_RESPONSE;
  1202. for (Index = 0; Index < Private->OfferNum; Index++) {
  1203. OfferType = Private->OfferBuffer[Index].Dhcp6.OfferType;
  1204. if (!IS_PROXY_OFFER (OfferType)) {
  1205. //
  1206. // Skip non proxy dhcp offers.
  1207. //
  1208. continue;
  1209. }
  1210. if (OfferType == PxeOfferTypeProxyBinl) {
  1211. //
  1212. // Try all the cached ProxyBinl offer one by one to request bootfilename.
  1213. //
  1214. if (EFI_ERROR (PxeBcRetryDhcp6Binl (Private, Index))) {
  1215. continue;
  1216. }
  1217. }
  1218. Private->SelectProxyType = OfferType;
  1219. ProxyIndex = Index;
  1220. Status = EFI_SUCCESS;
  1221. break;
  1222. }
  1223. }
  1224. if (!EFI_ERROR (Status) && (Private->SelectProxyType != PxeOfferTypeProxyBinl)) {
  1225. //
  1226. // Success to try to request by a ProxyPxe10 or ProxyWfm11a offer, copy and parse it.
  1227. //
  1228. Status = PxeBcCopyDhcp6Proxy (Private, ProxyIndex);
  1229. }
  1230. } else {
  1231. //
  1232. // Otherwise, the bootfilename must be included in DhcpOnly offer.
  1233. //
  1234. ASSERT (Cache6->OptList[PXEBC_DHCP6_IDX_BOOT_FILE_URL] != NULL);
  1235. }
  1236. }
  1237. if (!EFI_ERROR (Status)) {
  1238. //
  1239. // All PXE boot information is ready by now.
  1240. //
  1241. Status = PxeBcCopyDhcp6Ack (Private, &Private->DhcpAck.Dhcp6.Packet.Ack, TRUE);
  1242. Private->PxeBc.Mode->DhcpDiscoverValid = TRUE;
  1243. }
  1244. return Status;
  1245. }
  1246. /**
  1247. Unregister the address by Ip6Config protocol.
  1248. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1249. **/
  1250. VOID
  1251. PxeBcUnregisterIp6Address (
  1252. IN PXEBC_PRIVATE_DATA *Private
  1253. )
  1254. {
  1255. if (Private->Ip6Policy != PXEBC_IP6_POLICY_MAX) {
  1256. //
  1257. // PXE driver change the policy of IP6 driver, it's a chance to recover.
  1258. // Keep the point and there is no enough requirements to do recovery.
  1259. //
  1260. }
  1261. }
  1262. /**
  1263. Check whether IP driver could route the message which will be sent to ServerIp address.
  1264. This function will check the IP6 route table every 1 seconds until specified timeout is expired, if a valid
  1265. route is found in IP6 route table, the address will be filed in GatewayAddr and return.
  1266. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1267. @param[in] TimeOutInSecond Timeout value in seconds.
  1268. @param[out] GatewayAddr Pointer to store the gateway IP address.
  1269. @retval EFI_SUCCESS Found a valid gateway address successfully.
  1270. @retval EFI_TIMEOUT The operation is time out.
  1271. @retval Other Unexpected error happened.
  1272. **/
  1273. EFI_STATUS
  1274. PxeBcCheckRouteTable (
  1275. IN PXEBC_PRIVATE_DATA *Private,
  1276. IN UINTN TimeOutInSecond,
  1277. OUT EFI_IPv6_ADDRESS *GatewayAddr
  1278. )
  1279. {
  1280. EFI_STATUS Status;
  1281. EFI_IP6_PROTOCOL *Ip6;
  1282. EFI_IP6_MODE_DATA Ip6ModeData;
  1283. UINTN Index;
  1284. EFI_EVENT TimeOutEvt;
  1285. UINTN RetryCount;
  1286. BOOLEAN GatewayIsFound;
  1287. ASSERT (GatewayAddr != NULL);
  1288. ASSERT (Private != NULL);
  1289. Ip6 = Private->Ip6;
  1290. GatewayIsFound = FALSE;
  1291. RetryCount = 0;
  1292. TimeOutEvt = NULL;
  1293. ZeroMem (GatewayAddr, sizeof (EFI_IPv6_ADDRESS));
  1294. while (TRUE) {
  1295. Status = Ip6->GetModeData (Ip6, &Ip6ModeData, NULL, NULL);
  1296. if (EFI_ERROR (Status)) {
  1297. goto ON_EXIT;
  1298. }
  1299. //
  1300. // Find out the gateway address which can route the message which send to ServerIp.
  1301. //
  1302. for (Index = 0; Index < Ip6ModeData.RouteCount; Index++) {
  1303. if (NetIp6IsNetEqual (&Private->ServerIp.v6, &Ip6ModeData.RouteTable[Index].Destination, Ip6ModeData.RouteTable[Index].PrefixLength)) {
  1304. IP6_COPY_ADDRESS (GatewayAddr, &Ip6ModeData.RouteTable[Index].Gateway);
  1305. GatewayIsFound = TRUE;
  1306. break;
  1307. }
  1308. }
  1309. if (Ip6ModeData.AddressList != NULL) {
  1310. FreePool (Ip6ModeData.AddressList);
  1311. }
  1312. if (Ip6ModeData.GroupTable != NULL) {
  1313. FreePool (Ip6ModeData.GroupTable);
  1314. }
  1315. if (Ip6ModeData.RouteTable != NULL) {
  1316. FreePool (Ip6ModeData.RouteTable);
  1317. }
  1318. if (Ip6ModeData.NeighborCache != NULL) {
  1319. FreePool (Ip6ModeData.NeighborCache);
  1320. }
  1321. if (Ip6ModeData.PrefixTable != NULL) {
  1322. FreePool (Ip6ModeData.PrefixTable);
  1323. }
  1324. if (Ip6ModeData.IcmpTypeList != NULL) {
  1325. FreePool (Ip6ModeData.IcmpTypeList);
  1326. }
  1327. if (GatewayIsFound || (RetryCount == TimeOutInSecond)) {
  1328. break;
  1329. }
  1330. RetryCount++;
  1331. //
  1332. // Delay 1 second then recheck it again.
  1333. //
  1334. if (TimeOutEvt == NULL) {
  1335. Status = gBS->CreateEvent (
  1336. EVT_TIMER,
  1337. TPL_CALLBACK,
  1338. NULL,
  1339. NULL,
  1340. &TimeOutEvt
  1341. );
  1342. if (EFI_ERROR (Status)) {
  1343. goto ON_EXIT;
  1344. }
  1345. }
  1346. Status = gBS->SetTimer (TimeOutEvt, TimerRelative, TICKS_PER_SECOND);
  1347. if (EFI_ERROR (Status)) {
  1348. goto ON_EXIT;
  1349. }
  1350. while (EFI_ERROR (gBS->CheckEvent (TimeOutEvt))) {
  1351. Ip6->Poll (Ip6);
  1352. }
  1353. }
  1354. ON_EXIT:
  1355. if (TimeOutEvt != NULL) {
  1356. gBS->CloseEvent (TimeOutEvt);
  1357. }
  1358. if (GatewayIsFound) {
  1359. Status = EFI_SUCCESS;
  1360. } else if (RetryCount == TimeOutInSecond) {
  1361. Status = EFI_TIMEOUT;
  1362. }
  1363. return Status;
  1364. }
  1365. /**
  1366. Register the ready station address and gateway by Ip6Config protocol.
  1367. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1368. @param[in] Address The pointer to the ready address.
  1369. @retval EFI_SUCCESS Registered the address successfully.
  1370. @retval Others Failed to register the address.
  1371. **/
  1372. EFI_STATUS
  1373. PxeBcRegisterIp6Address (
  1374. IN PXEBC_PRIVATE_DATA *Private,
  1375. IN EFI_IPv6_ADDRESS *Address
  1376. )
  1377. {
  1378. EFI_IP6_PROTOCOL *Ip6;
  1379. EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
  1380. EFI_IP6_CONFIG_POLICY Policy;
  1381. EFI_IP6_CONFIG_MANUAL_ADDRESS CfgAddr;
  1382. EFI_IPv6_ADDRESS GatewayAddr;
  1383. UINTN DataSize;
  1384. EFI_EVENT MappedEvt;
  1385. EFI_STATUS Status;
  1386. BOOLEAN NoGateway;
  1387. EFI_IPv6_ADDRESS *Ip6Addr;
  1388. UINTN Index;
  1389. Status = EFI_SUCCESS;
  1390. MappedEvt = NULL;
  1391. Ip6Addr = NULL;
  1392. DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
  1393. Ip6Cfg = Private->Ip6Cfg;
  1394. Ip6 = Private->Ip6;
  1395. NoGateway = FALSE;
  1396. ZeroMem (&CfgAddr, sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS));
  1397. CopyMem (&CfgAddr.Address, Address, sizeof (EFI_IPv6_ADDRESS));
  1398. Status = Ip6->Configure (Ip6, &Private->Ip6CfgData);
  1399. if (EFI_ERROR (Status)) {
  1400. goto ON_EXIT;
  1401. }
  1402. //
  1403. // Retrieve the gateway address from IP6 route table.
  1404. //
  1405. Status = PxeBcCheckRouteTable (Private, PXEBC_IP6_ROUTE_TABLE_TIMEOUT, &GatewayAddr);
  1406. if (EFI_ERROR (Status)) {
  1407. NoGateway = TRUE;
  1408. }
  1409. //
  1410. // There is no channel between IP6 and PXE driver about address setting,
  1411. // so it has to set the new address by Ip6ConfigProtocol manually.
  1412. //
  1413. Policy = Ip6ConfigPolicyManual;
  1414. Status = Ip6Cfg->SetData (
  1415. Ip6Cfg,
  1416. Ip6ConfigDataTypePolicy,
  1417. sizeof (EFI_IP6_CONFIG_POLICY),
  1418. &Policy
  1419. );
  1420. if (EFI_ERROR (Status)) {
  1421. //
  1422. // There is no need to recover later.
  1423. //
  1424. Private->Ip6Policy = PXEBC_IP6_POLICY_MAX;
  1425. goto ON_EXIT;
  1426. }
  1427. //
  1428. // Create a notify event to set address flag when DAD if IP6 driver succeeded.
  1429. //
  1430. Status = gBS->CreateEvent (
  1431. EVT_NOTIFY_SIGNAL,
  1432. TPL_NOTIFY,
  1433. PxeBcCommonNotify,
  1434. &Private->IsAddressOk,
  1435. &MappedEvt
  1436. );
  1437. if (EFI_ERROR (Status)) {
  1438. goto ON_EXIT;
  1439. }
  1440. Private->IsAddressOk = FALSE;
  1441. Status = Ip6Cfg->RegisterDataNotify (
  1442. Ip6Cfg,
  1443. Ip6ConfigDataTypeManualAddress,
  1444. MappedEvt
  1445. );
  1446. if (EFI_ERROR (Status)) {
  1447. goto ON_EXIT;
  1448. }
  1449. Status = Ip6Cfg->SetData (
  1450. Ip6Cfg,
  1451. Ip6ConfigDataTypeManualAddress,
  1452. sizeof (EFI_IP6_CONFIG_MANUAL_ADDRESS),
  1453. &CfgAddr
  1454. );
  1455. if (EFI_ERROR (Status) && (Status != EFI_NOT_READY)) {
  1456. goto ON_EXIT;
  1457. } else if (Status == EFI_NOT_READY) {
  1458. //
  1459. // Poll the network until the asynchronous process is finished.
  1460. //
  1461. while (!Private->IsAddressOk) {
  1462. Ip6->Poll (Ip6);
  1463. }
  1464. //
  1465. // Check whether the IP6 address setting is successed.
  1466. //
  1467. DataSize = 0;
  1468. Status = Ip6Cfg->GetData (
  1469. Ip6Cfg,
  1470. Ip6ConfigDataTypeManualAddress,
  1471. &DataSize,
  1472. NULL
  1473. );
  1474. if ((Status != EFI_BUFFER_TOO_SMALL) || (DataSize == 0)) {
  1475. Status = EFI_DEVICE_ERROR;
  1476. goto ON_EXIT;
  1477. }
  1478. Ip6Addr = AllocatePool (DataSize);
  1479. if (Ip6Addr == NULL) {
  1480. return EFI_OUT_OF_RESOURCES;
  1481. }
  1482. Status = Ip6Cfg->GetData (
  1483. Ip6Cfg,
  1484. Ip6ConfigDataTypeManualAddress,
  1485. &DataSize,
  1486. (VOID *)Ip6Addr
  1487. );
  1488. if (EFI_ERROR (Status)) {
  1489. Status = EFI_DEVICE_ERROR;
  1490. goto ON_EXIT;
  1491. }
  1492. for (Index = 0; Index < DataSize / sizeof (EFI_IPv6_ADDRESS); Index++) {
  1493. if (CompareMem (Ip6Addr + Index, Address, sizeof (EFI_IPv6_ADDRESS)) == 0) {
  1494. break;
  1495. }
  1496. }
  1497. if (Index == DataSize / sizeof (EFI_IPv6_ADDRESS)) {
  1498. Status = EFI_ABORTED;
  1499. goto ON_EXIT;
  1500. }
  1501. }
  1502. //
  1503. // Set the default gateway address back if needed.
  1504. //
  1505. if (!NoGateway && !NetIp6IsUnspecifiedAddr (&GatewayAddr)) {
  1506. Status = Ip6Cfg->SetData (
  1507. Ip6Cfg,
  1508. Ip6ConfigDataTypeGateway,
  1509. sizeof (EFI_IPv6_ADDRESS),
  1510. &GatewayAddr
  1511. );
  1512. if (EFI_ERROR (Status)) {
  1513. goto ON_EXIT;
  1514. }
  1515. }
  1516. ON_EXIT:
  1517. if (MappedEvt != NULL) {
  1518. Ip6Cfg->UnregisterDataNotify (
  1519. Ip6Cfg,
  1520. Ip6ConfigDataTypeManualAddress,
  1521. MappedEvt
  1522. );
  1523. gBS->CloseEvent (MappedEvt);
  1524. }
  1525. if (Ip6Addr != NULL) {
  1526. FreePool (Ip6Addr);
  1527. }
  1528. return Status;
  1529. }
  1530. /**
  1531. Set the IP6 policy to Automatic.
  1532. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1533. @retval EFI_SUCCESS Switch the IP policy successfully.
  1534. @retval Others Unexpected error happened.
  1535. **/
  1536. EFI_STATUS
  1537. PxeBcSetIp6Policy (
  1538. IN PXEBC_PRIVATE_DATA *Private
  1539. )
  1540. {
  1541. EFI_IP6_CONFIG_POLICY Policy;
  1542. EFI_STATUS Status;
  1543. EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
  1544. UINTN DataSize;
  1545. Ip6Cfg = Private->Ip6Cfg;
  1546. DataSize = sizeof (EFI_IP6_CONFIG_POLICY);
  1547. //
  1548. // Get and store the current policy of IP6 driver.
  1549. //
  1550. Status = Ip6Cfg->GetData (
  1551. Ip6Cfg,
  1552. Ip6ConfigDataTypePolicy,
  1553. &DataSize,
  1554. &Private->Ip6Policy
  1555. );
  1556. if (EFI_ERROR (Status)) {
  1557. return Status;
  1558. }
  1559. if (Private->Ip6Policy == Ip6ConfigPolicyManual) {
  1560. Policy = Ip6ConfigPolicyAutomatic;
  1561. Status = Ip6Cfg->SetData (
  1562. Ip6Cfg,
  1563. Ip6ConfigDataTypePolicy,
  1564. sizeof (EFI_IP6_CONFIG_POLICY),
  1565. &Policy
  1566. );
  1567. if (EFI_ERROR (Status)) {
  1568. //
  1569. // There is no need to recover later.
  1570. //
  1571. Private->Ip6Policy = PXEBC_IP6_POLICY_MAX;
  1572. }
  1573. }
  1574. return Status;
  1575. }
  1576. /**
  1577. This function will register the station IP address and flush IP instance to start using the new IP address.
  1578. @param[in] Private The pointer to PXEBC_PRIVATE_DATA.
  1579. @retval EFI_SUCCESS The new IP address has been configured successfully.
  1580. @retval Others Failed to configure the address.
  1581. **/
  1582. EFI_STATUS
  1583. PxeBcSetIp6Address (
  1584. IN PXEBC_PRIVATE_DATA *Private
  1585. )
  1586. {
  1587. EFI_STATUS Status;
  1588. EFI_DHCP6_PROTOCOL *Dhcp6;
  1589. Dhcp6 = Private->Dhcp6;
  1590. CopyMem (&Private->StationIp.v6, &Private->TmpStationIp.v6, sizeof (EFI_IPv6_ADDRESS));
  1591. CopyMem (&Private->PxeBc.Mode->StationIp.v6, &Private->StationIp.v6, sizeof (EFI_IPv6_ADDRESS));
  1592. Status = PxeBcRegisterIp6Address (Private, &Private->StationIp.v6);
  1593. if (EFI_ERROR (Status)) {
  1594. Dhcp6->Stop (Dhcp6);
  1595. return Status;
  1596. }
  1597. Status = PxeBcFlushStationIp (Private, &Private->StationIp, NULL);
  1598. if (EFI_ERROR (Status)) {
  1599. PxeBcUnregisterIp6Address (Private);
  1600. Dhcp6->Stop (Dhcp6);
  1601. return Status;
  1602. }
  1603. AsciiPrint ("\n Station IP address is ");
  1604. PxeBcShowIp6Addr (&Private->StationIp.v6);
  1605. return EFI_SUCCESS;
  1606. }
  1607. /**
  1608. EFI_DHCP6_CALLBACK is provided by the consumer of the EFI DHCPv6 Protocol driver
  1609. to intercept events that occurred in the configuration process.
  1610. @param[in] This The pointer to the EFI DHCPv6 Protocol.
  1611. @param[in] Context The pointer to the context set by EFI_DHCP6_PROTOCOL.Configure().
  1612. @param[in] CurrentState The current operational state of the EFI DHCPv Protocol driver.
  1613. @param[in] Dhcp6Event The event that occurs in the current state, which usually means a
  1614. state transition.
  1615. @param[in] Packet The DHCPv6 packet that is going to be sent or was already received.
  1616. @param[out] NewPacket The packet that is used to replace the Packet above.
  1617. @retval EFI_SUCCESS Told the EFI DHCPv6 Protocol driver to continue the DHCP process.
  1618. @retval EFI_NOT_READY Only used in the Dhcp6Selecting state. The EFI DHCPv6 Protocol
  1619. driver will continue to wait for more packets.
  1620. @retval EFI_ABORTED Told the EFI DHCPv6 Protocol driver to abort the current process.
  1621. **/
  1622. EFI_STATUS
  1623. EFIAPI
  1624. PxeBcDhcp6CallBack (
  1625. IN EFI_DHCP6_PROTOCOL *This,
  1626. IN VOID *Context,
  1627. IN EFI_DHCP6_STATE CurrentState,
  1628. IN EFI_DHCP6_EVENT Dhcp6Event,
  1629. IN EFI_DHCP6_PACKET *Packet,
  1630. OUT EFI_DHCP6_PACKET **NewPacket OPTIONAL
  1631. )
  1632. {
  1633. PXEBC_PRIVATE_DATA *Private;
  1634. EFI_PXE_BASE_CODE_MODE *Mode;
  1635. EFI_PXE_BASE_CODE_CALLBACK_PROTOCOL *Callback;
  1636. EFI_DHCP6_PACKET *SelectAd;
  1637. EFI_STATUS Status;
  1638. BOOLEAN Received;
  1639. if ((Dhcp6Event != Dhcp6RcvdAdvertise) &&
  1640. (Dhcp6Event != Dhcp6SelectAdvertise) &&
  1641. (Dhcp6Event != Dhcp6SendSolicit) &&
  1642. (Dhcp6Event != Dhcp6SendRequest) &&
  1643. (Dhcp6Event != Dhcp6RcvdReply))
  1644. {
  1645. return EFI_SUCCESS;
  1646. }
  1647. ASSERT (Packet != NULL);
  1648. Private = (PXEBC_PRIVATE_DATA *)Context;
  1649. Mode = Private->PxeBc.Mode;
  1650. Callback = Private->PxeBcCallback;
  1651. //
  1652. // Callback to user when any traffic occurred if has.
  1653. //
  1654. if ((Dhcp6Event != Dhcp6SelectAdvertise) && (Callback != NULL)) {
  1655. Received = (BOOLEAN)(Dhcp6Event == Dhcp6RcvdAdvertise || Dhcp6Event == Dhcp6RcvdReply);
  1656. Status = Callback->Callback (
  1657. Callback,
  1658. Private->Function,
  1659. Received,
  1660. Packet->Length,
  1661. (EFI_PXE_BASE_CODE_PACKET *)&Packet->Dhcp6
  1662. );
  1663. if (Status != EFI_PXE_BASE_CODE_CALLBACK_STATUS_CONTINUE) {
  1664. return EFI_ABORTED;
  1665. }
  1666. }
  1667. Status = EFI_SUCCESS;
  1668. switch (Dhcp6Event) {
  1669. case Dhcp6SendSolicit:
  1670. if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {
  1671. //
  1672. // If the to be sent packet exceeds the maximum length, abort the DHCP process.
  1673. //
  1674. Status = EFI_ABORTED;
  1675. break;
  1676. }
  1677. //
  1678. // Record the first Solicate msg time
  1679. //
  1680. if (Private->SolicitTimes == 0) {
  1681. CalcElapsedTime (Private);
  1682. Private->SolicitTimes++;
  1683. }
  1684. //
  1685. // Cache the dhcp discover packet to mode data directly.
  1686. //
  1687. CopyMem (&Mode->DhcpDiscover.Dhcpv4, &Packet->Dhcp6, Packet->Length);
  1688. break;
  1689. case Dhcp6RcvdAdvertise:
  1690. Status = EFI_NOT_READY;
  1691. if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {
  1692. //
  1693. // Ignore the incoming packets which exceed the maximum length.
  1694. //
  1695. break;
  1696. }
  1697. if (Private->OfferNum < PXEBC_OFFER_MAX_NUM) {
  1698. //
  1699. // Cache the dhcp offers to OfferBuffer[] for select later, and record
  1700. // the OfferIndex and OfferCount.
  1701. //
  1702. PxeBcCacheDhcp6Offer (Private, Packet);
  1703. }
  1704. break;
  1705. case Dhcp6SendRequest:
  1706. if (Packet->Length > PXEBC_DHCP6_PACKET_MAX_SIZE) {
  1707. //
  1708. // If the to be sent packet exceeds the maximum length, abort the DHCP process.
  1709. //
  1710. Status = EFI_ABORTED;
  1711. break;
  1712. }
  1713. //
  1714. // Store the request packet as seed packet for discover.
  1715. //
  1716. if (Private->Dhcp6Request != NULL) {
  1717. FreePool (Private->Dhcp6Request);
  1718. }
  1719. Private->Dhcp6Request = AllocateZeroPool (Packet->Size);
  1720. if (Private->Dhcp6Request != NULL) {
  1721. CopyMem (Private->Dhcp6Request, Packet, Packet->Size);
  1722. }
  1723. break;
  1724. case Dhcp6SelectAdvertise:
  1725. //
  1726. // Select offer by the default policy or by order, and record the SelectIndex
  1727. // and SelectProxyType.
  1728. //
  1729. PxeBcSelectDhcp6Offer (Private);
  1730. if (Private->SelectIndex == 0) {
  1731. Status = EFI_ABORTED;
  1732. } else {
  1733. ASSERT (NewPacket != NULL);
  1734. SelectAd = &Private->OfferBuffer[Private->SelectIndex - 1].Dhcp6.Packet.Offer;
  1735. *NewPacket = AllocateZeroPool (SelectAd->Size);
  1736. ASSERT (*NewPacket != NULL);
  1737. if (*NewPacket == NULL) {
  1738. return EFI_ABORTED;
  1739. }
  1740. CopyMem (*NewPacket, SelectAd, SelectAd->Size);
  1741. }
  1742. break;
  1743. case Dhcp6RcvdReply:
  1744. //
  1745. // Cache the dhcp ack to Private->Dhcp6Ack, but it's not the final ack in mode data
  1746. // without verification.
  1747. //
  1748. ASSERT (Private->SelectIndex != 0);
  1749. Status = PxeBcCopyDhcp6Ack (Private, Packet, FALSE);
  1750. if (EFI_ERROR (Status)) {
  1751. Status = EFI_ABORTED;
  1752. }
  1753. break;
  1754. default:
  1755. ASSERT (0);
  1756. }
  1757. return Status;
  1758. }
  1759. /**
  1760. Build and send out the request packet for the bootfile, and parse the reply.
  1761. @param[in] Private The pointer to PxeBc private data.
  1762. @param[in] Type PxeBc option boot item type.
  1763. @param[in] Layer The pointer to option boot item layer.
  1764. @param[in] UseBis Use BIS or not.
  1765. @param[in] DestIp The pointer to the server address.
  1766. @retval EFI_SUCCESS Successfully discovered the boot file.
  1767. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
  1768. @retval EFI_NOT_FOUND Can't get the PXE reply packet.
  1769. @retval Others Failed to discover the boot file.
  1770. **/
  1771. EFI_STATUS
  1772. PxeBcDhcp6Discover (
  1773. IN PXEBC_PRIVATE_DATA *Private,
  1774. IN UINT16 Type,
  1775. IN UINT16 *Layer,
  1776. IN BOOLEAN UseBis,
  1777. IN EFI_IP_ADDRESS *DestIp
  1778. )
  1779. {
  1780. EFI_PXE_BASE_CODE_UDP_PORT SrcPort;
  1781. EFI_PXE_BASE_CODE_UDP_PORT DestPort;
  1782. EFI_PXE_BASE_CODE_MODE *Mode;
  1783. EFI_PXE_BASE_CODE_PROTOCOL *PxeBc;
  1784. EFI_PXE_BASE_CODE_DHCPV6_PACKET *Discover;
  1785. UINTN DiscoverLen;
  1786. EFI_DHCP6_PACKET *Request;
  1787. UINTN RequestLen;
  1788. EFI_DHCP6_PACKET *Reply;
  1789. UINT8 *RequestOpt;
  1790. UINT8 *DiscoverOpt;
  1791. UINTN ReadSize;
  1792. UINT16 OpCode;
  1793. UINT16 OpLen;
  1794. UINT32 Xid;
  1795. EFI_STATUS Status;
  1796. PxeBc = &Private->PxeBc;
  1797. Mode = PxeBc->Mode;
  1798. Request = Private->Dhcp6Request;
  1799. SrcPort = PXEBC_BS_DISCOVER_PORT;
  1800. DestPort = PXEBC_BS_DISCOVER_PORT;
  1801. if (!UseBis && (Layer != NULL)) {
  1802. *Layer &= EFI_PXE_BASE_CODE_BOOT_LAYER_MASK;
  1803. }
  1804. if (Request == NULL) {
  1805. return EFI_DEVICE_ERROR;
  1806. }
  1807. Discover = AllocateZeroPool (sizeof (EFI_PXE_BASE_CODE_DHCPV6_PACKET));
  1808. if (Discover == NULL) {
  1809. return EFI_OUT_OF_RESOURCES;
  1810. }
  1811. //
  1812. // Build the discover packet by the cached request packet before.
  1813. //
  1814. Xid = NET_RANDOM (NetRandomInitSeed ());
  1815. Discover->TransactionId = HTONL (Xid);
  1816. Discover->MessageType = Request->Dhcp6.Header.MessageType;
  1817. RequestOpt = Request->Dhcp6.Option;
  1818. DiscoverOpt = Discover->DhcpOptions;
  1819. DiscoverLen = sizeof (EFI_DHCP6_HEADER);
  1820. RequestLen = DiscoverLen;
  1821. while (RequestLen < Request->Length) {
  1822. OpCode = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpCode);
  1823. OpLen = NTOHS (((EFI_DHCP6_PACKET_OPTION *)RequestOpt)->OpLen);
  1824. if ((OpCode != EFI_DHCP6_IA_TYPE_NA) &&
  1825. (OpCode != EFI_DHCP6_IA_TYPE_TA))
  1826. {
  1827. //
  1828. // Copy all the options except IA option.
  1829. //
  1830. CopyMem (DiscoverOpt, RequestOpt, OpLen + 4);
  1831. DiscoverOpt += (OpLen + 4);
  1832. DiscoverLen += (OpLen + 4);
  1833. }
  1834. RequestOpt += (OpLen + 4);
  1835. RequestLen += (OpLen + 4);
  1836. }
  1837. Status = PxeBc->UdpWrite (
  1838. PxeBc,
  1839. 0,
  1840. &Private->ServerIp,
  1841. &DestPort,
  1842. NULL,
  1843. &Private->StationIp,
  1844. &SrcPort,
  1845. NULL,
  1846. NULL,
  1847. &DiscoverLen,
  1848. (VOID *)Discover
  1849. );
  1850. if (EFI_ERROR (Status)) {
  1851. goto ON_ERROR;
  1852. }
  1853. //
  1854. // Cache the right PXE reply packet here, set valid flag later.
  1855. // Especially for PXE discover packet, store it into mode data here.
  1856. //
  1857. if (Private->IsDoDiscover) {
  1858. CopyMem (&Mode->PxeDiscover.Dhcpv6, Discover, DiscoverLen);
  1859. Reply = &Private->PxeReply.Dhcp6.Packet.Ack;
  1860. } else {
  1861. Reply = &Private->ProxyOffer.Dhcp6.Packet.Offer;
  1862. }
  1863. ReadSize = (UINTN)Reply->Size;
  1864. //
  1865. // Start Udp6Read instance
  1866. //
  1867. Status = Private->Udp6Read->Configure (Private->Udp6Read, &Private->Udp6CfgData);
  1868. if (EFI_ERROR (Status)) {
  1869. goto ON_ERROR;
  1870. }
  1871. Status = PxeBc->UdpRead (
  1872. PxeBc,
  1873. EFI_PXE_BASE_CODE_UDP_OPFLAGS_ANY_DEST_IP,
  1874. NULL,
  1875. &SrcPort,
  1876. &Private->ServerIp,
  1877. &DestPort,
  1878. NULL,
  1879. NULL,
  1880. &ReadSize,
  1881. (VOID *)&Reply->Dhcp6
  1882. );
  1883. //
  1884. // Stop Udp6Read instance
  1885. //
  1886. Private->Udp6Read->Configure (Private->Udp6Read, NULL);
  1887. if (EFI_ERROR (Status)) {
  1888. goto ON_ERROR;
  1889. }
  1890. return EFI_SUCCESS;
  1891. ON_ERROR:
  1892. if (Discover != NULL) {
  1893. FreePool (Discover);
  1894. }
  1895. return Status;
  1896. }
  1897. /**
  1898. Start the DHCPv6 S.A.R.R. process to acquire the IPv6 address and other PXE boot information.
  1899. @param[in] Private The pointer to PxeBc private data.
  1900. @param[in] Dhcp6 The pointer to the EFI_DHCP6_PROTOCOL
  1901. @retval EFI_SUCCESS The S.A.R.R. process successfully finished.
  1902. @retval Others Failed to finish the S.A.R.R. process.
  1903. **/
  1904. EFI_STATUS
  1905. PxeBcDhcp6Sarr (
  1906. IN PXEBC_PRIVATE_DATA *Private,
  1907. IN EFI_DHCP6_PROTOCOL *Dhcp6
  1908. )
  1909. {
  1910. EFI_PXE_BASE_CODE_MODE *PxeMode;
  1911. EFI_DHCP6_CONFIG_DATA Config;
  1912. EFI_DHCP6_MODE_DATA Mode;
  1913. EFI_DHCP6_RETRANSMISSION *Retransmit;
  1914. EFI_DHCP6_PACKET_OPTION *OptList[PXEBC_DHCP6_OPTION_MAX_NUM];
  1915. UINT8 Buffer[PXEBC_DHCP6_OPTION_MAX_SIZE];
  1916. UINT32 OptCount;
  1917. EFI_STATUS Status;
  1918. EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;
  1919. EFI_STATUS TimerStatus;
  1920. EFI_EVENT Timer;
  1921. UINT64 GetMappingTimeOut;
  1922. UINTN DataSize;
  1923. EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS DadXmits;
  1924. Status = EFI_SUCCESS;
  1925. PxeMode = Private->PxeBc.Mode;
  1926. Ip6Cfg = Private->Ip6Cfg;
  1927. Timer = NULL;
  1928. //
  1929. // Build option list for the request packet.
  1930. //
  1931. OptCount = PxeBcBuildDhcp6Options (Private, OptList, Buffer);
  1932. ASSERT (OptCount > 0);
  1933. Retransmit = AllocateZeroPool (sizeof (EFI_DHCP6_RETRANSMISSION));
  1934. if (Retransmit == NULL) {
  1935. return EFI_OUT_OF_RESOURCES;
  1936. }
  1937. ZeroMem (&Mode, sizeof (EFI_DHCP6_MODE_DATA));
  1938. ZeroMem (&Config, sizeof (EFI_DHCP6_CONFIG_DATA));
  1939. Config.OptionCount = OptCount;
  1940. Config.OptionList = OptList;
  1941. Config.Dhcp6Callback = PxeBcDhcp6CallBack;
  1942. Config.CallbackContext = Private;
  1943. Config.IaInfoEvent = NULL;
  1944. Config.RapidCommit = FALSE;
  1945. Config.ReconfigureAccept = FALSE;
  1946. Config.IaDescriptor.IaId = Private->IaId;
  1947. Config.IaDescriptor.Type = EFI_DHCP6_IA_TYPE_NA;
  1948. Config.SolicitRetransmission = Retransmit;
  1949. Retransmit->Irt = 4;
  1950. Retransmit->Mrc = 4;
  1951. Retransmit->Mrt = 32;
  1952. Retransmit->Mrd = 60;
  1953. //
  1954. // Configure the DHCPv6 instance for PXE boot.
  1955. //
  1956. Status = Dhcp6->Configure (Dhcp6, &Config);
  1957. FreePool (Retransmit);
  1958. if (EFI_ERROR (Status)) {
  1959. return Status;
  1960. }
  1961. //
  1962. // Initialize the record fields for DHCPv6 offer in private data.
  1963. //
  1964. Private->IsProxyRecved = FALSE;
  1965. Private->OfferNum = 0;
  1966. Private->SelectIndex = 0;
  1967. ZeroMem (Private->OfferCount, sizeof (Private->OfferCount));
  1968. ZeroMem (Private->OfferIndex, sizeof (Private->OfferIndex));
  1969. //
  1970. // Start DHCPv6 S.A.R.R. process to acquire IPv6 address.
  1971. //
  1972. Status = Dhcp6->Start (Dhcp6);
  1973. if (Status == EFI_NO_MAPPING) {
  1974. //
  1975. // IP6 Linklocal address is not available for use, so stop current Dhcp process
  1976. // and wait for duplicate address detection to finish.
  1977. //
  1978. Dhcp6->Stop (Dhcp6);
  1979. //
  1980. // Get Duplicate Address Detection Transmits count.
  1981. //
  1982. DataSize = sizeof (EFI_IP6_CONFIG_DUP_ADDR_DETECT_TRANSMITS);
  1983. Status = Ip6Cfg->GetData (
  1984. Ip6Cfg,
  1985. Ip6ConfigDataTypeDupAddrDetectTransmits,
  1986. &DataSize,
  1987. &DadXmits
  1988. );
  1989. if (EFI_ERROR (Status)) {
  1990. Dhcp6->Configure (Dhcp6, NULL);
  1991. return Status;
  1992. }
  1993. Status = gBS->CreateEvent (EVT_TIMER, TPL_CALLBACK, NULL, NULL, &Timer);
  1994. if (EFI_ERROR (Status)) {
  1995. Dhcp6->Configure (Dhcp6, NULL);
  1996. return Status;
  1997. }
  1998. GetMappingTimeOut = TICKS_PER_SECOND * DadXmits.DupAddrDetectTransmits + PXEBC_DAD_ADDITIONAL_DELAY;
  1999. Status = gBS->SetTimer (Timer, TimerRelative, GetMappingTimeOut);
  2000. if (EFI_ERROR (Status)) {
  2001. gBS->CloseEvent (Timer);
  2002. Dhcp6->Configure (Dhcp6, NULL);
  2003. return Status;
  2004. }
  2005. do {
  2006. TimerStatus = gBS->CheckEvent (Timer);
  2007. if (!EFI_ERROR (TimerStatus)) {
  2008. Status = Dhcp6->Start (Dhcp6);
  2009. }
  2010. } while (TimerStatus == EFI_NOT_READY);
  2011. gBS->CloseEvent (Timer);
  2012. }
  2013. if (EFI_ERROR (Status)) {
  2014. if (Status == EFI_ICMP_ERROR) {
  2015. PxeMode->IcmpErrorReceived = TRUE;
  2016. }
  2017. Dhcp6->Configure (Dhcp6, NULL);
  2018. return Status;
  2019. }
  2020. //
  2021. // Get the acquired IPv6 address and store them.
  2022. //
  2023. Status = Dhcp6->GetModeData (Dhcp6, &Mode, NULL);
  2024. if (EFI_ERROR (Status)) {
  2025. Dhcp6->Stop (Dhcp6);
  2026. return Status;
  2027. }
  2028. ASSERT ((Mode.Ia != NULL) && (Mode.Ia->State == Dhcp6Bound));
  2029. //
  2030. // DHCP6 doesn't have an option to specify the router address on the subnet, the only way to get the
  2031. // router address in IP6 is the router discovery mechanism (the RS and RA, which only be handled when
  2032. // the IP policy is Automatic). So we just hold the station IP address here and leave the IP policy as
  2033. // Automatic, until we get the server IP address. This could let IP6 driver finish the router discovery
  2034. // to find a valid router address.
  2035. //
  2036. CopyMem (&Private->TmpStationIp.v6, &Mode.Ia->IaAddress[0].IpAddress, sizeof (EFI_IPv6_ADDRESS));
  2037. if (Mode.ClientId != NULL) {
  2038. FreePool (Mode.ClientId);
  2039. }
  2040. if (Mode.Ia != NULL) {
  2041. FreePool (Mode.Ia);
  2042. }
  2043. //
  2044. // Check the selected offer whether BINL retry is needed.
  2045. //
  2046. Status = PxeBcHandleDhcp6Offer (Private);
  2047. if (EFI_ERROR (Status)) {
  2048. Dhcp6->Stop (Dhcp6);
  2049. return Status;
  2050. }
  2051. return EFI_SUCCESS;
  2052. }