]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Dhcp4Dxe/Dhcp4Impl.c
Changed the revision number of AutoGen source code since build.exe was regenerated...
[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
72 Dhcp4ModeData->State = DhcpSb->DhcpState;\r
73 CopyMem (&Dhcp4ModeData->ConfigData, &DhcpSb->ActiveConfig, sizeof (EFI_DHCP4_CONFIG_DATA));\r
74 CopyMem (&Dhcp4ModeData->ClientMacAddress, &DhcpSb->Mac, sizeof (EFI_MAC_ADDRESS));\r
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
164 CopyMem (Dst, Src, sizeof (EFI_DHCP4_CONFIG_DATA));\r
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
253 DHCP_PROTOCOL *Instance;\r
254\r
255 Instance = DhcpSb->ActiveChild;\r
256 Config = &DhcpSb->ActiveConfig;\r
257\r
258 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
259 DhcpSb->ActiveChild = NULL;\r
260\r
261 if (Config->DiscoverTimeout != NULL) {\r
262 NetFreePool (Config->DiscoverTimeout);\r
263\r
264 Config->DiscoverTryCount = 0;\r
265 Config->DiscoverTimeout = NULL;\r
266 }\r
267\r
268 if (Config->RequestTimeout != NULL) {\r
269 NetFreePool (Config->RequestTimeout);\r
270\r
271 Config->RequestTryCount = 0;\r
272 Config->RequestTimeout = NULL;\r
273 }\r
274\r
275 Config->Dhcp4Callback = NULL;\r
276 Config->CallbackContext = NULL;\r
277}\r
278\r
279\r
280/**\r
281 Configure the DHCP protocol instance and its underlying DHCP service\r
282 for operation. If Dhcp4CfgData is NULL and the child is currently\r
283 controlling the DHCP service, release the control.\r
284\r
285 @param This The DHCP protocol instance\r
286 @param Dhcp4CfgData The DHCP configure data.\r
287\r
288 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
289 @retval EFI_ACCESS_DENIED The service isn't in one of configurable states,\r
290 or there is already an active child.\r
291 @retval EFI_OUT_OF_RESOURCE Failed to allocate some resources.\r
292 @retval EFI_SUCCESS The child is configured.\r
293\r
294**/\r
295STATIC\r
296EFI_STATUS\r
297EFIAPI\r
298EfiDhcp4Configure (\r
299 IN EFI_DHCP4_PROTOCOL *This,\r
300 IN EFI_DHCP4_CONFIG_DATA *Dhcp4CfgData OPTIONAL\r
301 )\r
302{\r
303 EFI_DHCP4_CONFIG_DATA *Config;\r
304 DHCP_PROTOCOL *Instance;\r
305 DHCP_SERVICE *DhcpSb;\r
306 EFI_STATUS Status;\r
307 EFI_TPL OldTpl;\r
308 UINT32 Index;\r
309 IP4_ADDR Ip;\r
310\r
311 //\r
312 // First validate the parameters\r
313 //\r
314 if (This == NULL) {\r
315 return EFI_INVALID_PARAMETER;\r
316 }\r
317\r
318 if (Dhcp4CfgData != NULL) {\r
319 if (Dhcp4CfgData->DiscoverTryCount && (Dhcp4CfgData->DiscoverTimeout == NULL)) {\r
320 return EFI_INVALID_PARAMETER;\r
321 }\r
322\r
323 if (Dhcp4CfgData->RequestTryCount && (Dhcp4CfgData->RequestTimeout == NULL)) {\r
324 return EFI_INVALID_PARAMETER;\r
325 }\r
326\r
327 if (Dhcp4CfgData->OptionCount && (Dhcp4CfgData->OptionList == NULL)) {\r
328 return EFI_INVALID_PARAMETER;\r
329 }\r
330\r
331 NetCopyMem (&Ip, &Dhcp4CfgData->ClientAddress, sizeof (IP4_ADDR));\r
332\r
333 if ((Ip != 0) && !Ip4IsUnicast (NTOHL (Ip), 0)) {\r
334\r
335 return EFI_INVALID_PARAMETER;\r
336 }\r
337 }\r
338\r
339 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
340\r
341 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
342 return EFI_INVALID_PARAMETER;\r
343 }\r
344\r
345 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
346\r
347 DhcpSb = Instance->Service;\r
348 Config = &DhcpSb->ActiveConfig;\r
349\r
350 Status = EFI_ACCESS_DENIED;\r
351\r
352 if ((DhcpSb->DhcpState != Dhcp4Stopped) &&\r
353 (DhcpSb->DhcpState != Dhcp4Init) &&\r
354 (DhcpSb->DhcpState != Dhcp4InitReboot) &&\r
355 (DhcpSb->DhcpState != Dhcp4Bound)) {\r
356\r
357 goto ON_EXIT;\r
358 }\r
359\r
360 if ((DhcpSb->ActiveChild != NULL) && (DhcpSb->ActiveChild != Instance)) {\r
361 goto ON_EXIT;\r
362 }\r
363\r
364 if (Dhcp4CfgData != NULL) {\r
365 Status = EFI_OUT_OF_RESOURCES;\r
366 DhcpCleanConfigure (Config);\r
367\r
368 if (EFI_ERROR (DhcpCopyConfigure (Config, Dhcp4CfgData))) {\r
369 goto ON_EXIT;\r
370 }\r
371\r
372 DhcpSb->UserOptionLen = 0;\r
373\r
374 for (Index = 0; Index < Dhcp4CfgData->OptionCount; Index++) {\r
375 DhcpSb->UserOptionLen += Dhcp4CfgData->OptionList[Index]->Length + 2;\r
376 }\r
377\r
378 DhcpSb->ActiveChild = Instance;\r
379\r
380 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
381 DhcpSb->ClientAddr = EFI_NTOHL (Dhcp4CfgData->ClientAddress);\r
382\r
383 if (DhcpSb->ClientAddr != 0) {\r
384 DhcpSb->DhcpState = Dhcp4InitReboot;\r
385 } else {\r
386 DhcpSb->DhcpState = Dhcp4Init;\r
387 }\r
388 }\r
389\r
390 DhcpSb->ServiceState = DHCP_CONFIGED;\r
391 Status = EFI_SUCCESS;\r
392\r
393 } else if (DhcpSb->ActiveChild == Instance) {\r
394 Status = EFI_SUCCESS;\r
395 DhcpYieldControl (DhcpSb);\r
396 }\r
397\r
398ON_EXIT:\r
399 NET_RESTORE_TPL (OldTpl);\r
400 return Status;\r
401}\r
402\r
403\r
404/**\r
405 Start the DHCP process.\r
406\r
407 @param This The DHCP protocol instance\r
408 @param CompletionEvent The event to signal is address is acquired.\r
409\r
410 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
411 @retval EFI_NOT_STARTED The protocol hasn't been configured.\r
412 @retval EFI_ALREADY_STARTED The DHCP process has already been started.\r
413 @retval EFI_SUCCESS The DHCP process is started.\r
414\r
415**/\r
416STATIC\r
417EFI_STATUS\r
418EFIAPI\r
419EfiDhcp4Start (\r
420 IN EFI_DHCP4_PROTOCOL *This,\r
421 IN EFI_EVENT CompletionEvent OPTIONAL\r
422 )\r
423{\r
424 DHCP_PROTOCOL *Instance;\r
425 DHCP_SERVICE *DhcpSb;\r
426 EFI_STATUS Status;\r
427 EFI_TPL OldTpl;\r
428\r
429 //\r
430 // First validate the parameters\r
431 //\r
432 if (This == NULL) {\r
433 return EFI_INVALID_PARAMETER;\r
434 }\r
435\r
436 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
437\r
438 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
439 return EFI_INVALID_PARAMETER;\r
440 }\r
441\r
442 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
443 DhcpSb = Instance->Service;\r
444\r
445 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
446 Status = EFI_NOT_STARTED;\r
447 goto ON_ERROR;\r
448 }\r
449\r
450 if ((DhcpSb->DhcpState != Dhcp4Init) && (DhcpSb->DhcpState != Dhcp4InitReboot)) {\r
451 Status = EFI_ALREADY_STARTED;\r
452 goto ON_ERROR;\r
453 }\r
454\r
455 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
456\r
457 if (EFI_ERROR (Status = DhcpInitRequest (DhcpSb))) {\r
458 goto ON_ERROR;\r
459 }\r
460\r
461 //\r
462 // Start/Restart the receiving.\r
463 //\r
464 Status = UdpIoRecvDatagram (DhcpSb->UdpIo, DhcpInput, DhcpSb, 0);\r
465\r
466 if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {\r
467 goto ON_ERROR;\r
468 }\r
469\r
470 Instance->CompletionEvent = CompletionEvent;\r
471\r
472 //\r
473 // Restore the TPL now, don't call poll function at NET_TPL_LOCK.\r
474 //\r
475 NET_RESTORE_TPL (OldTpl);\r
476\r
477 if (CompletionEvent == NULL) {\r
478 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
479 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
480 }\r
481\r
482 return DhcpSb->IoStatus;\r
483 }\r
484\r
485 return EFI_SUCCESS;\r
486\r
487ON_ERROR:\r
488 NET_RESTORE_TPL (OldTpl);\r
489 return Status;\r
490}\r
491\r
492\r
493/**\r
494 Request an extra manual renew/rebind.\r
495\r
496 @param This The DHCP protocol instance\r
497 @param RebindRequest TRUE if request a rebind, otherwise renew it\r
498 @param CompletionEvent Event to signal when complete\r
499\r
500 @retval EFI_INVALID_PARAMETER The parameters are invalid\r
501 @retval EFI_NOT_STARTED The DHCP protocol hasn't been started.\r
502 @retval EFI_ACCESS_DENIED The DHCP protocol isn't in Bound state.\r
503 @retval EFI_SUCCESS The DHCP is renewed/rebound.\r
504\r
505**/\r
506STATIC\r
507EFI_STATUS\r
508EFIAPI\r
509EfiDhcp4RenewRebind (\r
510 IN EFI_DHCP4_PROTOCOL *This,\r
511 IN BOOLEAN RebindRequest,\r
512 IN EFI_EVENT CompletionEvent OPTIONAL\r
513 )\r
514{\r
515 DHCP_PROTOCOL *Instance;\r
516 DHCP_SERVICE *DhcpSb;\r
517 EFI_STATUS Status;\r
518 EFI_TPL OldTpl;\r
519\r
520 //\r
521 // First validate the parameters\r
522 //\r
523 if (This == NULL) {\r
524 return EFI_INVALID_PARAMETER;\r
525 }\r
526\r
527 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
528\r
529 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
530 return EFI_INVALID_PARAMETER;\r
531 }\r
532\r
533 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
534 DhcpSb = Instance->Service;\r
535\r
536 if (DhcpSb->DhcpState == Dhcp4Stopped) {\r
537 Status = EFI_NOT_STARTED;\r
538 goto ON_ERROR;\r
539 }\r
540\r
541 if (DhcpSb->DhcpState != Dhcp4Bound) {\r
542 Status = EFI_ACCESS_DENIED;\r
543 goto ON_ERROR;\r
544 }\r
545\r
546 if (DHCP_IS_BOOTP (DhcpSb->Para)) {\r
547 return EFI_SUCCESS;\r
548 }\r
549\r
550 //\r
551 // Transit the states then send a extra DHCP request\r
552 //\r
553 if (!RebindRequest) {\r
554 DhcpSetState (DhcpSb, Dhcp4Renewing, FALSE);\r
555 } else {\r
556 DhcpSetState (DhcpSb, Dhcp4Rebinding, FALSE);\r
557 }\r
558\r
559 Status = DhcpSendMessage (\r
560 DhcpSb,\r
561 DhcpSb->Selected,\r
562 DhcpSb->Para,\r
563 DHCP_MSG_REQUEST,\r
564 "Extra renew/rebind by the application"\r
565 );\r
566\r
567 if (EFI_ERROR (Status)) {\r
568 DhcpSetState (DhcpSb, Dhcp4Bound, FALSE);\r
569 goto ON_ERROR;\r
570 }\r
571\r
572 DhcpSb->ExtraRefresh = TRUE;\r
573 DhcpSb->IoStatus = EFI_ALREADY_STARTED;\r
574 Instance->RenewRebindEvent = CompletionEvent;\r
575\r
576 NET_RESTORE_TPL (OldTpl);\r
577\r
578 if (CompletionEvent == NULL) {\r
579 while (DhcpSb->IoStatus == EFI_ALREADY_STARTED) {\r
580 DhcpSb->UdpIo->Udp->Poll (DhcpSb->UdpIo->Udp);\r
581 }\r
582\r
583 return DhcpSb->IoStatus;\r
584 }\r
585\r
586 return EFI_SUCCESS;\r
587\r
588ON_ERROR:\r
589 NET_RESTORE_TPL (OldTpl);\r
590 return Status;\r
591}\r
592\r
593\r
594/**\r
595 Release the current acquired lease.\r
596\r
597 @param This The DHCP protocol instance\r
598\r
599 @retval EFI_INVALID_PARAMETER The parameter is invalid\r
600 @retval EFI_DEVICE_ERROR Failed to transmit the DHCP release packet\r
601 @retval EFI_ACCESS_DENIED The DHCP service isn't in one of the connected\r
602 state.\r
603 @retval EFI_SUCCESS The lease is released.\r
604\r
605**/\r
606STATIC\r
607EFI_STATUS\r
608EFIAPI\r
609EfiDhcp4Release (\r
610 IN EFI_DHCP4_PROTOCOL *This\r
611 )\r
612{\r
613 DHCP_PROTOCOL *Instance;\r
614 DHCP_SERVICE *DhcpSb;\r
615 EFI_STATUS Status;\r
616 EFI_TPL OldTpl;\r
617\r
618 //\r
619 // First validate the parameters\r
620 //\r
621 if (This == NULL) {\r
622 return EFI_INVALID_PARAMETER;\r
623 }\r
624\r
625 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
626\r
627 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
628 return EFI_INVALID_PARAMETER;\r
629 }\r
630\r
631 Status = EFI_SUCCESS;\r
632 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
633 DhcpSb = Instance->Service;\r
634\r
635 if ((DhcpSb->DhcpState != Dhcp4InitReboot) && (DhcpSb->DhcpState != Dhcp4Bound)) {\r
636 Status = EFI_ACCESS_DENIED;\r
637 goto ON_EXIT;\r
638 }\r
639\r
640 if (!DHCP_IS_BOOTP (DhcpSb->Para) && (DhcpSb->DhcpState == Dhcp4Bound)) {\r
641 Status = DhcpSendMessage (\r
642 DhcpSb,\r
643 DhcpSb->Selected,\r
644 DhcpSb->Para,\r
645 DHCP_MSG_RELEASE,\r
646 NULL\r
647 );\r
648\r
649 if (EFI_ERROR (Status)) {\r
650 Status = EFI_DEVICE_ERROR;\r
651 goto ON_EXIT;\r
652 }\r
653 }\r
654\r
655 DhcpCleanLease (DhcpSb);\r
656\r
657ON_EXIT:\r
658 NET_RESTORE_TPL (OldTpl);\r
659 return Status;\r
660}\r
661\r
662\r
663/**\r
664 Stop the current DHCP process. After this, other DHCP child\r
665 can gain control of the service, configure and use it.\r
666\r
667 @param This The DHCP protocol instance\r
668\r
669 @retval EFI_INVALID_PARAMETER The parameter is invalid.\r
670 @retval EFI_SUCCESS The DHCP process is stopped.\r
671\r
672**/\r
673STATIC\r
674EFI_STATUS\r
675EFIAPI\r
676EfiDhcp4Stop (\r
677 IN EFI_DHCP4_PROTOCOL *This\r
678 )\r
679{\r
680 DHCP_PROTOCOL *Instance;\r
681 DHCP_SERVICE *DhcpSb;\r
682 EFI_TPL OldTpl;\r
683\r
684 //\r
685 // First validate the parameters\r
686 //\r
687 if (This == NULL) {\r
688 return EFI_INVALID_PARAMETER;\r
689 }\r
690\r
691 Instance = DHCP_INSTANCE_FROM_THIS (This);\r
692\r
693 if (Instance->Signature != DHCP_PROTOCOL_SIGNATURE) {\r
694 return EFI_INVALID_PARAMETER;\r
695 }\r
696\r
697 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
698 DhcpSb = Instance->Service;\r
699\r
700 DhcpCleanLease (DhcpSb);\r
701\r
702 DhcpSb->DhcpState = Dhcp4Stopped;\r
703 DhcpSb->ServiceState = DHCP_UNCONFIGED;\r
704\r
705 NET_RESTORE_TPL (OldTpl);\r
706 return EFI_SUCCESS;\r
707}\r
708\r
709\r
710/**\r
711 Build a new DHCP packet from the seed packet. Options may be deleted or\r
712 appended. The caller should free the NewPacket when finished using it.\r
713\r
714 @param This The DHCP protocol instance.\r
715 @param SeedPacket The seed packet to start with\r
716 @param DeleteCount The number of options to delete\r
717 @param DeleteList The options to delete from the packet\r
718 @param AppendCount The number of options to append\r
719 @param AppendList The options to append to the packet\r
720 @param NewPacket The new packet, allocated and built by this\r
721 function.\r
722\r
723 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
724 @retval EFI_OUT_OF_RESOURCES Failed to allocate memory\r
725 @retval EFI_SUCCESS The packet is build.\r
726\r
727**/\r
728STATIC\r
729EFI_STATUS\r
730EFIAPI\r
731EfiDhcp4Build (\r
732 IN EFI_DHCP4_PROTOCOL *This,\r
733 IN EFI_DHCP4_PACKET *SeedPacket,\r
734 IN UINT32 DeleteCount,\r
735 IN UINT8 *DeleteList OPTIONAL,\r
736 IN UINT32 AppendCount,\r
737 IN EFI_DHCP4_PACKET_OPTION *AppendList[] OPTIONAL,\r
738 OUT EFI_DHCP4_PACKET **NewPacket\r
739 )\r
740{\r
741 //\r
742 // First validate the parameters\r
743 //\r
744 if ((This == NULL) || (NewPacket == NULL)) {\r
745 return EFI_INVALID_PARAMETER;\r
746 }\r
747\r
748 if ((SeedPacket == NULL) || (SeedPacket->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
749 EFI_ERROR (DhcpValidateOptions (SeedPacket, NULL))) {\r
750\r
751 return EFI_INVALID_PARAMETER;\r
752 }\r
753\r
754 if (((DeleteCount == 0) && (AppendCount == 0)) ||\r
755 ((DeleteCount != 0) && (DeleteList == NULL)) ||\r
756 ((AppendCount != 0) && (AppendList == NULL))) {\r
757\r
758 return EFI_INVALID_PARAMETER;\r
759 }\r
760\r
761 return DhcpBuild (\r
762 SeedPacket,\r
763 DeleteCount,\r
764 DeleteList,\r
765 AppendCount,\r
766 AppendList,\r
767 NewPacket\r
768 );\r
769}\r
770\r
771\r
772/**\r
773 Transmit and receive a packet through this DHCP service.\r
774 This is unsupported.\r
775\r
776 @param This The DHCP protocol instance\r
777 @param Token The transmit and receive instance\r
778\r
779 @retval EFI_UNSUPPORTED It always returns unsupported.\r
780\r
781**/\r
782STATIC\r
783EFI_STATUS\r
784EFIAPI\r
785EfiDhcp4TransmitReceive (\r
786 IN EFI_DHCP4_PROTOCOL *This,\r
787 IN EFI_DHCP4_TRANSMIT_RECEIVE_TOKEN *Token\r
788 )\r
789{\r
790 //\r
791 // This function is for PXE, leave it for now\r
792 //\r
793 return EFI_UNSUPPORTED;\r
794}\r
795\r
796\r
797/**\r
798 Callback function for DhcpIterateOptions. This callback sets the\r
799 EFI_DHCP4_PACKET_OPTION array in the DHCP_PARSE_CONTEXT to point\r
800 the individual DHCP option in the packet.\r
801\r
802 @param Tag The DHCP option type\r
803 @param Len length of the DHCP option data\r
804 @param Data The DHCP option data\r
805 @param Context The context, to pass several parameters in.\r
806\r
807 @retval EFI_SUCCESS It always returns EFI_SUCCESS\r
808\r
809**/\r
810STATIC\r
811EFI_STATUS\r
812Dhcp4ParseCheckOption (\r
813 IN UINT8 Tag,\r
814 IN UINT8 Len,\r
815 IN UINT8 *Data,\r
816 IN VOID *Context\r
817 )\r
818{\r
819 DHCP_PARSE_CONTEXT *Parse;\r
820\r
821 Parse = (DHCP_PARSE_CONTEXT *) Context;\r
822 Parse->Index++;\r
823\r
824 if (Parse->Index < Parse->OptionCount) {\r
825 //\r
826 // Use _CR to get the memory position of EFI_DHCP4_PACKET_OPTION for\r
827 // the EFI_DHCP4_PACKET_OPTION->Data because DhcpIterateOptions only\r
828 // pass in the point to option data.\r
829 //\r
830 Parse->Option[Parse->Index - 1] = _CR (Data, EFI_DHCP4_PACKET_OPTION, Data);\r
831 }\r
832\r
833 return EFI_SUCCESS;\r
834}\r
835\r
836\r
837/**\r
838 Parse the DHCP options in the Packet into the PacketOptionList.\r
839 User should allocate this array of EFI_DHCP4_PACKET_OPTION points.\r
840\r
841 @param This The DHCP protocol instance\r
842 @param Packet The DHCP packet to parse\r
843 @param OptionCount On input, the size of the PacketOptionList; On\r
844 output, the actual number of options processed.\r
845 @param PacketOptionList The array of EFI_DHCP4_PACKET_OPTION points\r
846\r
847 @retval EFI_INVALID_PARAMETER The parameters are invalid.\r
848 @retval EFI_BUFFER_TOO_SMALL A bigger array of points is needed.\r
849 @retval EFI_SUCCESS The options are parsed.\r
850\r
851**/\r
852STATIC\r
853EFI_STATUS\r
854EFIAPI\r
855EfiDhcp4Parse (\r
856 IN EFI_DHCP4_PROTOCOL *This,\r
857 IN EFI_DHCP4_PACKET *Packet,\r
858 IN OUT UINT32 *OptionCount,\r
859 OUT EFI_DHCP4_PACKET_OPTION *PacketOptionList[] OPTIONAL\r
860 )\r
861{\r
862 DHCP_PARSE_CONTEXT Context;\r
863 EFI_STATUS Status;\r
864\r
865 //\r
866 // First validate the parameters\r
867 //\r
868 if ((This == NULL) || (Packet == NULL) || (OptionCount == NULL)) {\r
869 return EFI_INVALID_PARAMETER;\r
870 }\r
871\r
872 if ((Packet->Size < Packet->Length + 2 * sizeof (UINT32)) ||\r
873 (Packet->Dhcp4.Magik != DHCP_OPTION_MAGIC) ||\r
874 EFI_ERROR (DhcpValidateOptions (Packet, NULL))) {\r
875\r
876 return EFI_INVALID_PARAMETER;\r
877 }\r
878\r
879 if ((*OptionCount != 0) && (PacketOptionList == NULL)) {\r
880 return EFI_BUFFER_TOO_SMALL;\r
881 }\r
882\r
883 NetZeroMem (PacketOptionList, *OptionCount * sizeof (EFI_DHCP4_PACKET_OPTION *));\r
884\r
885 Context.Option = PacketOptionList;\r
886 Context.OptionCount = *OptionCount;\r
887 Context.Index = 0;\r
888\r
889 Status = DhcpIterateOptions (Packet, Dhcp4ParseCheckOption, &Context);\r
890\r
891 if (EFI_ERROR (Status)) {\r
892 return Status;\r
893 }\r
894\r
895 *OptionCount = Context.Index;\r
896\r
897 if (Context.Index > Context.OptionCount) {\r
898 return EFI_BUFFER_TOO_SMALL;\r
899 }\r
900\r
901 return EFI_SUCCESS;\r
902}\r
903\r
904EFI_DHCP4_PROTOCOL mDhcp4ProtocolTemplate = {\r
905 EfiDhcp4GetModeData,\r
906 EfiDhcp4Configure,\r
907 EfiDhcp4Start,\r
908 EfiDhcp4RenewRebind,\r
909 EfiDhcp4Release,\r
910 EfiDhcp4Stop,\r
911 EfiDhcp4Build,\r
912 EfiDhcp4TransmitReceive,\r
913 EfiDhcp4Parse\r
914};\r