]> git.proxmox.com Git - mirror_edk2.git/blame - EdkModulePkg/Universal/Network/PxeDhcp4/Dxe/PxeDhcp4InitSelect.c
1. Remove #ifdef _MSC_EXTENSION_ from all source files
[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
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
878ddf1f 335 //\r
336 // Get pointer to our instance data.\r
337 //\r
338 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);\r
339\r
340 if (Private == NULL) {\r
341 return EFI_INVALID_PARAMETER;\r
342 }\r
343\r
344 if (Private->PxeBc == NULL) {\r
345 return EFI_DEVICE_ERROR;\r
346 }\r
347 //\r
348 // Setup variables...\r
349 //\r
350 Private->offers = 0;\r
351 Private->offer_list = NULL;\r
352\r
353 EfiStatus = gBS->HandleProtocol (\r
354 Private->Handle,\r
355 &gEfiPxeDhcp4CallbackProtocolGuid,\r
356 (VOID *) &Private->callback\r
357 );\r
358\r
359 if (EFI_ERROR (EfiStatus)) {\r
360 Private->callback = NULL;\r
361 }\r
362\r
363 Private->function = EFI_PXE_DHCP4_FUNCTION_INIT;\r
364\r
365 //\r
366 // Increment the transaction ID.\r
367 //\r
368 {\r
369 UINT32 xid;\r
370\r
371 CopyMem (&xid, &This->Data->Discover.dhcp4.xid, sizeof (UINT32));\r
372\r
373 xid = htonl (htonl (xid) + 1);\r
374\r
375 CopyMem (&This->Data->Discover.dhcp4.xid, &xid, sizeof (UINT32));\r
376 }\r
377 //\r
378 // Transmit discover and wait for offers...\r
379 //\r
380 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
381\r
382 EfiStatus = tx_rx_udp (\r
383 Private,\r
384 &bcast_ip,\r
385 NULL,\r
386 NULL,\r
387 NULL,\r
388 &This->Data->Discover,\r
389 &offer,\r
390 &offer_verify,\r
391 seconds_timeout\r
392 );\r
393\r
394 if (EFI_ERROR (EfiStatus)) {\r
395 if (Private->offer_list) {\r
396 gBS->FreePool (Private->offer_list);\r
397 }\r
398\r
399 Private->offers = 0;\r
400 Private->offer_list = NULL;\r
401 Private->callback = NULL;\r
402\r
403 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
404 return EfiStatus;\r
405 }\r
406\r
407 *Offers = Private->offers;\r
408 *OfferList = Private->offer_list;\r
409\r
410 Private->offers = 0;\r
411 Private->offer_list = NULL;\r
412 Private->callback = NULL;\r
413\r
414 This->Data->InitCompleted = TRUE;\r
415 This->Data->SelectCompleted = FALSE;\r
416 This->Data->IsBootp = FALSE;\r
417 This->Data->IsAck = FALSE;\r
418\r
419 return EFI_SUCCESS;\r
420}\r
421\r
422/* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */\r
423EFI_STATUS\r
424EFIAPI\r
425PxeDhcp4Select (\r
426 IN EFI_PXE_DHCP4_PROTOCOL *This,\r
427 IN UINTN seconds_timeout,\r
428 IN DHCP4_PACKET *Offer\r
429 )\r
430{\r
431 PXE_DHCP4_PRIVATE_DATA *Private;\r
432 EFI_STATUS EfiStatus;\r
433 DHCP4_PACKET request;\r
434 DHCP4_PACKET acknak;\r
435 EFI_IP_ADDRESS bcast_ip;\r
436 EFI_IP_ADDRESS zero_ip;\r
437 EFI_IP_ADDRESS local_ip;\r
438 DHCP4_OP *srvid;\r
439 DHCP4_OP *op;\r
440 UINT32 dhcp4_magik;\r
441 UINT8 buf[16];\r
442 BOOLEAN is_bootp;\r
443\r
444 //\r
445 // Verify parameters.\r
446 //\r
447 if (This == NULL || seconds_timeout < DHCP4_MIN_SECONDS || seconds_timeout > DHCP4_MAX_SECONDS || Offer == NULL) {\r
448 return EFI_INVALID_PARAMETER;\r
449 }\r
450 //\r
451 // Check protocol state.\r
452 //\r
453 if (This->Data == NULL) {\r
454 return EFI_NOT_STARTED;\r
455 }\r
456\r
457 if (!This->Data->SetupCompleted) {\r
458 return EFI_NOT_READY;\r
459 }\r
460 //\r
461 // Get pointer to instance data.\r
462 //\r
463 Private = PXE_DHCP4_PRIVATE_DATA_FROM_THIS (This);\r
464\r
465 if (Private == NULL) {\r
466 return EFI_INVALID_PARAMETER;\r
467 }\r
468\r
469 if (Private->PxeBc == NULL) {\r
470 return EFI_DEVICE_ERROR;\r
471 }\r
472\r
878ddf1f 473 //\r
474 // Setup useful variables...\r
475 //\r
476 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
477\r
478 ZeroMem (&zero_ip, sizeof (EFI_IP_ADDRESS));\r
479\r
480 ZeroMem (&local_ip, sizeof (EFI_IP_ADDRESS));\r
481 local_ip.v4.Addr[0] = 127;\r
482 local_ip.v4.Addr[3] = 1;\r
483\r
484 This->Data->SelectCompleted = FALSE;\r
485 This->Data->IsBootp = FALSE;\r
486 This->Data->IsAck = FALSE;\r
487\r
488 EfiStatus = gBS->HandleProtocol (\r
489 Private->Handle,\r
490 &gEfiPxeDhcp4CallbackProtocolGuid,\r
491 (VOID *) &Private->callback\r
492 );\r
493\r
494 if (EFI_ERROR (EfiStatus)) {\r
495 Private->callback = NULL;\r
496 }\r
497\r
498 Private->function = EFI_PXE_DHCP4_FUNCTION_SELECT;\r
499\r
500 //\r
501 // Verify offer packet fields.\r
502 //\r
503 if (Offer->dhcp4.op != BOOTP_REPLY) {\r
504 Private->callback = NULL;\r
505 return EFI_INVALID_PARAMETER;\r
506 }\r
507\r
508 if (Offer->dhcp4.htype != This->Data->Discover.dhcp4.htype) {\r
509 Private->callback = NULL;\r
510 return EFI_INVALID_PARAMETER;\r
511 }\r
512\r
513 if (Offer->dhcp4.hlen != This->Data->Discover.dhcp4.hlen) {\r
514 Private->callback = NULL;\r
515 return EFI_INVALID_PARAMETER;\r
516 }\r
517\r
518 if (CompareMem (&Offer->dhcp4.xid, &This->Data->Discover.dhcp4.xid, 4)) {\r
519 Private->callback = NULL;\r
520 return EFI_INVALID_PARAMETER;\r
521 }\r
522\r
523 if (!CompareMem (&Offer->dhcp4.yiaddr, &bcast_ip, 4)) {\r
524 Private->callback = NULL;\r
525 return EFI_INVALID_PARAMETER;\r
526 }\r
527\r
528 if (!CompareMem (&Offer->dhcp4.yiaddr, &zero_ip, 4)) {\r
529 Private->callback = NULL;\r
530 return EFI_INVALID_PARAMETER;\r
531 }\r
532\r
533 if (!CompareMem (&Offer->dhcp4.yiaddr, &local_ip, 4)) {\r
534 Private->callback = NULL;\r
535 return EFI_INVALID_PARAMETER;\r
536 }\r
537\r
538 if (CompareMem (\r
539 &Offer->dhcp4.chaddr,\r
540 &This->Data->Discover.dhcp4.chaddr,\r
541 16\r
542 )) {\r
543 Private->callback = NULL;\r
544 return EFI_INVALID_PARAMETER;\r
545 }\r
546 //\r
547 // DHCP option checks\r
548 //\r
549 dhcp4_magik = htonl (DHCP4_MAGIK_NUMBER);\r
550 is_bootp = TRUE;\r
551\r
552 if (!CompareMem (&Offer->dhcp4.magik, &dhcp4_magik, 4)) {\r
553 //\r
554 // If present, DHCP message type must be offer.\r
555 //\r
556 EfiStatus = find_opt (Offer, DHCP4_MESSAGE_TYPE, 0, &op);\r
557\r
558 if (!EFI_ERROR (EfiStatus)) {\r
559 if (op->len != 1 || op->data[0] != DHCP4_MESSAGE_TYPE_OFFER) {\r
560 Private->callback = NULL;\r
561 return EFI_INVALID_PARAMETER;\r
562 }\r
563\r
564 is_bootp = FALSE;\r
565 }\r
566 //\r
567 // If present, DHCP max message size must be valid.\r
568 //\r
569 EfiStatus = find_opt (Offer, DHCP4_MAX_MESSAGE_SIZE, 0, &op);\r
570\r
571 if (!EFI_ERROR (EfiStatus)) {\r
572 if (op->len != 2 || ((op->data[0] << 8) | op->data[1]) < DHCP4_DEFAULT_MAX_MESSAGE_SIZE) {\r
573 Private->callback = NULL;\r
574 return EFI_INVALID_PARAMETER;\r
575 }\r
576 }\r
577 //\r
578 // If present, DHCP server identifier must be valid.\r
579 //\r
580 EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &op);\r
581\r
582 if (!EFI_ERROR (EfiStatus)) {\r
583 if (op->len != 4 || !CompareMem (op->data, &bcast_ip, 4) || !CompareMem (op->data, &zero_ip, 4)) {\r
584 Private->callback = NULL;\r
585 return EFI_INVALID_PARAMETER;\r
586 }\r
587 }\r
588 //\r
589 // If present, DHCP subnet mask must be valid.\r
590 //\r
591 EfiStatus = find_opt (\r
592 Offer,\r
593 DHCP4_SUBNET_MASK,\r
594 0,\r
595 &op\r
596 );\r
597\r
598 if (!EFI_ERROR (EfiStatus)) {\r
599 if (op->len != 4) {\r
600 Private->callback = NULL;\r
601 return EFI_INVALID_PARAMETER;\r
602 }\r
603 }\r
604 }\r
605 //\r
606 // Early out for BOOTP.\r
607 //\r
608 This->Data->IsBootp = is_bootp;\r
609 if (is_bootp) {\r
610 //\r
611 // Copy offer packet to instance data.\r
612 //\r
613 CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));\r
614\r
615 //\r
616 // Copy discover to request and offer to acknak.\r
617 //\r
618 CopyMem (\r
619 &This->Data->Request,\r
620 &This->Data->Discover,\r
621 sizeof (DHCP4_PACKET)\r
622 );\r
623\r
624 CopyMem (\r
625 &This->Data->AckNak,\r
626 &This->Data->Offer,\r
627 sizeof (DHCP4_PACKET)\r
628 );\r
629\r
630 //\r
631 // Set state flags.\r
632 //\r
633 This->Data->SelectCompleted = TRUE;\r
634 This->Data->IsAck = TRUE;\r
635\r
636 Private->callback = NULL;\r
637 return EFI_SUCCESS;\r
638 }\r
639 //\r
640 // Copy discover packet contents to request packet.\r
641 //\r
642 CopyMem (&request, &This->Data->Discover, sizeof (DHCP4_PACKET));\r
643\r
644 This->Data->IsAck = FALSE;\r
645\r
646 //\r
647 // Change DHCP message type from discover to request.\r
648 //\r
649 EfiStatus = find_opt (&request, DHCP4_MESSAGE_TYPE, 0, &op);\r
650\r
651 if (EFI_ERROR (EfiStatus) && EfiStatus != EFI_NOT_FOUND) {\r
652 Private->callback = NULL;\r
653 return EFI_INVALID_PARAMETER;\r
654 }\r
655\r
656 if (EfiStatus == EFI_NOT_FOUND) {\r
657 EfiStatus = find_opt (&request, DHCP4_END, 0, &op);\r
658\r
659 if (EFI_ERROR (EfiStatus)) {\r
660 Private->callback = NULL;\r
661 return EFI_INVALID_PARAMETER;\r
662 }\r
663\r
664 op->op = DHCP4_MESSAGE_TYPE;\r
665 op->len = 1;\r
666\r
667 op->data[1] = DHCP4_END;\r
668 }\r
669\r
670 op->data[0] = DHCP4_MESSAGE_TYPE_REQUEST;\r
671\r
672 //\r
673 // Copy server identifier option from offer to request.\r
674 //\r
675 EfiStatus = find_opt (Offer, DHCP4_SERVER_IDENTIFIER, 0, &srvid);\r
676\r
677 if (EFI_ERROR (EfiStatus)) {\r
678 Private->callback = NULL;\r
679 return EFI_INVALID_PARAMETER;\r
680 }\r
681\r
682 if (srvid->len != 4) {\r
683 Private->callback = NULL;\r
684 return EFI_INVALID_PARAMETER;\r
685 }\r
686\r
687 EfiStatus = add_opt (&request, srvid);\r
688\r
689 if (EFI_ERROR (EfiStatus)) {\r
690 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
691 Private->callback = NULL;\r
692 return EfiStatus;\r
693 }\r
694 //\r
695 // Add requested IP address option to request packet.\r
696 //\r
697 op = (DHCP4_OP *) buf;\r
698 op->op = DHCP4_REQUESTED_IP_ADDRESS;\r
699 op->len = 4;\r
700 CopyMem (op->data, &Offer->dhcp4.yiaddr, 4);\r
701\r
702 EfiStatus = add_opt (&request, op);\r
703\r
704 if (EFI_ERROR (EfiStatus)) {\r
705 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
706 Private->callback = NULL;\r
707 return EfiStatus;\r
708 }\r
709 //\r
710 // Transimit DHCP request and wait for DHCP ack...\r
711 //\r
712 SetMem (&bcast_ip, sizeof (EFI_IP_ADDRESS), 0xFF);\r
713\r
714 EfiStatus = tx_rx_udp (\r
715 Private,\r
716 &bcast_ip,\r
717 NULL,\r
718 NULL,\r
719 NULL,\r
720 &request,\r
721 &acknak,\r
722 &acknak_verify,\r
723 seconds_timeout\r
724 );\r
725\r
726 if (EFI_ERROR (EfiStatus)) {\r
727 DebugPrint (("%a:%d:%r\n", __FILE__, __LINE__, EfiStatus));\r
728 Private->callback = NULL;\r
729 return EfiStatus;\r
730 }\r
731 //\r
732 // Set Data->IsAck and return.\r
733 //\r
734 EfiStatus = find_opt (&acknak, DHCP4_MESSAGE_TYPE, 0, &op);\r
735\r
736 if (EFI_ERROR (EfiStatus)) {\r
737 Private->callback = NULL;\r
738 return EFI_DEVICE_ERROR;\r
739 }\r
740\r
741 if (op->len != 1) {\r
742 Private->callback = NULL;\r
743 return EFI_DEVICE_ERROR;\r
744 }\r
745\r
746 switch (op->data[0]) {\r
747 case DHCP4_MESSAGE_TYPE_ACK:\r
748 This->Data->IsAck = TRUE;\r
749 break;\r
750\r
751 case DHCP4_MESSAGE_TYPE_NAK:\r
752 This->Data->IsAck = FALSE;\r
753 break;\r
754\r
755 default:\r
756 Private->callback = NULL;\r
757 return EFI_DEVICE_ERROR;\r
758 }\r
759 //\r
760 // Copy packets into instance data...\r
761 //\r
762 CopyMem (&This->Data->Offer, Offer, sizeof (DHCP4_PACKET));\r
763 CopyMem (&This->Data->Request, &request, sizeof (DHCP4_PACKET));\r
764 CopyMem (&This->Data->AckNak, &acknak, sizeof (DHCP4_PACKET));\r
765\r
766 This->Data->SelectCompleted = TRUE;\r
767\r
768 Private->callback = NULL;\r
769 return EFI_SUCCESS;\r
770}\r
771\r
772/* eof - PxeDhcp4InitSelect.c */\r