]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4InitSelect.c
changed the guid assignment from constant array to hi and low UINT64s (Intel compiler...
[mirror_edk2.git] / EdkModulePkg / Universal / Network / PxeDhcp4 / Dxe / PxeDhcp4InitSelect.c
CommitLineData
878ddf1f 1/*++\r
2\r
3Copyright (c) 2006, Intel Corporation \r
4All rights reserved. This program and the accompanying materials \r
5are licensed and made available under the terms and conditions of the BSD License \r
6which accompanies this distribution. The full text of the license may be found at \r
7http://opensource.org/licenses/bsd-license.php \r
8 \r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
11\r
12Module Name:\r
13 PxeDhcp4InitSelect.c\r
14 \r
15Abstract:\r
16\r
17--*/\r
18\r
19\r
20#include "PxeDhcp4.h"\r
21\r
22#define DebugPrint(x)\r
23//\r
24// #define DebugPrint(x) Aprint x\r
25//\r
26/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
27STATIC\r
28INTN\r
29offer_verify (\r
30 IN PXE_DHCP4_PRIVATE_DATA *Private,\r
31 IN DHCP4_PACKET *tx_pkt,\r
32 IN DHCP4_PACKET *rx_pkt,\r
33 IN UINTN rx_pkt_size\r
34 )\r
35/*++\r
36 -2 = ignore, stop waiting\r
37 -1 = ignore, keep waiting\r
38 0 = accept, keep waiting\r
39 1 = accept, stop waiting\r
40--*/\r
41{\r
42 EFI_STATUS EfiStatus;\r
43 DHCP4_PACKET *tmp;\r
44 DHCP4_OP *msg_type_op;\r
45 DHCP4_OP *srvid_op;\r
46 UINT32 magik;\r
47\r
48 //\r
49 // Verify parameters. Touch unused parameters to keep\r
50 // compiler happy.\r
51 //\r
52 ASSERT (Private);\r
53 ASSERT (rx_pkt);\r
54\r
55 if (Private == NULL || rx_pkt == NULL) {\r
56 return -2;\r
57 }\r
58\r
59 tx_pkt = tx_pkt;\r
60 rx_pkt_size = rx_pkt_size;\r
61\r
62 //\r
63 // This may be a BOOTP Reply or DHCP Offer packet.\r
64 // If there is no DHCP magik number, assume that\r
65 // this is a BOOTP Reply packet.\r
66 //\r
67 magik = htonl (DHCP4_MAGIK_NUMBER);\r
68\r
69 while (!CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {\r
70 //\r
71 // If there is no DHCP message type option, assume\r
72 // this is a BOOTP reply packet and cache it.\r
73 //\r
74 EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);\r
75\r
76 if (EFI_ERROR (EfiStatus)) {\r
77 break;\r
78 }\r
79 //\r
80 // If there is a DHCP message type option, it must be a\r
81 // DHCP offer packet\r
82 //\r
83 if (msg_type_op->len != 1) {\r
84 return -1;\r
85 }\r
86\r
87 if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {\r
88 return -1;\r
89 }\r
90 //\r
91 // There must be a server identifier option.\r
92 //\r
93 EfiStatus = find_opt (\r
94 rx_pkt,\r
95 DHCP4_SERVER_IDENTIFIER,\r
96 0,\r
97 &srvid_op\r
98 );\r
99\r
100 if (EFI_ERROR (EfiStatus)) {\r
101 return -1;\r
102 }\r
103\r
104 if (srvid_op->len != 4) {\r
105 return -1;\r
106 }\r
107 //\r
108 // Good DHCP offer packet.\r
109 //\r
110 break;\r
111 }\r
112 //\r
113 // Good DHCP (or BOOTP) packet. Cache it!\r
114 //\r
115 EfiStatus = gBS->AllocatePool (\r
116 EfiBootServicesData,\r
117 (Private->offers + 1) * sizeof (DHCP4_PACKET),\r
118 (VOID **) &tmp\r
119 );\r
120\r
121 if (EFI_ERROR (EfiStatus)) {\r
122 return -2;\r
123 }\r
124\r
125 ASSERT (tmp);\r
126\r
127 if (Private->offers != 0) {\r
128 CopyMem (\r
129 tmp,\r
130 Private->offer_list,\r
131 Private->offers * sizeof (DHCP4_PACKET)\r
132 );\r
133\r
134 gBS->FreePool (Private->offer_list);\r
135 }\r
136\r
137 CopyMem (&tmp[Private->offers++], rx_pkt, sizeof (DHCP4_PACKET));\r
138\r
139 Private->offer_list = tmp;\r
140\r
141 return 0;\r
142}\r
143\r
144/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
145STATIC\r
146INTN\r
147acknak_verify (\r
148 IN PXE_DHCP4_PRIVATE_DATA *Private,\r
149 IN DHCP4_PACKET *tx_pkt,\r
150 IN DHCP4_PACKET *rx_pkt,\r
151 IN UINTN rx_pkt_size\r
152 )\r
153/*++\r
154 -2 = ignore, stop waiting\r
155 -1 = ignore, keep waiting\r
156 0 = accept, keep waiting\r
157 1 = accept, stop waiting\r
158--*/\r
159{\r
160 EFI_STATUS EfiStatus;\r
161 DHCP4_OP *msg_type_op;\r
162 DHCP4_OP *srvid_op;\r
163 DHCP4_OP *renew_op;\r
164 DHCP4_OP *rebind_op;\r
165 DHCP4_OP *lease_time_op;\r
166 UINT32 magik;\r
167\r
168 //\r
169 // Verify parameters. Touch unused parameters to\r
170 // keep compiler happy.\r
171 //\r
172 ASSERT (Private);\r
173 ASSERT (rx_pkt);\r
174\r
175 if (Private == NULL || rx_pkt == NULL) {\r
176 return -2;\r
177 }\r
178\r
179 tx_pkt = tx_pkt;\r
180 rx_pkt_size = rx_pkt_size;\r
181\r
182 //\r
183 // This must be a DHCP Ack message.\r
184 //\r
185 magik = htonl (DHCP4_MAGIK_NUMBER);\r
186\r
187 if (CompareMem (&rx_pkt->dhcp4.magik, &magik, 4)) {\r
188 return -1;\r
189 }\r
190\r
191 EfiStatus = find_opt (rx_pkt, DHCP4_MESSAGE_TYPE, 0, &msg_type_op);\r
192\r
193 if (EFI_ERROR (EfiStatus)) {\r
194 return -1;\r
195 }\r
196\r
197 if (msg_type_op->len != 1) {\r
198 return -1;\r
199 }\r
200\r
201 if (msg_type_op->data[0] != DHCP4_MESSAGE_TYPE_ACK) {\r
202 return -1;\r
203 }\r
204 //\r
205 // There must be a server identifier.\r
206 //\r
207 EfiStatus = find_opt (rx_pkt, DHCP4_SERVER_IDENTIFIER, 0, &srvid_op);\r
208\r
209 if (EFI_ERROR (EfiStatus)) {\r
210 return -1;\r
211 }\r
212\r
213 if (srvid_op->len != 4) {\r
214 return -1;\r
215 }\r
216 //\r
217 // There should be a renewal time.\r
218 // If there is not, we will default to the 7/8 of the rebinding time.\r
219 //\r
220 EfiStatus = find_opt (rx_pkt, DHCP4_RENEWAL_TIME, 0, &renew_op);\r
221\r
222 if (EFI_ERROR (EfiStatus)) {\r
223 renew_op = NULL;\r
224 } else if (renew_op->len != 4) {\r
225 renew_op = NULL;\r
226 }\r
227 //\r
228 // There should be a rebinding time.\r
229 // If there is not, we will default to 7/8 of the lease time.\r
230 //\r
231 EfiStatus = find_opt (rx_pkt, DHCP4_REBINDING_TIME, 0, &rebind_op);\r
232\r
233 if (EFI_ERROR (EfiStatus)) {\r
234 rebind_op = NULL;\r
235 } else if (rebind_op->len != 4) {\r
236 rebind_op = NULL;\r
237 }\r
238 //\r
239 // There should be a lease time.\r
240 // If there is not, we will default to one week.\r
241 //\r
242 EfiStatus = find_opt (rx_pkt, DHCP4_LEASE_TIME, 0, &lease_time_op);\r
243\r
244 if (EFI_ERROR (EfiStatus)) {\r
245 lease_time_op = NULL;\r
246 } else if (lease_time_op->len != 4) {\r
247 lease_time_op = NULL;\r
248 }\r
249 //\r
250 // Packet looks good. Double check the renew, rebind and lease times.\r
251 //\r
252 CopyMem (&Private->ServerIp, srvid_op->data, 4);\r
253\r
254 if (renew_op != NULL) {\r
255 CopyMem (&Private->RenewTime, renew_op->data, 4);\r
256 Private->RenewTime = htonl (Private->RenewTime);\r
257 } else {\r
258 Private->RenewTime = 0;\r
259 }\r
260\r
261 if (rebind_op != NULL) {\r
262 CopyMem (&Private->RebindTime, rebind_op->data, 4);\r
263 Private->RebindTime = htonl (Private->RebindTime);\r
264 } else {\r
265 Private->RebindTime = 0;\r
266 }\r
267\r
268 if (lease_time_op != NULL) {\r
269 CopyMem (&Private->LeaseTime, lease_time_op->data, 4);\r
270 Private->LeaseTime = htonl (Private->LeaseTime);\r
271 } else {\r
272 Private->LeaseTime = 0;\r
273 }\r
274\r
275 if (Private->LeaseTime < 60) {\r
276 Private->LeaseTime = 7 * 86400;\r
277 }\r
278\r
279 if (Private->RebindTime < 52 || Private->RebindTime >= Private->LeaseTime) {\r
280 Private->RebindTime = Private->LeaseTime / 2 + Private->LeaseTime / 4 + Private->LeaseTime / 8;\r
281 }\r
282\r
283 if (Private->RenewTime < 45 || Private->RenewTime >= Private->RebindTime) {\r
284 Private->RenewTime = Private->RebindTime / 2 + Private->RebindTime / 4 + Private->RebindTime / 8;\r
285 }\r
286\r
287 return 1;\r
288}\r
289\r
290/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
291EFI_STATUS\r
292EFIAPI\r
293PxeDhcp4Init (\r
294 IN EFI_PXE_DHCP4_PROTOCOL *This,\r
295 IN UINTN seconds_timeout,\r
296 OUT UINTN *Offers,\r
297 OUT DHCP4_PACKET **OfferList\r
298 )\r
299{\r
300 PXE_DHCP4_PRIVATE_DATA *Private;\r
301 DHCP4_PACKET offer;\r
302 EFI_IP_ADDRESS bcast_ip;\r
303 EFI_STATUS EfiStatus;\r
304\r
305 //\r
306 // Verify parameters and protocol state.\r
307 //\r
308 if (This == NULL ||\r
309 seconds_timeout < DHCP4_MIN_SECONDS ||\r
310 seconds_timeout > DHCP4_MAX_SECONDS ||\r
311 Offers == NULL ||\r
312 OfferList == NULL\r
313 ) {\r
314 //\r
315 // Return parameters are not initialized when\r
316 // parameters are invalid!\r
317 //\r
318 return EFI_INVALID_PARAMETER;\r
319 }\r
320\r
321 *Offers = 0;\r
322 *OfferList = NULL;\r
323\r
324 //\r
325 // Check protocol state.\r
326 //\r
327 if (This->Data == NULL) {\r
328 return EFI_NOT_STARTED;\r
329 }\r
330\r
331 if (!This->Data->SetupCompleted) {\r
332 return EFI_NOT_READY;\r
333 }\r
334\r
335#if 0\r
336 if (!is_good_discover (&This->Data->Discover)) {\r
337 //\r
338 // %%TBD - check discover packet fields\r
339 //\r
340 }\r
341#endif\r
342 //\r
343 // Get pointer to our instance data.\r
344 //\r
345 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);\r
346\r
347 if (Private == NULL) {\r
348 return EFI_INVALID_PARAMETER;\r
349 }\r
350\r
351 if (Private->PxeBc == NULL) {\r
352 return EFI_DEVICE_ERROR;\r
353 }\r
354 //\r
355 // Setup variables...\r
356 //\r
357 Private->offers = 0;\r
358 Private->offer_list = NULL;\r
359\r
360 EfiStatus = gBS->HandleProtocol (\r
361 Private->Handle,\r
362 &gEfiPxeDhcp4CallbackProtocolGuid,\r
363 (VOID *) &Private->callback\r
364 );\r
365\r
366 if (EFI_ERROR (EfiStatus)) {\r
367 Private->callback = NULL;\r
368 }\r
369\r
370 Private->function = EFI_PXE_DHCP4_FUNCTION_INIT;\r
371\r
372 //\r
373 // Increment the transaction ID.\r
374 //\r
375 {\r
376 UINT32 xid;\r
377\r
378 CopyMem (&xid, &This->Data->Discover.dhcp4.xid, sizeof (UINT32));\r
379\r
380 xid = htonl (htonl (xid) + 1);\r
381\r
382 CopyMem (&This->Data->Discover.dhcp4.xid, &xid, sizeof (UINT32));\r
383 }\r
384 //\r
385 // Transmit discover and wait for offers...\r
386 //\r
387 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
388\r
389 EfiStatus = tx_rx_udp (\r
390 Private,\r
391 &bcast_ip,\r
392 NULL,\r
393 NULL,\r
394 NULL,\r
395 &This->Data->Discover,\r
396 &offer,\r
397 &offer_verify,\r
398 seconds_timeout\r
399 );\r
400\r
401 if (EFI_ERROR (EfiStatus)) {\r
402 if (Private->offer_list) {\r
403 gBS->FreePool (Private->offer_list);\r
404 }\r
405\r
406 Private->offers = 0;\r
407 Private->offer_list = NULL;\r
408 Private->callback = NULL;\r
409\r
410 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
411 return EfiStatus;\r
412 }\r
413\r
414 *Offers = Private->offers;\r
415 *OfferList = Private->offer_list;\r
416\r
417 Private->offers = 0;\r
418 Private->offer_list = NULL;\r
419 Private->callback = NULL;\r
420\r
421 This->Data->InitCompleted = TRUE;\r
422 This->Data->SelectCompleted = FALSE;\r
423 This->Data->IsBootp = FALSE;\r
424 This->Data->IsAck = FALSE;\r
425\r
426 return EFI_SUCCESS;\r
427}\r
428\r
429/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
430EFI_STATUS\r
431EFIAPI\r
432PxeDhcp4Select (\r
433 IN EFI_PXE_DHCP4_PROTOCOL *This,\r
434 IN UINTN seconds_timeout,\r
435 IN DHCP4_PACKET *Offer\r
436 )\r
437{\r
438 PXE_DHCP4_PRIVATE_DATA *Private;\r
439 EFI_STATUS EfiStatus;\r
440 DHCP4_PACKET request;\r
441 DHCP4_PACKET acknak;\r
442 EFI_IP_ADDRESS bcast_ip;\r
443 EFI_IP_ADDRESS zero_ip;\r
444 EFI_IP_ADDRESS local_ip;\r
445 DHCP4_OP *srvid;\r
446 DHCP4_OP *op;\r
447 UINT32 dhcp4_magik;\r
448 UINT8 buf[16];\r
449 BOOLEAN is_bootp;\r
450\r
451 //\r
452 // Verify parameters.\r
453 //\r
454 if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS || Offer == NULL) {\r
455 return EFI_INVALID_PARAMETER;\r
456 }\r
457 //\r
458 // Check protocol state.\r
459 //\r
460 if (This->Data == NULL) {\r
461 return EFI_NOT_STARTED;\r
462 }\r
463\r
464 if (!This->Data->SetupCompleted) {\r
465 return EFI_NOT_READY;\r
466 }\r
467 //\r
468 // Get pointer to instance data.\r
469 //\r
470 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);\r
471\r
472 if (Private == NULL) {\r
473 return EFI_INVALID_PARAMETER;\r
474 }\r
475\r
476 if (Private->PxeBc == NULL) {\r
477 return EFI_DEVICE_ERROR;\r
478 }\r
479\r
480#if 0\r
481 if (!is_good_discover (&This->Data->Discover)) {\r
482 //\r
483 // %%TBD - check discover packet fields\r
484 //\r
485 }\r
486#endif\r
487 //\r
488 // Setup useful variables...\r
489 //\r
490 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
491\r
492 ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));\r
493\r
494 ZeroMem (&local_ip, sizeof (EFI_IP_ADDRESS));\r
495 local_ip.v4.Addr[0] = 127;\r
496 local_ip.v4.Addr[3] = 1;\r
497\r
498 This->Data->SelectCompleted = FALSE;\r
499 This->Data->IsBootp = FALSE;\r
500 This->Data->IsAck = FALSE;\r
501\r
502 EfiStatus = gBS->HandleProtocol (\r
503 Private->Handle,\r
504 &gEfiPxeDhcp4CallbackProtocolGuid,\r
505 (VOID *) &Private->callback\r
506 );\r
507\r
508 if (EFI_ERROR (EfiStatus)) {\r
509 Private->callback = NULL;\r
510 }\r
511\r
512 Private->function = EFI_PXE_DHCP4_FUNCTION_SELECT;\r
513\r
514 //\r
515 // Verify offer packet fields.\r
516 //\r
517 if (Offer->dhcp4.op != BOOTP_REPLY) {\r
518 Private->callback = NULL;\r
519 return EFI_INVALID_PARAMETER;\r
520 }\r
521\r
522 if (Offer->dhcp4.htype != This->Data->Discover.dhcp4.htype) {\r
523 Private->callback = NULL;\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526\r
527 if (Offer->dhcp4.hlen != This->Data->Discover.dhcp4.hlen) {\r
528 Private->callback = NULL;\r
529 return EFI_INVALID_PARAMETER;\r
530 }\r
531\r
532 if (CompareMem (&Offer->dhcp4.xid, &This->Data->Discover.dhcp4.xid, 4)) {\r
533 Private->callback = NULL;\r
534 return EFI_INVALID_PARAMETER;\r
535 }\r
536\r
537 if (!CompareMem (&Offer->dhcp4.yiaddr, &bcast_ip, 4)) {\r
538 Private->callback = NULL;\r
539 return EFI_INVALID_PARAMETER;\r
540 }\r
541\r
542 if (!CompareMem (&Offer->dhcp4.yiaddr, &zero_ip, 4)) {\r
543 Private->callback = NULL;\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546\r
547 if (!CompareMem (&Offer->dhcp4.yiaddr, &local_ip, 4)) {\r
548 Private->callback = NULL;\r
549 return EFI_INVALID_PARAMETER;\r
550 }\r
551\r
552 if (CompareMem (\r
553 &Offer->dhcp4.chaddr,\r
554 &This->Data->Discover.dhcp4.chaddr,\r
555 16\r
556 )) {\r
557 Private->callback = NULL;\r
558 return EFI_INVALID_PARAMETER;\r
559 }\r
560 //\r
561 // DHCP option checks\r
562 //\r
563 dhcp4_magik = htonl (DHCP4_MAGIK_NUMBER);\r
564 is_bootp = TRUE;\r
565\r
566 if (!CompareMem (&Offer->dhcp4.magik, &dhcp4_magik, 4)) {\r
567 //\r
568 // If present, DHCP message type must be offer.\r
569 //\r
570 EfiStatus = find_opt (Offer, DHCP4_MESSAGE_TYPE, 0, &op);\r
571\r
572 if (!EFI_ERROR (EfiStatus)) {\r
573 if (op->len != 1 || op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {\r
574 Private->callback = NULL;\r
575 return EFI_INVALID_PARAMETER;\r
576 }\r
577\r
578 is_bootp = FALSE;\r
579 }\r
580 //\r
581 // If present, DHCP max message size must be valid.\r
582 //\r
583 EfiStatus = find_opt (Offer, DHCP4_MAX_MESSAGE_SIZE, 0, &op);\r
584\r
585 if (!EFI_ERROR (EfiStatus)) {\r
586 if (op->len != 2 || ((op->data[0] << 8) | op->data[1]) < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) {\r
587 Private->callback = NULL;\r
588 return EFI_INVALID_PARAMETER;\r
589 }\r
590 }\r
591 //\r
592 // If present, DHCP server identifier must be valid.\r
593 //\r
594 EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &op);\r
595\r
596 if (!EFI_ERROR (EfiStatus)) {\r
597 if (op->len != 4 || !CompareMem (op->data, &bcast_ip, 4) || !CompareMem (op->data, &zero_ip, 4)) {\r
598 Private->callback = NULL;\r
599 return EFI_INVALID_PARAMETER;\r
600 }\r
601 }\r
602 //\r
603 // If present, DHCP subnet mask must be valid.\r
604 //\r
605 EfiStatus = find_opt (\r
606 Offer,\r
607 DHCP4_SUBNET_MASK,\r
608 0,\r
609 &op\r
610 );\r
611\r
612 if (!EFI_ERROR (EfiStatus)) {\r
613 if (op->len != 4) {\r
614 Private->callback = NULL;\r
615 return EFI_INVALID_PARAMETER;\r
616 }\r
617 }\r
618 }\r
619 //\r
620 // Early out for BOOTP.\r
621 //\r
622 This->Data->IsBootp = is_bootp;\r
623 if (is_bootp) {\r
624 //\r
625 // Copy offer packet to instance data.\r
626 //\r
627 CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));\r
628\r
629 //\r
630 // Copy discover to request and offer to acknak.\r
631 //\r
632 CopyMem (\r
633 &This->Data->Request,\r
634 &This->Data->Discover,\r
635 sizeof (DHCP4_PACKET)\r
636 );\r
637\r
638 CopyMem (\r
639 &This->Data->AckNak,\r
640 &This->Data->Offer,\r
641 sizeof (DHCP4_PACKET)\r
642 );\r
643\r
644 //\r
645 // Set state flags.\r
646 //\r
647 This->Data->SelectCompleted = TRUE;\r
648 This->Data->IsAck = TRUE;\r
649\r
650 Private->callback = NULL;\r
651 return EFI_SUCCESS;\r
652 }\r
653 //\r
654 // Copy discover packet contents to request packet.\r
655 //\r
656 CopyMem (&request, &This->Data->Discover, sizeof (DHCP4_PACKET));\r
657\r
658 This->Data->IsAck = FALSE;\r
659\r
660 //\r
661 // Change DHCP message type from discover to request.\r
662 //\r
663 EfiStatus = find_opt (&request, DHCP4_MESSAGE_TYPE, 0, &op);\r
664\r
665 if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) {\r
666 Private->callback = NULL;\r
667 return EFI_INVALID_PARAMETER;\r
668 }\r
669\r
670 if (EfiStatus == EFI_NOT_FOUND) {\r
671 EfiStatus = find_opt (&request, DHCP4_END, 0, &op);\r
672\r
673 if (EFI_ERROR (EfiStatus)) {\r
674 Private->callback = NULL;\r
675 return EFI_INVALID_PARAMETER;\r
676 }\r
677\r
678 op->op = DHCP4_MESSAGE_TYPE;\r
679 op->len = 1;\r
680\r
681 op->data[1] = DHCP4_END;\r
682 }\r
683\r
684 op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;\r
685\r
686 //\r
687 // Copy server identifier option from offer to request.\r
688 //\r
689 EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &srvid);\r
690\r
691 if (EFI_ERROR (EfiStatus)) {\r
692 Private->callback = NULL;\r
693 return EFI_INVALID_PARAMETER;\r
694 }\r
695\r
696 if (srvid->len != 4) {\r
697 Private->callback = NULL;\r
698 return EFI_INVALID_PARAMETER;\r
699 }\r
700\r
701 EfiStatus = add_opt (&request, srvid);\r
702\r
703 if (EFI_ERROR (EfiStatus)) {\r
704 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
705 Private->callback = NULL;\r
706 return EfiStatus;\r
707 }\r
708 //\r
709 // Add requested IP address option to request packet.\r
710 //\r
711 op = (DHCP4_OP *) buf;\r
712 op->op = DHCP4_REQUESTED_IP_ADDRESS;\r
713 op->len = 4;\r
714 CopyMem (op->data, &Offer->dhcp4.yiaddr, 4);\r
715\r
716 EfiStatus = add_opt (&request, op);\r
717\r
718 if (EFI_ERROR (EfiStatus)) {\r
719 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
720 Private->callback = NULL;\r
721 return EfiStatus;\r
722 }\r
723 //\r
724 // Transimit DHCP request and wait for DHCP ack...\r
725 //\r
726 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
727\r
728 EfiStatus = tx_rx_udp (\r
729 Private,\r
730 &bcast_ip,\r
731 NULL,\r
732 NULL,\r
733 NULL,\r
734 &request,\r
735 &acknak,\r
736 &acknak_verify,\r
737 seconds_timeout\r
738 );\r
739\r
740 if (EFI_ERROR (EfiStatus)) {\r
741 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
742 Private->callback = NULL;\r
743 return EfiStatus;\r
744 }\r
745 //\r
746 // Set Data->IsAck and return.\r
747 //\r
748 EfiStatus = find_opt (&acknak, DHCP4_MESSAGE_TYPE, 0, &op);\r
749\r
750 if (EFI_ERROR (EfiStatus)) {\r
751 Private->callback = NULL;\r
752 return EFI_DEVICE_ERROR;\r
753 }\r
754\r
755 if (op->len != 1) {\r
756 Private->callback = NULL;\r
757 return EFI_DEVICE_ERROR;\r
758 }\r
759\r
760 switch (op->data[0]) {\r
761 case DHCP4_MESSAGE_TYPE_ACK:\r
762 This->Data->IsAck = TRUE;\r
763 break;\r
764\r
765 case DHCP4_MESSAGE_TYPE_NAK:\r
766 This->Data->IsAck = FALSE;\r
767 break;\r
768\r
769 default:\r
770 Private->callback = NULL;\r
771 return EFI_DEVICE_ERROR;\r
772 }\r
773 //\r
774 // Copy packets into instance data...\r
775 //\r
776 CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));\r
777 CopyMem (&This->Data->Request, &request, sizeof (DHCP4_PACKET));\r
778 CopyMem (&This->Data->AckNak, &acknak, sizeof (DHCP4_PACKET));\r
779\r
780 This->Data->SelectCompleted = TRUE;\r
781\r
782 Private->callback = NULL;\r
783 return EFI_SUCCESS;\r
784}\r
785\r
786/* eof - PxeDhcp4InitSelect.c */\r