]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Clean up Network Components to support GCC build.
[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
60\r
61 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
62 return EFI_INVALID_PARAMETER;\r
63 }\r
64\r
65 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
66 DhcpSb = Instance->Service;\r
67\r
68 //\r
69 // Caller can use GetModeData to retrieve current DHCP states\r
70 // no matter whether it is the active child or not.\r
71 //\r
687a2e5f 72 Dhcp4ModeData->State = (EFI_DHCP4_STATE) DhcpSb->DhcpState;\r
73 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (Dhcp4ModeData->ConfigData));\r
74 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (Dhcp4ModeData->ClientMacAddress));\r
772db4bb 75\r
76 Ip = HTONL (DhcpSb->ClientAddr);\r
77 NetCopyMem (&Dhcp4ModeData->ClientAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
78\r
79 Ip = HTONL (DhcpSb->Netmask);\r
80 NetCopyMem (&Dhcp4ModeData->SubnetMask, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
81\r
82 Ip = HTONL (DhcpSb->ServerAddr);\r
83 NetCopyMem (&Dhcp4ModeData->ServerAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
84\r
85 Para = DhcpSb->Para;\r
86\r
87 if (Para != NULL) {\r
88 Ip = HTONL (Para->Router);\r
89 NetCopyMem (&Dhcp4ModeData->RouterAddress, &Ip, sizeof (EFI_IPv4_ADDRESS));\r
90 Dhcp4ModeData->LeaseTime = Para->Lease;\r
91 } else {\r
92 NetZeroMem (&Dhcp4ModeData->RouterAddress, sizeof (EFI_IPv4_ADDRESS));\r
93 Dhcp4ModeData->LeaseTime = 0xffffffff;\r
94 }\r
95\r
96 Dhcp4ModeData->ReplyPacket = DhcpSb->Selected;\r
97\r
98 NET_RESTORE_TPL (OldTpl);\r
99 return EFI_SUCCESS;\r
100}\r
101\r
102\r
103/**\r
104 Free the resource related to the configure parameters.\r
105 DHCP driver will make a copy of the user's configure\r
106 such as the time out value.\r
107\r
108 @param Config The DHCP configure data\r
109\r
110 @return None\r
111\r
112**/\r
113VOID\r
114DhcpCleanConfigure (\r
115 IN EFI_DHCP4_CONFIG_DATA *Config\r
116 )\r
117{\r
118 UINT32 Index;\r
119\r
120 if (Config->DiscoverTimeout != NULL) {\r
121 NetFreePool (Config->DiscoverTimeout);\r
122 }\r
123\r
124 if (Config->RequestTimeout != NULL) {\r
125 NetFreePool (Config->RequestTimeout);\r
126 }\r
127\r
128 if (Config->OptionList != NULL) {\r
129 for (Index = 0; Index < Config->OptionCount; Index++) {\r
130 if (Config->OptionList[Index] != NULL) {\r
131 NetFreePool (Config->OptionList[Index]);\r
132 }\r
133 }\r
134\r
135 NetFreePool (Config->OptionList);\r
136 }\r
137\r
138 NetZeroMem (Config, sizeof (EFI_DHCP4_CONFIG_DATA));\r
139}\r
140\r
141\r
142/**\r
143 Allocate memory for configure parameter such as timeout value for Dst,\r
144 then copy the configure parameter from Src to Dst.\r
145\r
146 @param Dst The destination DHCP configure data.\r
147 @param Src The source DHCP configure data.\r
148\r
149 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory.\r
150 @retval EFI_SUCCESS The configure is copied.\r
151\r
152**/\r
153EFI_STATUS\r
154DhcpCopyConfigure (\r
155 IN EFI_DHCP4_CONFIG_DATA *Dst,\r
156 IN EFI_DHCP4_CONFIG_DATA *Src\r
157 )\r
158{\r
159 EFI_DHCP4_PACKET_OPTION **DstOptions;\r
160 EFI_DHCP4_PACKET_OPTION **SrcOptions;\r
161 INTN Len;\r
162 UINT32 Index;\r
163\r
72030458 164 CopyMem (Dst, Src, sizeof (*Dst));\r
772db4bb 165 Dst->DiscoverTimeout = NULL;\r
166 Dst->RequestTimeout = NULL;\r
167 Dst->OptionList = NULL;\r
168\r
169 //\r
170 // Allocate a memory then copy DiscoverTimeout to it\r
171 //\r
172 if (Src->DiscoverTimeout != NULL) {\r
173 Len = Src->DiscoverTryCount * sizeof (UINT32);\r
174 Dst->DiscoverTimeout = NetAllocatePool (Len);\r
175\r
176 if (Dst->DiscoverTimeout == NULL) {\r
177 return EFI_OUT_OF_RESOURCES;\r
178 }\r
179\r
180 for (Index = 0; Index < Src->DiscoverTryCount; Index++) {\r
181 Dst->DiscoverTimeout[Index] = NET_MAX (Src->DiscoverTimeout[Index], 1);\r
182 }\r
183 }\r
184\r
185 //\r
186 // Allocate a memory then copy RequestTimeout to it\r
187 //\r
188 if (Src->RequestTimeout != NULL) {\r
189 Len = Src->RequestTryCount * sizeof (UINT32);\r
190 Dst->RequestTimeout = NetAllocatePool (Len);\r
191\r
192 if (Dst->RequestTimeout == NULL) {\r
193 goto ON_ERROR;\r
194 }\r
195\r
196 for (Index = 0; Index < Src->RequestTryCount; Index++) {\r
197 Dst->RequestTimeout[Index] = NET_MAX (Src->RequestTimeout[Index], 1);\r
198 }\r
199 }\r
200\r
201 //\r
202 // Allocate an array of dhcp option point, then allocate memory\r
203 // for each option and copy the source option to it\r
204 //\r
205 if (Src->OptionList != NULL) {\r
206 Len = Src->OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *);\r
207 Dst->OptionList = NetAllocateZeroPool (Len);\r
208\r
209 if (Dst->OptionList == NULL) {\r
210 goto ON_ERROR;\r
211 }\r
212\r
213 DstOptions = Dst->OptionList;\r
214 SrcOptions = Src->OptionList;\r
215\r
216 for (Index = 0; Index < Src->OptionCount; Index++) {\r
217 Len = sizeof (EFI_DHCP4_PACKET_OPTION) + NET_MAX (SrcOptions[Index]->Length - 1, 0);\r
218\r
219 DstOptions[Index] = NetAllocatePool (Len);\r
220\r
221 if (DstOptions[Index] == NULL) {\r
222 goto ON_ERROR;\r
223 }\r
224\r
225 NetCopyMem (DstOptions[Index], SrcOptions[Index], Len);\r
226 }\r
227 }\r
228\r
229 return EFI_SUCCESS;\r
230\r
231ON_ERROR:\r
232 DhcpCleanConfigure (Dst);\r
233 return EFI_OUT_OF_RESOURCES;\r
234}\r
235\r
236\r
237/**\r
238 Give up the control of the DHCP service to let other child\r
239 resume. Don't change the service's DHCP state and the Client\r
240 address and option list configure as required by RFC2131.\r
241\r
242 @param DhcpSb The DHCP service instance.\r
243\r
244 @return None\r
245\r
246**/\r
247VOID\r
248DhcpYieldControl (\r
249 IN DHCP_SERVICE *DhcpSb\r
250 )\r
251{\r
252 EFI_DHCP4_CONFIG_DATA *Config;\r
772db4bb 253\r
772db4bb 254 Config = &DhcpSb->ActiveConfig;\r
255\r
256 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
257 DhcpSb->ActiveChild = NULL;\r
258\r
259 if (Config->DiscoverTimeout != NULL) {\r
260 NetFreePool (Config->DiscoverTimeout);\r
261\r
262 Config->DiscoverTryCount = 0;\r
263 Config->DiscoverTimeout = NULL;\r
264 }\r
265\r
266 if (Config->RequestTimeout != NULL) {\r
267 NetFreePool (Config->RequestTimeout);\r
268\r
269 Config->RequestTryCount = 0;\r
270 Config->RequestTimeout = NULL;\r
271 }\r
272\r
273 Config->Dhcp4Callback = NULL;\r
274 Config->CallbackContext = NULL;\r
275}\r
276\r
277\r
278/**\r
279 Configure the DHCP protocol instance and its underlying DHCP service\r
280 for operation. If Dhcp4CfgData is NULL and the child is currently\r
281 controlling the DHCP service, release the control.\r
282\r
283 @param This The DHCP protocol instance\r
284 @param Dhcp4CfgData The DHCP configure data.\r
285\r
286 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
287 @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,\r
288 or there is already an active child.\r
289 @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.\r
290 @retval EFI_SUCCESS The child is configured.\r
291\r
292**/\r
293STATIC\r
294EFI_STATUS\r
295EFIAPI\r
296EfiDhcp4Configure (\r
297 IN EFI_DHCP4_PROTOCOL *This,\r
298 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
299 )\r
300{\r
301 EFI_DHCP4_CONFIG_DATA *Config;\r
302 DHCP_PROTOCOL *Instance;\r
303 DHCP_SERVICE *DhcpSb;\r
304 EFI_STATUS Status;\r
305 EFI_TPL OldTpl;\r
306 UINT32 Index;\r
307 IP4_ADDR Ip;\r
308\r
309 //\r
310 // First validate the parameters\r
311 //\r
312 if (This == NULL) {\r
313 return EFI_INVALID_PARAMETER;\r
314 }\r
315\r
316 if (Dhcp4CfgData != NULL) {\r
317 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
318 return EFI_INVALID_PARAMETER;\r
319 }\r
320\r
321 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
322 return EFI_INVALID_PARAMETER;\r
323 }\r
324\r
325 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
326 return EFI_INVALID_PARAMETER;\r
327 }\r
328\r
329 NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
330\r
331 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
332\r
333 return EFI_INVALID_PARAMETER;\r
334 }\r
335 }\r
336\r
337 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
338\r
339 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
340 return EFI_INVALID_PARAMETER;\r
341 }\r
342\r
343 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
344\r
345 DhcpSb = Instance->Service;\r
346 Config = &DhcpSb->ActiveConfig;\r
347\r
348 Status = EFI_ACCESS_DENIED;\r
349\r
350 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&\r
351 (DhcpSb->DhcpState != Dhcp4Init) &&\r
352 (DhcpSb->DhcpState != Dhcp4InitReboot) &&\r
353 (DhcpSb->DhcpState != Dhcp4Bound)) {\r
354\r
355 goto ON_EXIT;\r
356 }\r
357\r
358 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {\r
359 goto ON_EXIT;\r
360 }\r
361\r
362 if (Dhcp4CfgData != NULL) {\r
363 Status = EFI_OUT_OF_RESOURCES;\r
364 DhcpCleanConfigure (Config);\r
365\r
366 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {\r
367 goto ON_EXIT;\r
368 }\r
369\r
370 DhcpSb->UserOptionLen = 0;\r
371\r
372 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {\r
373 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;\r
374 }\r
375\r
376 DhcpSb->ActiveChild = Instance;\r
377\r
378 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
379 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);\r
380\r
381 if (DhcpSb->ClientAddr != 0) {\r
382 DhcpSb->DhcpState = Dhcp4InitReboot;\r
383 } else {\r
384 DhcpSb->DhcpState = Dhcp4Init;\r
385 }\r
386 }\r
387\r
388 DhcpSb->ServiceState = DHCP_CONFIGED;\r
389 Status = EFI_SUCCESS;\r
390\r
391 } else if (DhcpSb->ActiveChild == Instance) {\r
392 Status = EFI_SUCCESS;\r
393 DhcpYieldControl (DhcpSb);\r
394 }\r
395\r
396ON_EXIT:\r
397 NET_RESTORE_TPL (OldTpl);\r
398 return Status;\r
399}\r
400\r
401\r
402/**\r
403 Start the DHCP process.\r
404\r
405 @param This The DHCP protocol instance\r
406 @param CompletionEvent The event to signal is address is acquired.\r
407\r
408 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
409 @retval EFI_NOT_STARTED The protocol hasn't been configured.\r
410 @retval EFI_ALREADY_STARTED The DHCP process has already been started.\r
411 @retval EFI_SUCCESS The DHCP process is started.\r
412\r
413**/\r
414STATIC\r
415EFI_STATUS\r
416EFIAPI\r
417EfiDhcp4Start (\r
418 IN EFI_DHCP4_PROTOCOL *This,\r
419 IN EFI_EVENT CompletionEvent OPTIONAL\r
420 )\r
421{\r
422 DHCP_PROTOCOL *Instance;\r
423 DHCP_SERVICE *DhcpSb;\r
424 EFI_STATUS Status;\r
425 EFI_TPL OldTpl;\r
426\r
427 //\r
428 // First validate the parameters\r
429 //\r
430 if (This == NULL) {\r
431 return EFI_INVALID_PARAMETER;\r
432 }\r
433\r
434 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
435\r
436 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
437 return EFI_INVALID_PARAMETER;\r
438 }\r
439\r
440 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
441 DhcpSb = Instance->Service;\r
442\r
443 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
444 Status = EFI_NOT_STARTED;\r
445 goto ON_ERROR;\r
446 }\r
447\r
448 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {\r
449 Status = EFI_ALREADY_STARTED;\r
450 goto ON_ERROR;\r
451 }\r
452\r
453 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
454\r
455 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
456 goto ON_ERROR;\r
457 }\r
458\r
459 //\r
460 // Start/Restart the receiving.\r
461 //\r
462 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
463\r
464 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
465 goto ON_ERROR;\r
466 }\r
467\r
468 Instance->CompletionEvent = CompletionEvent;\r
469\r
470 //\r
471 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.\r
472 //\r
473 NET_RESTORE_TPL (OldTpl);\r
474\r
475 if (CompletionEvent == NULL) {\r
476 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
477 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
478 }\r
479\r
480 return DhcpSb->IoStatus;\r
481 }\r
482\r
483 return EFI_SUCCESS;\r
484\r
485ON_ERROR:\r
486 NET_RESTORE_TPL (OldTpl);\r
487 return Status;\r
488}\r
489\r
490\r
491/**\r
492 Request an extra manual renew/rebind.\r
493\r
494 @param This The DHCP protocol instance\r
495 @param RebindRequest TRUE if request a rebind, otherwise renew it\r
496 @param CompletionEvent Event to signal when complete\r
497\r
498 @retval EFI_INVALID_PARAMETER The parameters are invalid\r
499 @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.\r
500 @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.\r
501 @retval EFI_SUCCESS The DHCP is renewed/rebound.\r
502\r
503**/\r
504STATIC\r
505EFI_STATUS\r
506EFIAPI\r
507EfiDhcp4RenewRebind (\r
508 IN EFI_DHCP4_PROTOCOL *This,\r
509 IN BOOLEAN RebindRequest,\r
510 IN EFI_EVENT CompletionEvent OPTIONAL\r
511 )\r
512{\r
513 DHCP_PROTOCOL *Instance;\r
514 DHCP_SERVICE *DhcpSb;\r
515 EFI_STATUS Status;\r
516 EFI_TPL OldTpl;\r
517\r
518 //\r
519 // First validate the parameters\r
520 //\r
521 if (This == NULL) {\r
522 return EFI_INVALID_PARAMETER;\r
523 }\r
524\r
525 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
526\r
527 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
528 return EFI_INVALID_PARAMETER;\r
529 }\r
530\r
531 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
532 DhcpSb = Instance->Service;\r
533\r
534 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
535 Status = EFI_NOT_STARTED;\r
536 goto ON_ERROR;\r
537 }\r
538\r
539 if (DhcpSb->DhcpState != Dhcp4Bound) {\r
540 Status = EFI_ACCESS_DENIED;\r
541 goto ON_ERROR;\r
542 }\r
543\r
544 if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
545 return EFI_SUCCESS;\r
546 }\r
547\r
548 //\r
549 // Transit the states then send a extra DHCP request\r
550 //\r
551 if (!RebindRequest) {\r
552 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);\r
553 } else {\r
554 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
555 }\r
556\r
557 Status = DhcpSendMessage (\r
558 DhcpSb,\r
559 DhcpSb->Selected,\r
560 DhcpSb->Para,\r
561 DHCP_MSG_REQUEST,\r
67a58d0f 562 (UINT8 *) "Extra renew/rebind by the application"\r
772db4bb 563 );\r
564\r
565 if (EFI_ERROR (Status)) {\r
566 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
567 goto ON_ERROR;\r
568 }\r
569\r
570 DhcpSb->ExtraRefresh = TRUE;\r
571 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
572 Instance->RenewRebindEvent = CompletionEvent;\r
573\r
574 NET_RESTORE_TPL (OldTpl);\r
575\r
576 if (CompletionEvent == NULL) {\r
577 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
578 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
579 }\r
580\r
581 return DhcpSb->IoStatus;\r
582 }\r
583\r
584 return EFI_SUCCESS;\r
585\r
586ON_ERROR:\r
587 NET_RESTORE_TPL (OldTpl);\r
588 return Status;\r
589}\r
590\r
591\r
592/**\r
593 Release the current acquired lease.\r
594\r
595 @param This The DHCP protocol instance\r
596\r
597 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
598 @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet\r
599 @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected\r
600 state.\r
601 @retval EFI_SUCCESS The lease is released.\r
602\r
603**/\r
604STATIC\r
605EFI_STATUS\r
606EFIAPI\r
607EfiDhcp4Release (\r
608 IN EFI_DHCP4_PROTOCOL *This\r
609 )\r
610{\r
611 DHCP_PROTOCOL *Instance;\r
612 DHCP_SERVICE *DhcpSb;\r
613 EFI_STATUS Status;\r
614 EFI_TPL OldTpl;\r
615\r
616 //\r
617 // First validate the parameters\r
618 //\r
619 if (This == NULL) {\r
620 return EFI_INVALID_PARAMETER;\r
621 }\r
622\r
623 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
624\r
625 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
626 return EFI_INVALID_PARAMETER;\r
627 }\r
628\r
629 Status = EFI_SUCCESS;\r
630 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
631 DhcpSb = Instance->Service;\r
632\r
633 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
634 Status = EFI_ACCESS_DENIED;\r
635 goto ON_EXIT;\r
636 }\r
637\r
638 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {\r
639 Status = DhcpSendMessage (\r
640 DhcpSb,\r
641 DhcpSb->Selected,\r
642 DhcpSb->Para,\r
643 DHCP_MSG_RELEASE,\r
644 NULL\r
645 );\r
646\r
647 if (EFI_ERROR (Status)) {\r
648 Status = EFI_DEVICE_ERROR;\r
649 goto ON_EXIT;\r
650 }\r
651 }\r
652\r
653 DhcpCleanLease (DhcpSb);\r
654\r
655ON_EXIT:\r
656 NET_RESTORE_TPL (OldTpl);\r
657 return Status;\r
658}\r
659\r
660\r
661/**\r
662 Stop the current DHCP process. After this, other DHCP child\r
663 can gain control of the service, configure and use it.\r
664\r
665 @param This The DHCP protocol instance\r
666\r
667 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
668 @retval EFI_SUCCESS The DHCP process is stopped.\r
669\r
670**/\r
671STATIC\r
672EFI_STATUS\r
673EFIAPI\r
674EfiDhcp4Stop (\r
675 IN EFI_DHCP4_PROTOCOL *This\r
676 )\r
677{\r
678 DHCP_PROTOCOL *Instance;\r
679 DHCP_SERVICE *DhcpSb;\r
680 EFI_TPL OldTpl;\r
681\r
682 //\r
683 // First validate the parameters\r
684 //\r
685 if (This == NULL) {\r
686 return EFI_INVALID_PARAMETER;\r
687 }\r
688\r
689 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
690\r
691 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
692 return EFI_INVALID_PARAMETER;\r
693 }\r
694\r
695 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
696 DhcpSb = Instance->Service;\r
697\r
698 DhcpCleanLease (DhcpSb);\r
699\r
700 DhcpSb->DhcpState = Dhcp4Stopped;\r
701 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
702\r
703 NET_RESTORE_TPL (OldTpl);\r
704 return EFI_SUCCESS;\r
705}\r
706\r
707\r
708/**\r
709 Build a new DHCP packet from the seed packet. Options may be deleted or\r
710 appended. The caller should free the NewPacket when finished using it.\r
711\r
712 @param This The DHCP protocol instance.\r
713 @param SeedPacket The seed packet to start with\r
714 @param DeleteCount The number of options to delete\r
715 @param DeleteList The options to delete from the packet\r
716 @param AppendCount The number of options to append\r
717 @param AppendList The options to append to the packet\r
718 @param NewPacket The new packet, allocated and built by this\r
719 function.\r
720\r
721 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
722 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory\r
723 @retval EFI_SUCCESS The packet is build.\r
724\r
725**/\r
726STATIC\r
727EFI_STATUS\r
728EFIAPI\r
729EfiDhcp4Build (\r
730 IN EFI_DHCP4_PROTOCOL *This,\r
731 IN EFI_DHCP4_PACKET *SeedPacket,\r
732 IN UINT32 DeleteCount,\r
733 IN UINT8 *DeleteList OPTIONAL,\r
734 IN UINT32 AppendCount,\r
735 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
736 OUT EFI_DHCP4_PACKET **NewPacket\r
737 )\r
738{\r
739 //\r
740 // First validate the parameters\r
741 //\r
742 if ((This == NULL) || (NewPacket == NULL)) {\r
743 return EFI_INVALID_PARAMETER;\r
744 }\r
745\r
746 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
747 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {\r
748\r
749 return EFI_INVALID_PARAMETER;\r
750 }\r
751\r
752 if (((DeleteCount == 0) && (AppendCount == 0)) ||\r
753 ((DeleteCount != 0) && (DeleteList == NULL)) ||\r
754 ((AppendCount != 0) && (AppendList == NULL))) {\r
755\r
756 return EFI_INVALID_PARAMETER;\r
757 }\r
758\r
759 return DhcpBuild (\r
760 SeedPacket,\r
761 DeleteCount,\r
762 DeleteList,\r
763 AppendCount,\r
764 AppendList,\r
765 NewPacket\r
766 );\r
767}\r
768\r
769\r
770/**\r
771 Transmit and receive a packet through this DHCP service.\r
772 This is unsupported.\r
773\r
774 @param This The DHCP protocol instance\r
775 @param Token The transmit and receive instance\r
776\r
777 @retval EFI_UNSUPPORTED It always returns unsupported.\r
778\r
779**/\r
780STATIC\r
781EFI_STATUS\r
782EFIAPI\r
783EfiDhcp4TransmitReceive (\r
784 IN EFI_DHCP4_PROTOCOL *This,\r
785 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
786 )\r
787{\r
788 //\r
789 // This function is for PXE, leave it for now\r
790 //\r
791 return EFI_UNSUPPORTED;\r
792}\r
793\r
794\r
795/**\r
796 Callback function for DhcpIterateOptions. This callback sets the\r
797 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
798 the individual DHCP option in the packet.\r
799\r
800 @param Tag The DHCP option type\r
801 @param Len length of the DHCP option data\r
802 @param Data The DHCP option data\r
803 @param Context The context, to pass several parameters in.\r
804\r
805 @retval EFI_SUCCESS It always returns EFI_SUCCESS\r
806\r
807**/\r
808STATIC\r
809EFI_STATUS\r
810Dhcp4ParseCheckOption (\r
811 IN UINT8 Tag,\r
812 IN UINT8 Len,\r
813 IN UINT8 *Data,\r
814 IN VOID *Context\r
815 )\r
816{\r
817 DHCP_PARSE_CONTEXT *Parse;\r
818\r
819 Parse = (DHCP_PARSE_CONTEXT *) Context;\r
820 Parse->Index++;\r
821\r
822 if (Parse->Index < Parse->OptionCount) {\r
823 //\r
824 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
825 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
826 // pass in the point to option data.\r
827 //\r
828 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
829 }\r
830\r
831 return EFI_SUCCESS;\r
832}\r
833\r
834\r
835/**\r
836 Parse the DHCP options in the Packet into the PacketOptionList.\r
837 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.\r
838\r
839 @param This The DHCP protocol instance\r
840 @param Packet The DHCP packet to parse\r
841 @param OptionCount On input, the size of the PacketOptionList; On\r
842 output, the actual number of options processed.\r
843 @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points\r
844\r
845 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
846 @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.\r
847 @retval EFI_SUCCESS The options are parsed.\r
848\r
849**/\r
850STATIC\r
851EFI_STATUS\r
852EFIAPI\r
853EfiDhcp4Parse (\r
854 IN EFI_DHCP4_PROTOCOL *This,\r
855 IN EFI_DHCP4_PACKET *Packet,\r
856 IN OUT UINT32 *OptionCount,\r
857 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
858 )\r
859{\r
860 DHCP_PARSE_CONTEXT Context;\r
861 EFI_STATUS Status;\r
862\r
863 //\r
864 // First validate the parameters\r
865 //\r
866 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {\r
867 return EFI_INVALID_PARAMETER;\r
868 }\r
869\r
870 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||\r
871 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
872 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
873\r
874 return EFI_INVALID_PARAMETER;\r
875 }\r
876\r
877 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {\r
878 return EFI_BUFFER_TOO_SMALL;\r
879 }\r
880\r
881 NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
882\r
883 Context.Option = PacketOptionList;\r
884 Context.OptionCount = *OptionCount;\r
885 Context.Index = 0;\r
886\r
887 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);\r
888\r
889 if (EFI_ERROR (Status)) {\r
890 return Status;\r
891 }\r
892\r
893 *OptionCount = Context.Index;\r
894\r
895 if (Context.Index > Context.OptionCount) {\r
896 return EFI_BUFFER_TOO_SMALL;\r
897 }\r
898\r
899 return EFI_SUCCESS;\r
900}\r
901\r
902EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {\r
903 EfiDhcp4GetModeData,\r
904 EfiDhcp4Configure,\r
905 EfiDhcp4Start,\r
906 EfiDhcp4RenewRebind,\r
907 EfiDhcp4Release,\r
908 EfiDhcp4Stop,\r
909 EfiDhcp4Build,\r
910 EfiDhcp4TransmitReceive,\r
911 EfiDhcp4Parse\r
912};\r