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