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