]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Sync the latest version from R8.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Dhcp4Dxe / Dhcp4Impl.c
CommitLineData
772db4bb 1/** @file\r
2\r
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
11\r
12Module Name:\r
13\r
14 Dhcp4Impl.c\r
15\r
16Abstract:\r
17\r
18 This file implement the EFI_DHCP4_PROTOCOL interface.\r
19\r
20\r
21**/\r
22\r
23\r
24#include "Dhcp4Impl.h"\r
25\r
26\r
27/**\r
28 Get the current operation parameter and lease for the network interface.\r
29\r
30 @param This The DHCP protocol instance\r
31 @param Dhcp4ModeData The variable to save the DHCP mode data.\r
32\r
33 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
34 @retval EFI_SUCCESS The Dhcp4ModeData is updated with the current\r
35 operation parameter.\r
36\r
37**/\r
38STATIC\r
39EFI_STATUS\r
40EFIAPI\r
41EfiDhcp4GetModeData (\r
42 IN EFI_DHCP4_PROTOCOL *This,\r
43 OUT EFI_DHCP4_MODE_DATA *Dhcp4ModeData\r
44 )\r
45{\r
46 DHCP_PROTOCOL *Instance;\r
47 DHCP_SERVICE *DhcpSb;\r
48 DHCP_PARAMETER *Para;\r
49 EFI_TPL OldTpl;\r
50 IP4_ADDR Ip;\r
51\r
52 //\r
53 // First validate the parameters.\r
54 //\r
55 if ((This == NULL) || (Dhcp4ModeData == NULL)) {\r
56 return EFI_INVALID_PARAMETER;\r
57 }\r
58\r
59 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
c4a62a12 60 \r
772db4bb 61 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
62 DhcpSb = Instance->Service;\r
63\r
64 //\r
65 // Caller can use GetModeData to retrieve current DHCP states\r
66 // no matter whether it is the active child or not.\r
67 //\r
687a2e5f 68 Dhcp4ModeData->State = (EFI_DHCP4_STATE) DhcpSb->DhcpState;\r
69 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));\r
70 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));\r
772db4bb 71\r
72 Ip = HTONL (DhcpSb->ClientAddr);\r
73 NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
74\r
75 Ip = HTONL (DhcpSb->Netmask);\r
76 NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
77\r
78 Ip = HTONL (DhcpSb->ServerAddr);\r
79 NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
80\r
81 Para = DhcpSb->Para;\r
82\r
83 if (Para != NULL) {\r
84 Ip = HTONL (Para->Router);\r
85 NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
86 Dhcp4ModeData->LeaseTime = Para->Lease;\r
87 } else {\r
88 NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
89 Dhcp4ModeData->LeaseTime = 0xffffffff;\r
90 }\r
91\r
92 Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;\r
93\r
94 NET_RESTORE_TPL (OldTpl);\r
95 return EFI_SUCCESS;\r
96}\r
97\r
98\r
99/**\r
100 Free the resource related to the configure parameters.\r
101 DHCP driver will make a copy of the user's configure\r
102 such as the time out value.\r
103\r
104 @param Config The DHCP configure data\r
105\r
106 @return None\r
107\r
108**/\r
109VOID\r
110DhcpCleanConfigure (\r
111 IN EFI_DHCP4_CONFIG_DATA *Config\r
112 )\r
113{\r
114 UINT32 Index;\r
115\r
116 if (Config->DiscoverTimeout != NULL) {\r
117 NetFreePool (Config->DiscoverTimeout);\r
118 }\r
119\r
120 if (Config->RequestTimeout != NULL) {\r
121 NetFreePool (Config->RequestTimeout);\r
122 }\r
123\r
124 if (Config->OptionList != NULL) {\r
125 for (Index = 0; Index < Config->OptionCount; Index++) {\r
126 if (Config->OptionList[Index] != NULL) {\r
127 NetFreePool (Config->OptionList[Index]);\r
128 }\r
129 }\r
130\r
131 NetFreePool (Config->OptionList);\r
132 }\r
133\r
134 NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
135}\r
136\r
137\r
138/**\r
139 Allocate memory for configure parameter such as timeout value for Dst,\r
140 then copy the configure parameter from Src to Dst.\r
141\r
142 @param Dst The destination DHCP configure data.\r
143 @param Src The source DHCP configure data.\r
144\r
145 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
146 @retval EFI_SUCCESS The configure is copied.\r
147\r
148**/\r
149EFI_STATUS\r
150DhcpCopyConfigure (\r
151 IN EFI_DHCP4_CONFIG_DATA *Dst,\r
152 IN EFI_DHCP4_CONFIG_DATA *Src\r
153 )\r
154{\r
155 EFI_DHCP4_PACKET_OPTION **DstOptions;\r
156 EFI_DHCP4_PACKET_OPTION **SrcOptions;\r
157 INTN Len;\r
158 UINT32 Index;\r
159\r
72030458 160 CopyMem (Dst, Src, sizeof (*Dst));\r
772db4bb 161 Dst->DiscoverTimeout = NULL;\r
162 Dst->RequestTimeout = NULL;\r
163 Dst->OptionList = NULL;\r
164\r
165 //\r
166 // Allocate a memory then copy DiscoverTimeout to it\r
167 //\r
168 if (Src->DiscoverTimeout != NULL) {\r
169 Len = Src->DiscoverTryCount * sizeof (UINT32);\r
170 Dst->DiscoverTimeout = NetAllocatePool (Len);\r
171\r
172 if (Dst->DiscoverTimeout == NULL) {\r
173 return EFI_OUT_OF_RESOURCES;\r
174 }\r
175\r
176 for (Index = 0; Index < Src->DiscoverTryCount; Index++) {\r
36ee91ca 177 Dst->DiscoverTimeout[Index] = MAX (Src->DiscoverTimeout[Index], 1);\r
772db4bb 178 }\r
179 }\r
180\r
181 //\r
182 // Allocate a memory then copy RequestTimeout to it\r
183 //\r
184 if (Src->RequestTimeout != NULL) {\r
185 Len = Src->RequestTryCount * sizeof (UINT32);\r
186 Dst->RequestTimeout = NetAllocatePool (Len);\r
187\r
188 if (Dst->RequestTimeout == NULL) {\r
189 goto ON_ERROR;\r
190 }\r
191\r
192 for (Index = 0; Index < Src->RequestTryCount; Index++) {\r
36ee91ca 193 Dst->RequestTimeout[Index] = MAX (Src->RequestTimeout[Index], 1);\r
772db4bb 194 }\r
195 }\r
196\r
197 //\r
198 // Allocate an array of dhcp option point, then allocate memory\r
199 // for each option and copy the source option to it\r
200 //\r
201 if (Src->OptionList != NULL) {\r
202 Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);\r
203 Dst->OptionList = NetAllocateZeroPool (Len);\r
204\r
205 if (Dst->OptionList == NULL) {\r
206 goto ON_ERROR;\r
207 }\r
208\r
209 DstOptions = Dst->OptionList;\r
210 SrcOptions = Src->OptionList;\r
211\r
212 for (Index = 0; Index < Src->OptionCount; Index++) {\r
36ee91ca 213 Len = sizeof (EFI_DHCP4_PACKET_OPTION) + MAX (SrcOptions[Index]->Length - 1, 0);\r
772db4bb 214\r
215 DstOptions[Index] = NetAllocatePool (Len);\r
216\r
217 if (DstOptions[Index] == NULL) {\r
218 goto ON_ERROR;\r
219 }\r
220\r
221 NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
222 }\r
223 }\r
224\r
225 return EFI_SUCCESS;\r
226\r
227ON_ERROR:\r
228 DhcpCleanConfigure (Dst);\r
229 return EFI_OUT_OF_RESOURCES;\r
230}\r
231\r
232\r
233/**\r
234 Give up the control of the DHCP service to let other child\r
235 resume. Don't change the service's DHCP state and the Client\r
236 address and option list configure as required by RFC2131.\r
237\r
238 @param DhcpSb The DHCP service instance.\r
239\r
240 @return None\r
241\r
242**/\r
243VOID\r
244DhcpYieldControl (\r
245 IN DHCP_SERVICE *DhcpSb\r
246 )\r
247{\r
248 EFI_DHCP4_CONFIG_DATA *Config;\r
772db4bb 249\r
772db4bb 250 Config = &DhcpSb->ActiveConfig;\r
251\r
252 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
253 DhcpSb->ActiveChild = NULL;\r
254\r
255 if (Config->DiscoverTimeout != NULL) {\r
256 NetFreePool (Config->DiscoverTimeout);\r
257\r
258 Config->DiscoverTryCount = 0;\r
259 Config->DiscoverTimeout = NULL;\r
260 }\r
261\r
262 if (Config->RequestTimeout != NULL) {\r
263 NetFreePool (Config->RequestTimeout);\r
264\r
265 Config->RequestTryCount = 0;\r
266 Config->RequestTimeout = NULL;\r
267 }\r
268\r
269 Config->Dhcp4Callback = NULL;\r
270 Config->CallbackContext = NULL;\r
271}\r
272\r
273\r
274/**\r
275 Configure the DHCP protocol instance and its underlying DHCP service\r
276 for operation. If Dhcp4CfgData is NULL and the child is currently\r
277 controlling the DHCP service, release the control.\r
278\r
279 @param This The DHCP protocol instance\r
280 @param Dhcp4CfgData The DHCP configure data.\r
281\r
282 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
283 @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,\r
284 or there is already an active child.\r
285 @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.\r
286 @retval EFI_SUCCESS The child is configured.\r
287\r
288**/\r
289STATIC\r
290EFI_STATUS\r
291EFIAPI\r
292EfiDhcp4Configure (\r
293 IN EFI_DHCP4_PROTOCOL *This,\r
294 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
295 )\r
296{\r
297 EFI_DHCP4_CONFIG_DATA *Config;\r
298 DHCP_PROTOCOL *Instance;\r
299 DHCP_SERVICE *DhcpSb;\r
300 EFI_STATUS Status;\r
301 EFI_TPL OldTpl;\r
302 UINT32 Index;\r
303 IP4_ADDR Ip;\r
304\r
305 //\r
306 // First validate the parameters\r
307 //\r
308 if (This == NULL) {\r
309 return EFI_INVALID_PARAMETER;\r
310 }\r
311\r
312 if (Dhcp4CfgData != NULL) {\r
313 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
314 return EFI_INVALID_PARAMETER;\r
315 }\r
316\r
317 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
318 return EFI_INVALID_PARAMETER;\r
319 }\r
320\r
321 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
322 return EFI_INVALID_PARAMETER;\r
323 }\r
324\r
325 NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
326\r
327 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
328\r
329 return EFI_INVALID_PARAMETER;\r
330 }\r
331 }\r
332\r
333 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
334\r
335 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
336 return EFI_INVALID_PARAMETER;\r
337 }\r
338\r
339 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
340\r
341 DhcpSb = Instance->Service;\r
342 Config = &DhcpSb->ActiveConfig;\r
343\r
344 Status = EFI_ACCESS_DENIED;\r
345\r
346 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&\r
347 (DhcpSb->DhcpState != Dhcp4Init) &&\r
348 (DhcpSb->DhcpState != Dhcp4InitReboot) &&\r
349 (DhcpSb->DhcpState != Dhcp4Bound)) {\r
350\r
351 goto ON_EXIT;\r
352 }\r
353\r
354 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {\r
355 goto ON_EXIT;\r
356 }\r
357\r
358 if (Dhcp4CfgData != NULL) {\r
359 Status = EFI_OUT_OF_RESOURCES;\r
360 DhcpCleanConfigure (Config);\r
361\r
362 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {\r
363 goto ON_EXIT;\r
364 }\r
365\r
366 DhcpSb->UserOptionLen = 0;\r
367\r
368 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {\r
369 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;\r
370 }\r
371\r
372 DhcpSb->ActiveChild = Instance;\r
373\r
374 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
375 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);\r
376\r
377 if (DhcpSb->ClientAddr != 0) {\r
378 DhcpSb->DhcpState = Dhcp4InitReboot;\r
379 } else {\r
380 DhcpSb->DhcpState = Dhcp4Init;\r
381 }\r
382 }\r
383\r
384 DhcpSb->ServiceState = DHCP_CONFIGED;\r
385 Status = EFI_SUCCESS;\r
386\r
387 } else if (DhcpSb->ActiveChild == Instance) {\r
388 Status = EFI_SUCCESS;\r
389 DhcpYieldControl (DhcpSb);\r
390 }\r
391\r
392ON_EXIT:\r
393 NET_RESTORE_TPL (OldTpl);\r
394 return Status;\r
395}\r
396\r
397\r
398/**\r
399 Start the DHCP process.\r
400\r
401 @param This The DHCP protocol instance\r
402 @param CompletionEvent The event to signal is address is acquired.\r
403\r
404 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
405 @retval EFI_NOT_STARTED The protocol hasn't been configured.\r
406 @retval EFI_ALREADY_STARTED The DHCP process has already been started.\r
407 @retval EFI_SUCCESS The DHCP process is started.\r
408\r
409**/\r
410STATIC\r
411EFI_STATUS\r
412EFIAPI\r
413EfiDhcp4Start (\r
414 IN EFI_DHCP4_PROTOCOL *This,\r
415 IN EFI_EVENT CompletionEvent OPTIONAL\r
416 )\r
417{\r
418 DHCP_PROTOCOL *Instance;\r
419 DHCP_SERVICE *DhcpSb;\r
420 EFI_STATUS Status;\r
421 EFI_TPL OldTpl;\r
422\r
423 //\r
424 // First validate the parameters\r
425 //\r
426 if (This == NULL) {\r
427 return EFI_INVALID_PARAMETER;\r
428 }\r
429\r
430 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
431\r
432 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
433 return EFI_INVALID_PARAMETER;\r
434 }\r
435\r
436 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
437 DhcpSb = Instance->Service;\r
438\r
439 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
440 Status = EFI_NOT_STARTED;\r
441 goto ON_ERROR;\r
442 }\r
443\r
444 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {\r
445 Status = EFI_ALREADY_STARTED;\r
446 goto ON_ERROR;\r
447 }\r
448\r
449 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
450\r
451 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
452 goto ON_ERROR;\r
453 }\r
454\r
455 //\r
456 // Start/Restart the receiving.\r
457 //\r
458 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
459\r
460 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
461 goto ON_ERROR;\r
462 }\r
463\r
464 Instance->CompletionEvent = CompletionEvent;\r
465\r
466 //\r
467 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.\r
468 //\r
469 NET_RESTORE_TPL (OldTpl);\r
470\r
471 if (CompletionEvent == NULL) {\r
472 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
473 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
474 }\r
475\r
476 return DhcpSb->IoStatus;\r
477 }\r
478\r
479 return EFI_SUCCESS;\r
480\r
481ON_ERROR:\r
482 NET_RESTORE_TPL (OldTpl);\r
483 return Status;\r
484}\r
485\r
486\r
487/**\r
488 Request an extra manual renew/rebind.\r
489\r
490 @param This The DHCP protocol instance\r
491 @param RebindRequest TRUE if request a rebind, otherwise renew it\r
492 @param CompletionEvent Event to signal when complete\r
493\r
494 @retval EFI_INVALID_PARAMETER The parameters are invalid\r
495 @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.\r
496 @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.\r
497 @retval EFI_SUCCESS The DHCP is renewed/rebound.\r
498\r
499**/\r
500STATIC\r
501EFI_STATUS\r
502EFIAPI\r
503EfiDhcp4RenewRebind (\r
504 IN EFI_DHCP4_PROTOCOL *This,\r
505 IN BOOLEAN RebindRequest,\r
506 IN EFI_EVENT CompletionEvent OPTIONAL\r
507 )\r
508{\r
509 DHCP_PROTOCOL *Instance;\r
510 DHCP_SERVICE *DhcpSb;\r
511 EFI_STATUS Status;\r
512 EFI_TPL OldTpl;\r
513\r
514 //\r
515 // First validate the parameters\r
516 //\r
517 if (This == NULL) {\r
518 return EFI_INVALID_PARAMETER;\r
519 }\r
520\r
521 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
522\r
523 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526\r
527 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
528 DhcpSb = Instance->Service;\r
529\r
530 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
531 Status = EFI_NOT_STARTED;\r
532 goto ON_ERROR;\r
533 }\r
534\r
535 if (DhcpSb->DhcpState != Dhcp4Bound) {\r
536 Status = EFI_ACCESS_DENIED;\r
537 goto ON_ERROR;\r
538 }\r
539\r
540 if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
541 return EFI_SUCCESS;\r
542 }\r
543\r
544 //\r
545 // Transit the states then send a extra DHCP request\r
546 //\r
547 if (!RebindRequest) {\r
548 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);\r
549 } else {\r
550 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
551 }\r
552\r
553 Status = DhcpSendMessage (\r
554 DhcpSb,\r
555 DhcpSb->Selected,\r
556 DhcpSb->Para,\r
557 DHCP_MSG_REQUEST,\r
67a58d0f 558 (UINT8 *) "Extra renew/rebind by the application"\r
772db4bb 559 );\r
560\r
561 if (EFI_ERROR (Status)) {\r
562 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
563 goto ON_ERROR;\r
564 }\r
565\r
566 DhcpSb->ExtraRefresh = TRUE;\r
567 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
568 Instance->RenewRebindEvent = CompletionEvent;\r
569\r
570 NET_RESTORE_TPL (OldTpl);\r
571\r
572 if (CompletionEvent == NULL) {\r
573 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
574 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
575 }\r
576\r
577 return DhcpSb->IoStatus;\r
578 }\r
579\r
580 return EFI_SUCCESS;\r
581\r
582ON_ERROR:\r
583 NET_RESTORE_TPL (OldTpl);\r
584 return Status;\r
585}\r
586\r
587\r
588/**\r
589 Release the current acquired lease.\r
590\r
591 @param This The DHCP protocol instance\r
592\r
593 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
594 @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet\r
595 @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected\r
596 state.\r
597 @retval EFI_SUCCESS The lease is released.\r
598\r
599**/\r
600STATIC\r
601EFI_STATUS\r
602EFIAPI\r
603EfiDhcp4Release (\r
604 IN EFI_DHCP4_PROTOCOL *This\r
605 )\r
606{\r
607 DHCP_PROTOCOL *Instance;\r
608 DHCP_SERVICE *DhcpSb;\r
609 EFI_STATUS Status;\r
610 EFI_TPL OldTpl;\r
611\r
612 //\r
613 // First validate the parameters\r
614 //\r
615 if (This == NULL) {\r
616 return EFI_INVALID_PARAMETER;\r
617 }\r
618\r
619 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
620\r
621 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
622 return EFI_INVALID_PARAMETER;\r
623 }\r
624\r
625 Status = EFI_SUCCESS;\r
626 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
627 DhcpSb = Instance->Service;\r
628\r
629 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
630 Status = EFI_ACCESS_DENIED;\r
631 goto ON_EXIT;\r
632 }\r
633\r
634 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {\r
635 Status = DhcpSendMessage (\r
636 DhcpSb,\r
637 DhcpSb->Selected,\r
638 DhcpSb->Para,\r
639 DHCP_MSG_RELEASE,\r
640 NULL\r
641 );\r
642\r
643 if (EFI_ERROR (Status)) {\r
644 Status = EFI_DEVICE_ERROR;\r
645 goto ON_EXIT;\r
646 }\r
647 }\r
648\r
649 DhcpCleanLease (DhcpSb);\r
650\r
651ON_EXIT:\r
652 NET_RESTORE_TPL (OldTpl);\r
653 return Status;\r
654}\r
655\r
656\r
657/**\r
658 Stop the current DHCP process. After this, other DHCP child\r
659 can gain control of the service, configure and use it.\r
660\r
661 @param This The DHCP protocol instance\r
662\r
663 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
664 @retval EFI_SUCCESS The DHCP process is stopped.\r
665\r
666**/\r
667STATIC\r
668EFI_STATUS\r
669EFIAPI\r
670EfiDhcp4Stop (\r
671 IN EFI_DHCP4_PROTOCOL *This\r
672 )\r
673{\r
674 DHCP_PROTOCOL *Instance;\r
675 DHCP_SERVICE *DhcpSb;\r
676 EFI_TPL OldTpl;\r
677\r
678 //\r
679 // First validate the parameters\r
680 //\r
681 if (This == NULL) {\r
682 return EFI_INVALID_PARAMETER;\r
683 }\r
684\r
685 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
686\r
687 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
688 return EFI_INVALID_PARAMETER;\r
689 }\r
690\r
691 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
692 DhcpSb = Instance->Service;\r
693\r
694 DhcpCleanLease (DhcpSb);\r
695\r
696 DhcpSb->DhcpState = Dhcp4Stopped;\r
697 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
698\r
699 NET_RESTORE_TPL (OldTpl);\r
700 return EFI_SUCCESS;\r
701}\r
702\r
703\r
704/**\r
705 Build a new DHCP packet from the seed packet. Options may be deleted or\r
706 appended. The caller should free the NewPacket when finished using it.\r
707\r
708 @param This The DHCP protocol instance.\r
709 @param SeedPacket The seed packet to start with\r
710 @param DeleteCount The number of options to delete\r
711 @param DeleteList The options to delete from the packet\r
712 @param AppendCount The number of options to append\r
713 @param AppendList The options to append to the packet\r
714 @param NewPacket The new packet, allocated and built by this\r
715 function.\r
716\r
717 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
718 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory\r
719 @retval EFI_SUCCESS The packet is build.\r
720\r
721**/\r
722STATIC\r
723EFI_STATUS\r
724EFIAPI\r
725EfiDhcp4Build (\r
726 IN EFI_DHCP4_PROTOCOL *This,\r
727 IN EFI_DHCP4_PACKET *SeedPacket,\r
728 IN UINT32 DeleteCount,\r
729 IN UINT8 *DeleteList OPTIONAL,\r
730 IN UINT32 AppendCount,\r
731 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
732 OUT EFI_DHCP4_PACKET **NewPacket\r
733 )\r
734{\r
735 //\r
736 // First validate the parameters\r
737 //\r
738 if ((This == NULL) || (NewPacket == NULL)) {\r
739 return EFI_INVALID_PARAMETER;\r
740 }\r
741\r
742 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
743 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {\r
744\r
745 return EFI_INVALID_PARAMETER;\r
746 }\r
747\r
748 if (((DeleteCount == 0) && (AppendCount == 0)) ||\r
749 ((DeleteCount != 0) && (DeleteList == NULL)) ||\r
750 ((AppendCount != 0) && (AppendList == NULL))) {\r
751\r
752 return EFI_INVALID_PARAMETER;\r
753 }\r
754\r
755 return DhcpBuild (\r
756 SeedPacket,\r
757 DeleteCount,\r
758 DeleteList,\r
759 AppendCount,\r
760 AppendList,\r
761 NewPacket\r
762 );\r
763}\r
764\r
c4a62a12 765STATIC\r
766EFI_STATUS\r
767Dhcp4InstanceConfigUdpIo (\r
768 IN UDP_IO_PORT *UdpIo,\r
769 IN VOID *Context\r
770 )\r
771{\r
772 DHCP_PROTOCOL *Instance;\r
773 DHCP_SERVICE *DhcpSb;\r
774 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
775 EFI_UDP4_CONFIG_DATA UdpConfigData;\r
776 IP4_ADDR Ip;\r
777\r
778 Instance = (DHCP_PROTOCOL *) Context;\r
779 DhcpSb = Instance->Service;\r
780 Token = Instance->Token;\r
781\r
782 NetZeroMem (&UdpConfigData, sizeof (EFI_UDP4_CONFIG_DATA));\r
783\r
784 UdpConfigData.AcceptBroadcast = TRUE;\r
785 UdpConfigData.AllowDuplicatePort = TRUE;\r
786 UdpConfigData.TimeToLive = 64;\r
787 UdpConfigData.DoNotFragment = TRUE;\r
788\r
789 Ip = HTONL (DhcpSb->ClientAddr);\r
790 NetCopyMem (&UdpConfigData.StationAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
791\r
792 Ip = HTONL (DhcpSb->Netmask);\r
793 NetCopyMem (&UdpConfigData.SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
794\r
795 if ((Token->ListenPointCount == 0) || (Token->ListenPoints[0].ListenPort == 0)) {\r
796 UdpConfigData.StationPort = DHCP_CLIENT_PORT;\r
797 } else {\r
798 UdpConfigData.StationPort = Token->ListenPoints[0].ListenPort;\r
799 }\r
800\r
801 return UdpIo->Udp->Configure (UdpIo->Udp, &UdpConfigData);\r
802}\r
803\r
804STATIC\r
805EFI_STATUS\r
806Dhcp4InstanceCreateUdpIo (\r
807 IN DHCP_PROTOCOL *Instance\r
808 )\r
809{\r
810 DHCP_SERVICE *DhcpSb;\r
811\r
812 ASSERT (Instance->Token != NULL);\r
813\r
814 DhcpSb = Instance->Service;\r
815 Instance->UdpIo = UdpIoCreatePort (DhcpSb->Controller, DhcpSb->Image, Dhcp4InstanceConfigUdpIo, Instance);\r
816 if (Instance->UdpIo == NULL) {\r
817 return EFI_OUT_OF_RESOURCES;\r
818 } else {\r
819 return EFI_SUCCESS;\r
820 }\r
821}\r
822\r
823STATIC\r
824VOID\r
825DhcpDummyExtFree (\r
826 IN VOID *Arg\r
827 )\r
828/*++\r
829\r
830Routine Description:\r
831\r
832 Release the packet.\r
833\r
834Arguments:\r
835\r
836 Arg - The packet to release\r
837\r
838Returns:\r
839\r
840 None\r
841\r
842--*/\r
843{ \r
844}\r
845\r
846VOID\r
847PxeDhcpInput (\r
848 NET_BUF *UdpPacket,\r
849 UDP_POINTS *Points,\r
850 EFI_STATUS IoStatus,\r
851 VOID *Context\r
852 )\r
853{\r
854 DHCP_PROTOCOL *Instance;\r
855 DHCP_SERVICE *DhcpSb;\r
856 EFI_DHCP4_HEADER *Head;\r
857 NET_BUF *Wrap;\r
858 EFI_DHCP4_PACKET *Packet;\r
859 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
860 UINT32 Len;\r
861 EFI_STATUS Status;\r
862\r
863 Wrap = NULL;\r
864 Instance = (DHCP_PROTOCOL *) Context;\r
865 Token = Instance->Token;\r
866 DhcpSb = Instance->Service;\r
867\r
868 //\r
869 // Don't restart receive if error occurs or DHCP is destoried.\r
870 //\r
871 if (EFI_ERROR (IoStatus)) {\r
872 return ;\r
873 }\r
874\r
875 ASSERT (UdpPacket != NULL);\r
876 \r
877 //\r
878 // Validate the packet received\r
879 //\r
880 if (UdpPacket->TotalSize < sizeof (EFI_DHCP4_HEADER)) {\r
881 goto RESTART;\r
882 }\r
883 \r
884 //\r
885 // Copy the DHCP message to a continuous memory block, make the buffer size\r
886 // of the EFI_DHCP4_PACKET a multiple of 4-byte.\r
887 //\r
888 Len = NET_ROUNDUP (sizeof (EFI_DHCP4_PACKET) + UdpPacket->TotalSize - sizeof (EFI_DHCP4_HEADER), 4);\r
889 Wrap = NetbufAlloc (Len);\r
890\r
891 if (Wrap == NULL) {\r
892 goto RESTART;\r
893 }\r
894\r
895 Packet = (EFI_DHCP4_PACKET *) NetbufAllocSpace (Wrap, Len, NET_BUF_TAIL);\r
896 Packet->Size = Len;\r
897 Head = &Packet->Dhcp4.Header;\r
898 Packet->Length = NetbufCopy (UdpPacket, 0, UdpPacket->TotalSize, (UINT8 *) Head);\r
899\r
900 if (Packet->Length != UdpPacket->TotalSize) {\r
901 goto RESTART;\r
902 }\r
903 \r
904 //\r
905 // Is this packet the answer to our packet?\r
906 //\r
907 if ((Head->OpCode != BOOTP_REPLY) ||\r
908 (Head->Xid != Token->Packet->Dhcp4.Header.Xid) ||\r
909 !NET_MAC_EQUAL (&DhcpSb->Mac, Head->ClientHwAddr, DhcpSb->HwLen)) {\r
910 goto RESTART;\r
911 }\r
912 \r
913 //\r
914 // Validate the options and retrieve the interested options\r
915 //\r
916 if ((Packet->Length > sizeof (EFI_DHCP4_HEADER) + sizeof (UINT32)) &&\r
917 (Packet->Dhcp4.Magik == DHCP_OPTION_MAGIC) &&\r
918 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
919\r
920 goto RESTART;\r
921 }\r
922\r
923 //\r
924 // Keep this packet in the ResponseQueue.\r
925 //\r
926 NET_GET_REF (Wrap);\r
927 NetbufQueAppend (&Instance->ResponseQueue, Wrap);\r
928\r
929RESTART:\r
930\r
931 NetbufFree (UdpPacket);\r
932\r
933 if (Wrap != NULL) {\r
934 NetbufFree (Wrap);\r
935 }\r
936\r
937 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
938 if (EFI_ERROR (Status)) {\r
939 PxeDhcpDone (Instance);\r
940 }\r
941}\r
942\r
943VOID\r
944PxeDhcpDone (\r
945 IN DHCP_PROTOCOL *Instance\r
946 )\r
947{\r
948 EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token;\r
949\r
950 Token = Instance->Token;\r
951\r
952 Token->ResponseCount = Instance->ResponseQueue.BufNum;\r
953 if (Token->ResponseCount != 0) {\r
954 Token->ResponseList = (EFI_DHCP4_PACKET *) NetAllocatePool (Instance->ResponseQueue.BufSize);\r
955 if (Token->ResponseList == NULL) {\r
956 Token->Status = EFI_OUT_OF_RESOURCES;\r
957 goto SIGNAL_USER;\r
958 }\r
959\r
960 //\r
961 // Copy the recieved DHCP responses.\r
962 //\r
963 NetbufQueCopy (&Instance->ResponseQueue, 0, Instance->ResponseQueue.BufSize, (UINT8 *) Token->ResponseList);\r
964 Token->Status = EFI_SUCCESS;\r
965 } else {\r
966 Token->ResponseList = NULL;\r
967 Token->Status = EFI_TIMEOUT;\r
968 }\r
969\r
970SIGNAL_USER:\r
971 //\r
972 // Clean the resources dedicated for this transmit receive transaction.\r
973 //\r
974 NetbufQueFlush (&Instance->ResponseQueue);\r
975 UdpIoCleanPort (Instance->UdpIo);\r
976 UdpIoFreePort (Instance->UdpIo);\r
977 Instance->UdpIo = NULL;\r
978 Instance->Token = NULL;\r
979\r
980 if (Token->CompletionEvent != NULL) {\r
981 gBS->SignalEvent (Token->CompletionEvent);\r
982 } \r
983}\r
984\r
772db4bb 985\r
986/**\r
987 Transmit and receive a packet through this DHCP service.\r
988 This is unsupported.\r
989\r
990 @param This The DHCP protocol instance\r
991 @param Token The transmit and receive instance\r
992\r
993 @retval EFI_UNSUPPORTED It always returns unsupported.\r
994\r
995**/\r
996STATIC\r
997EFI_STATUS\r
998EFIAPI\r
999EfiDhcp4TransmitReceive (\r
1000 IN EFI_DHCP4_PROTOCOL *This,\r
1001 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
1002 )\r
1003{\r
c4a62a12 1004 DHCP_PROTOCOL *Instance;\r
1005 EFI_TPL OldTpl;\r
1006 EFI_STATUS Status;\r
1007 NET_FRAGMENT Frag;\r
1008 NET_BUF *Wrap;\r
1009 UDP_POINTS EndPoint;\r
1010 IP4_ADDR Ip;\r
1011 DHCP_SERVICE *DhcpSb;\r
1012 IP4_ADDR Gateway;\r
1013 IP4_ADDR SubnetMask;\r
1014\r
1015 if ((This == NULL) || (Token == NULL) || (Token->Packet == NULL)) {\r
1016 return EFI_INVALID_PARAMETER;\r
1017 }\r
1018\r
1019 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
1020 DhcpSb = Instance->Service;\r
1021\r
1022 if (Instance->Token != NULL) {\r
1023 //\r
1024 // The previous call to TransmitReceive is not finished.\r
1025 //\r
1026 return EFI_NOT_READY;\r
1027 }\r
1028\r
1029 if ((Token->Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
1030 (NTOHL (Token->Packet->Dhcp4.Header.Xid) == Instance->Service->Xid) ||\r
1031 (Token->TimeoutValue == 0) ||\r
1032 ((Token->ListenPointCount != 0) && (Token->ListenPoints == NULL)) ||\r
1033 EFI_ERROR (DhcpValidateOptions (Token->Packet, NULL)) ||\r
1034 EFI_IP4_EQUAL (&Token->RemoteAddress, &mZeroIp4Addr)) {\r
1035 //\r
1036 // The DHCP packet isn't well-formed, the Transaction ID is already used\r
1037 // , the timeout value is zero, the ListenPoint is invalid,\r
1038 // or the RemoteAddress is zero.\r
1039 //\r
1040 return EFI_INVALID_PARAMETER;\r
1041 }\r
1042\r
1043 if (DhcpSb->ClientAddr == 0) {\r
1044\r
1045 return EFI_NO_MAPPING;\r
1046 }\r
1047\r
1048 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
1049\r
1050 //\r
1051 // Save the token and the timeout value.\r
1052 //\r
1053 Instance->Token = Token;\r
1054 Instance->Timeout = Token->TimeoutValue;\r
1055\r
1056 //\r
1057 // Create a UDP IO for this transmit receive transaction.\r
1058 //\r
1059 Status = Dhcp4InstanceCreateUdpIo (Instance);\r
1060 if (EFI_ERROR (Status)) {\r
1061 goto ON_ERROR;\r
1062 }\r
1063\r
772db4bb 1064 //\r
c4a62a12 1065 // Wrap the DHCP packet into a net buffer.\r
772db4bb 1066 //\r
c4a62a12 1067 Frag.Bulk = (UINT8 *) &Token->Packet->Dhcp4;\r
1068 Frag.Len = Token->Packet->Length;\r
1069 Wrap = NetbufFromExt (&Frag, 1, 0, 0, DhcpDummyExtFree, NULL);\r
1070 if (Wrap == NULL) {\r
1071 Status = EFI_OUT_OF_RESOURCES;\r
1072 goto ON_ERROR;\r
1073 }\r
1074\r
1075 //\r
1076 // Set the local address and local port.\r
1077 //\r
1078 EndPoint.LocalAddr = 0;\r
1079 EndPoint.LocalPort = 0;\r
1080\r
1081 //\r
1082 // Set the destination address and destination port.\r
1083 //\r
1084 NetCopyMem (&Ip, &Token->RemoteAddress, sizeof (EFI_IPv4_ADDRESS));\r
1085 EndPoint.RemoteAddr = NTOHL (Ip);\r
1086\r
1087 if (Token->RemotePort == 0) {\r
1088 EndPoint.RemotePort = DHCP_SERVER_PORT;\r
1089 } else {\r
1090 EndPoint.RemotePort = Token->RemotePort;\r
1091 }\r
1092\r
1093 //\r
1094 // Get the gateway.\r
1095 //\r
1096 SubnetMask = DhcpSb->Netmask;\r
1097 Gateway = 0;\r
1098 if (!IP4_NET_EQUAL (DhcpSb->ClientAddr, EndPoint.RemoteAddr, SubnetMask)) {\r
1099 NetCopyMem (&Gateway, &Token->GatewayAddress, sizeof (EFI_IPv4_ADDRESS));\r
1100 Gateway = NTOHL (Gateway);\r
1101 }\r
1102\r
1103 //\r
1104 // Transmit the DHCP packet.\r
1105 //\r
1106 Status = UdpIoSendDatagram (Instance->UdpIo, Wrap, &EndPoint, Gateway, DhcpOnPacketSent, NULL);\r
1107 if (EFI_ERROR (Status)) {\r
1108 NetbufFree (Wrap);\r
1109 goto ON_ERROR;\r
1110 }\r
1111\r
1112 //\r
1113 // Start to receive the DHCP response.\r
1114 //\r
1115 Status = UdpIoRecvDatagram (Instance->UdpIo, PxeDhcpInput, Instance, 0);\r
1116 if (EFI_ERROR (Status)) {\r
1117 goto ON_ERROR;\r
1118 }\r
1119\r
1120ON_ERROR:\r
1121\r
1122 if (EFI_ERROR (Status) && (Instance->UdpIo != NULL)) {\r
1123 UdpIoCleanPort (Instance->UdpIo);\r
1124 UdpIoFreePort (Instance->UdpIo);\r
1125 Instance->UdpIo = NULL;\r
1126 Instance->Token = NULL;\r
1127 }\r
1128\r
1129 NET_RESTORE_TPL (OldTpl);\r
1130\r
1131 if (!EFI_ERROR (Status) && (Token->CompletionEvent == NULL)) {\r
1132 //\r
1133 // Keep polling until timeout if no error happens and the CompletionEvent\r
1134 // is NULL.\r
1135 //\r
1136 while (Instance->Timeout != 0) {\r
1137 Instance->UdpIo->Udp->Poll (Instance->UdpIo->Udp);\r
1138 }\r
1139 }\r
1140\r
1141 return Status;\r
772db4bb 1142}\r
1143\r
1144\r
1145/**\r
1146 Callback function for DhcpIterateOptions. This callback sets the\r
1147 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
1148 the individual DHCP option in the packet.\r
1149\r
1150 @param Tag The DHCP option type\r
1151 @param Len length of the DHCP option data\r
1152 @param Data The DHCP option data\r
1153 @param Context The context, to pass several parameters in.\r
1154\r
1155 @retval EFI_SUCCESS It always returns EFI_SUCCESS\r
1156\r
1157**/\r
1158STATIC\r
1159EFI_STATUS\r
1160Dhcp4ParseCheckOption (\r
1161 IN UINT8 Tag,\r
1162 IN UINT8 Len,\r
1163 IN UINT8 *Data,\r
1164 IN VOID *Context\r
1165 )\r
1166{\r
1167 DHCP_PARSE_CONTEXT *Parse;\r
1168\r
1169 Parse = (DHCP_PARSE_CONTEXT *) Context;\r
1170 Parse->Index++;\r
1171\r
36ee91ca 1172 if (Parse->Index <= Parse->OptionCount) {\r
772db4bb 1173 //\r
1174 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
1175 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
1176 // pass in the point to option data.\r
1177 //\r
1178 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
1179 }\r
1180\r
1181 return EFI_SUCCESS;\r
1182}\r
1183\r
1184\r
1185/**\r
1186 Parse the DHCP options in the Packet into the PacketOptionList.\r
1187 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.\r
1188\r
1189 @param This The DHCP protocol instance\r
1190 @param Packet The DHCP packet to parse\r
1191 @param OptionCount On input, the size of the PacketOptionList; On\r
1192 output, the actual number of options processed.\r
1193 @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points\r
1194\r
1195 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
1196 @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.\r
1197 @retval EFI_SUCCESS The options are parsed.\r
1198\r
1199**/\r
1200STATIC\r
1201EFI_STATUS\r
1202EFIAPI\r
1203EfiDhcp4Parse (\r
1204 IN EFI_DHCP4_PROTOCOL *This,\r
1205 IN EFI_DHCP4_PACKET *Packet,\r
1206 IN OUT UINT32 *OptionCount,\r
1207 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
1208 )\r
1209{\r
1210 DHCP_PARSE_CONTEXT Context;\r
1211 EFI_STATUS Status;\r
1212\r
1213 //\r
1214 // First validate the parameters\r
1215 //\r
1216 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {\r
1217 return EFI_INVALID_PARAMETER;\r
1218 }\r
1219\r
1220 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||\r
1221 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
1222 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
1223\r
1224 return EFI_INVALID_PARAMETER;\r
1225 }\r
1226\r
1227 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {\r
1228 return EFI_BUFFER_TOO_SMALL;\r
1229 }\r
1230\r
1231 NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
1232\r
1233 Context.Option = PacketOptionList;\r
1234 Context.OptionCount = *OptionCount;\r
1235 Context.Index = 0;\r
1236\r
1237 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);\r
1238\r
1239 if (EFI_ERROR (Status)) {\r
1240 return Status;\r
1241 }\r
1242\r
1243 *OptionCount = Context.Index;\r
1244\r
1245 if (Context.Index > Context.OptionCount) {\r
1246 return EFI_BUFFER_TOO_SMALL;\r
1247 }\r
1248\r
1249 return EFI_SUCCESS;\r
1250}\r
1251\r
1252EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {\r
1253 EfiDhcp4GetModeData,\r
1254 EfiDhcp4Configure,\r
1255 EfiDhcp4Start,\r
1256 EfiDhcp4RenewRebind,\r
1257 EfiDhcp4Release,\r
1258 EfiDhcp4Stop,\r
1259 EfiDhcp4Build,\r
1260 EfiDhcp4TransmitReceive,\r
1261 EfiDhcp4Parse\r
1262};\r
c4a62a12 1263\r