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