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