]> git.proxmox.com Git - mirror_edk2.git/blob - MdeModulePkg/Universal/Network/Ip4ConfigDxe/Ip4Config.c
SourceLevelDebugPkg/SecPeiDebugAgentLib: Restore CPU interrupt state
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4ConfigDxe / Ip4Config.c
1 /** @file
2 This code implements the IP4Config and NicIp4Config protocols.
3
4 Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
5 Copyright (c) 2006 - 2012, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at<BR>
9 http://opensource.org/licenses/bsd-license.php
10
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
13
14 **/
15
16 #include "Ip4Config.h"
17 #include "NicIp4Variable.h"
18
19 //
20 // Ip4 Config Protocol
21 //
22 GLOBAL_REMOVE_IF_UNREFERENCED EFI_IP4_CONFIG_PROTOCOL mIp4ConfigProtocolTemplate = {
23 EfiIp4ConfigStart,
24 EfiIp4ConfigStop,
25 EfiIp4ConfigGetData
26 };
27
28 /**
29 Get the NIC's configure information from the IP4 configure variable.
30 It will remove the invalid variable.
31
32 @param Instance The IP4 CONFIG instance.
33
34 @return NULL if no configure for the NIC in the variable, or it is invalid.
35 Otherwise the pointer to the NIC's IP configure parameter will be returned.
36
37 **/
38 NIC_IP4_CONFIG_INFO *
39 EfiNicIp4ConfigGetInfo (
40 IN IP4_CONFIG_INSTANCE *Instance
41 )
42 {
43 NIC_IP4_CONFIG_INFO *NicConfig;
44
45 //
46 // Read the configuration parameter for this NIC from
47 // the EFI variable
48 //
49 NicConfig = Ip4ConfigReadVariable (Instance);
50 if (NicConfig == NULL) {
51 return NULL;
52 }
53
54 //
55 // Validate the configuration, if the configuration is invalid,
56 // remove it from the variable.
57 //
58 if (!Ip4ConfigIsValid (NicConfig)) {
59 Ip4ConfigWriteVariable (Instance, NULL);
60
61 FreePool (NicConfig);
62 NicConfig = NULL;
63 }
64
65 return NicConfig;
66 }
67
68 /**
69 Set the IP configure parameters for this NIC.
70
71 If Reconfig is TRUE, the IP driver will be informed to discard current
72 auto configure parameter and restart the auto configuration process.
73 If current there is a pending auto configuration, EFI_ALREADY_STARTED is
74 returned. You can only change the configure setting when either
75 the configure has finished or not started yet. If NicConfig, the
76 NIC's configure parameter is removed from the variable.
77
78 @param Instance The IP4 CONFIG instance.
79 @param NicConfig The new NIC IP4 configure parameter.
80 @param Reconfig Inform the IP4 driver to restart the auto
81 configuration.
82
83 @retval EFI_SUCCESS The configure parameter for this NIC was
84 set successfully.
85 @retval EFI_INVALID_PARAMETER This is NULL or the configure parameter is
86 invalid.
87 @retval EFI_ALREADY_STARTED There is a pending auto configuration.
88 @retval EFI_NOT_FOUND No auto configure parameter is found.
89
90 **/
91 EFI_STATUS
92 EFIAPI
93 EfiNicIp4ConfigSetInfo (
94 IN IP4_CONFIG_INSTANCE *Instance,
95 IN NIC_IP4_CONFIG_INFO *NicConfig OPTIONAL,
96 IN BOOLEAN Reconfig
97 )
98 {
99 EFI_STATUS Status;
100
101 //
102 // Validate the parameters
103 //
104 if (Instance == NULL) {
105 return EFI_INVALID_PARAMETER;
106 }
107
108 if ((NicConfig != NULL) && (!Ip4ConfigIsValid (NicConfig) ||
109 !NIC_ADDR_EQUAL (&NicConfig->NicAddr, &Instance->NicAddr))) {
110 return EFI_INVALID_PARAMETER;
111 }
112
113 if (Instance->State == IP4_CONFIG_STATE_STARTED) {
114 return EFI_ALREADY_STARTED;
115 }
116
117 //
118 // Update the parameter in the configure variable
119 //
120 Status = Ip4ConfigWriteVariable (Instance, NicConfig);
121 if (EFI_ERROR (Status)) {
122 return Status;
123 }
124
125 //
126 // Signal the IP4 to run the auto configuration again
127 //
128 if (Reconfig && (Instance->ReconfigEvent != NULL)) {
129 //
130 // When NicConfig is NULL, NIC IP4 configuration parameter is removed,
131 // the auto configuration process should stop running the configuration
132 // policy for the EFI IPv4 Protocol driver.
133 //
134 if (NicConfig == NULL) {
135 Instance->DoNotStart = TRUE;
136 }
137
138 Status = gBS->SignalEvent (Instance->ReconfigEvent);
139 DispatchDpc ();
140 }
141
142 if (NicConfig == NULL) {
143 return Status;
144 }
145 //
146 // A dedicated timer is used to poll underlying media status.In case of
147 // cable swap, a new round auto configuration will be initiated. The timer
148 // starts in DHCP policy only. STATIC policy stops the timer.
149 //
150 if (NicConfig->Source == IP4_CONFIG_SOURCE_DHCP) {
151 gBS->SetTimer (Instance->Timer, TimerPeriodic, TICKS_PER_SECOND);
152 } else if (NicConfig->Source == IP4_CONFIG_SOURCE_STATIC) {
153 gBS->SetTimer (Instance->Timer, TimerCancel, 0);
154 }
155
156 return Status;
157 }
158
159 /**
160 Callback function when DHCP process finished. It will save the
161 retrieved IP configure parameter from DHCP to the NVRam.
162
163 @param Event The callback event
164 @param Context Opaque context to the callback
165
166 @return None
167
168 **/
169 VOID
170 EFIAPI
171 Ip4ConfigOnDhcp4Complete (
172 IN EFI_EVENT Event,
173 IN VOID *Context
174 )
175 {
176 IP4_CONFIG_INSTANCE *Instance;
177 EFI_DHCP4_MODE_DATA Dhcp4Mode;
178 EFI_IP4_IPCONFIG_DATA *Ip4Config;
179 EFI_STATUS Status;
180 BOOLEAN Permanent;
181 IP4_ADDR Subnet;
182 IP4_ADDR Ip1;
183 IP4_ADDR Ip2;
184
185 Instance = (IP4_CONFIG_INSTANCE *) Context;
186 ASSERT (Instance->Dhcp4 != NULL);
187
188 Instance->State = IP4_CONFIG_STATE_CONFIGURED;
189 Instance->Result = EFI_TIMEOUT;
190
191 //
192 // Get the DHCP retrieved parameters
193 //
194 Status = Instance->Dhcp4->GetModeData (Instance->Dhcp4, &Dhcp4Mode);
195
196 if (EFI_ERROR (Status)) {
197 goto ON_EXIT;
198 }
199
200 if (Dhcp4Mode.State == Dhcp4Bound) {
201 //
202 // Save the new configuration retrieved by DHCP both in
203 // the instance and to NVRam. So, both the IP4 driver and
204 // other user can get that address.
205 //
206 Permanent = FALSE;
207
208 if (Instance->NicConfig != NULL) {
209 ASSERT (Instance->NicConfig->Source == IP4_CONFIG_SOURCE_DHCP);
210 Permanent = Instance->NicConfig->Permanent;
211 FreePool (Instance->NicConfig);
212 }
213
214 Instance->NicConfig = AllocatePool (sizeof (NIC_IP4_CONFIG_INFO) + 2* sizeof (EFI_IP4_ROUTE_TABLE));
215
216 if (Instance->NicConfig == NULL) {
217 Instance->Result = EFI_OUT_OF_RESOURCES;
218 goto ON_EXIT;
219 }
220
221 Instance->NicConfig->Ip4Info.RouteTable = (EFI_IP4_ROUTE_TABLE *) (Instance->NicConfig + 1);
222
223 CopyMem (&Instance->NicConfig->NicAddr, &Instance->NicAddr, sizeof (Instance->NicConfig->NicAddr));
224 Instance->NicConfig->Source = IP4_CONFIG_SOURCE_DHCP;
225 Instance->NicConfig->Permanent = Permanent;
226
227 Ip4Config = &Instance->NicConfig->Ip4Info;
228 Ip4Config->StationAddress = Dhcp4Mode.ClientAddress;
229 Ip4Config->SubnetMask = Dhcp4Mode.SubnetMask;
230
231 //
232 // Create a route for the connected network
233 //
234 Ip4Config->RouteTableSize = 1;
235
236 CopyMem (&Ip1, &Dhcp4Mode.ClientAddress, sizeof (IP4_ADDR));
237 CopyMem (&Ip2, &Dhcp4Mode.SubnetMask, sizeof (IP4_ADDR));
238
239 Subnet = Ip1 & Ip2;
240
241 CopyMem (&Ip4Config->RouteTable[0].SubnetAddress, &Subnet, sizeof (EFI_IPv4_ADDRESS));
242 CopyMem (&Ip4Config->RouteTable[0].SubnetMask, &Dhcp4Mode.SubnetMask, sizeof (EFI_IPv4_ADDRESS));
243 ZeroMem (&Ip4Config->RouteTable[0].GatewayAddress, sizeof (EFI_IPv4_ADDRESS));
244
245 //
246 // Create a route if there is a default router.
247 //
248 if (!EFI_IP4_EQUAL (&Dhcp4Mode.RouterAddress, &mZeroIp4Addr)) {
249 Ip4Config->RouteTableSize = 2;
250
251 ZeroMem (&Ip4Config->RouteTable[1].SubnetAddress, sizeof (EFI_IPv4_ADDRESS));
252 ZeroMem (&Ip4Config->RouteTable[1].SubnetMask, sizeof (EFI_IPv4_ADDRESS));
253 CopyMem (&Ip4Config->RouteTable[1].GatewayAddress, &Dhcp4Mode.RouterAddress, sizeof (EFI_IPv4_ADDRESS));
254 }
255
256 Instance->Result = EFI_SUCCESS;
257
258 //
259 // ignore the return status of EfiNicIp4ConfigSetInfo. Network
260 // stack can operate even that failed.
261 //
262 EfiNicIp4ConfigSetInfo (Instance, Instance->NicConfig, FALSE);
263 }
264
265 ON_EXIT:
266 gBS->SignalEvent (Instance->DoneEvent);
267 Ip4ConfigCleanDhcp4 (Instance);
268
269 DispatchDpc ();
270
271 return ;
272 }
273
274 /**
275 Starts running the configuration policy for the EFI IPv4 Protocol driver.
276
277 The Start() function is called to determine and to begin the platform
278 configuration policy by the EFI IPv4 Protocol driver. This determination may
279 be as simple as returning EFI_UNSUPPORTED if there is no EFI IPv4 Protocol
280 driver configuration policy. It may be as involved as loading some defaults
281 from nonvolatile storage, downloading dynamic data from a DHCP server, and
282 checking permissions with a site policy server.
283 Starting the configuration policy is just the beginning. It may finish almost
284 instantly or it may take several minutes before it fails to retrieve configuration
285 information from one or more servers. Once the policy is started, drivers
286 should use the DoneEvent parameter to determine when the configuration policy
287 has completed. EFI_IP4_CONFIG_PROTOCOL.GetData() must then be called to
288 determine if the configuration succeeded or failed.
289 Until the configuration completes successfully, EFI IPv4 Protocol driver instances
290 that are attempting to use default configurations must return EFI_NO_MAPPING.
291 Once the configuration is complete, the EFI IPv4 Configuration Protocol driver
292 signals DoneEvent. The configuration may need to be updated in the future,
293 however; in this case, the EFI IPv4 Configuration Protocol driver must signal
294 ReconfigEvent, and all EFI IPv4 Protocol driver instances that are using default
295 configurations must return EFI_NO_MAPPING until the configuration policy has
296 been rerun.
297
298 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
299 @param DoneEvent Event that will be signaled when the EFI IPv4
300 Protocol driver configuration policy completes
301 execution. This event must be of type EVT_NOTIFY_SIGNAL.
302 @param ReconfigEvent Event that will be signaled when the EFI IPv4
303 Protocol driver configuration needs to be updated.
304 This event must be of type EVT_NOTIFY_SIGNAL.
305
306 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
307 driver is now running.
308 @retval EFI_INVALID_PARAMETER One or more of the following parameters is NULL:
309 This
310 DoneEvent
311 ReconfigEvent
312 @retval EFI_OUT_OF_RESOURCES Required system resources could not be allocated.
313 @retval EFI_ALREADY_STARTED The configuration policy for the EFI IPv4 Protocol
314 driver was already started.
315 @retval EFI_DEVICE_ERROR An unexpected system error or network error occurred.
316 @retval EFI_UNSUPPORTED This interface does not support the EFI IPv4 Protocol
317 driver configuration.
318
319 **/
320 EFI_STATUS
321 EFIAPI
322 EfiIp4ConfigStart (
323 IN EFI_IP4_CONFIG_PROTOCOL *This,
324 IN EFI_EVENT DoneEvent,
325 IN EFI_EVENT ReconfigEvent
326 )
327 {
328 IP4_CONFIG_INSTANCE *Instance;
329 EFI_DHCP4_PROTOCOL *Dhcp4;
330 EFI_DHCP4_MODE_DATA Dhcp4Mode;
331 EFI_DHCP4_PACKET_OPTION *OptionList[1];
332 IP4_CONFIG_DHCP4_OPTION ParaList;
333 EFI_STATUS Status;
334 UINT32 Source;
335 EFI_TPL OldTpl;
336
337 if ((This == NULL) || (DoneEvent == NULL) || (ReconfigEvent == NULL)) {
338 return EFI_INVALID_PARAMETER;
339 }
340
341 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
342
343 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
344
345 if (Instance->State != IP4_CONFIG_STATE_IDLE) {
346 Status = EFI_ALREADY_STARTED;
347
348 goto ON_EXIT;
349 }
350
351 Instance->DoneEvent = DoneEvent;
352 Instance->ReconfigEvent = ReconfigEvent;
353
354 Instance->NicConfig = EfiNicIp4ConfigGetInfo (Instance);
355
356 if (Instance->NicConfig == NULL) {
357 if (Instance->DoNotStart) {
358 Instance->DoNotStart = FALSE;
359 Status = EFI_SUCCESS;
360 goto ON_EXIT;
361 }
362
363 Source = IP4_CONFIG_SOURCE_DHCP;
364 } else {
365 Source = Instance->NicConfig->Source;
366 }
367
368 //
369 // If the source is static, the auto configuration is done.
370 // return now.
371 //
372 if (Source == IP4_CONFIG_SOURCE_STATIC) {
373 Instance->State = IP4_CONFIG_STATE_CONFIGURED;
374 Instance->Result = EFI_SUCCESS;
375
376 gBS->SignalEvent (Instance->DoneEvent);
377 Status = EFI_SUCCESS;
378 goto ON_EXIT;
379 }
380
381 //
382 // Start the dhcp process
383 //
384 ASSERT ((Source == IP4_CONFIG_SOURCE_DHCP) && (Instance->Dhcp4 == NULL));
385
386 Status = NetLibCreateServiceChild (
387 Instance->Controller,
388 Instance->Image,
389 &gEfiDhcp4ServiceBindingProtocolGuid,
390 &Instance->Dhcp4Handle
391 );
392
393 if (EFI_ERROR (Status)) {
394 goto ON_ERROR;
395 }
396
397 Status = gBS->OpenProtocol (
398 Instance->Dhcp4Handle,
399 &gEfiDhcp4ProtocolGuid,
400 (VOID **) &Instance->Dhcp4,
401 Instance->Image,
402 Instance->Controller,
403 EFI_OPEN_PROTOCOL_BY_DRIVER
404 );
405
406 if (EFI_ERROR (Status)) {
407 goto ON_ERROR;
408 }
409
410 //
411 // Check the current DHCP status, if the DHCP process has
412 // already finished, return now.
413 //
414 Dhcp4 = Instance->Dhcp4;
415 Status = Dhcp4->GetModeData (Dhcp4, &Dhcp4Mode);
416
417 if (EFI_ERROR (Status)) {
418 goto ON_ERROR;
419 }
420
421 if (Dhcp4Mode.State == Dhcp4Bound) {
422 Ip4ConfigOnDhcp4Complete (NULL, Instance);
423
424 goto ON_EXIT;
425 }
426
427 //
428 // Try to start the DHCP process. Use most of the current
429 // DHCP configuration to avoid problems if some DHCP client
430 // yields the control of this DHCP service to us.
431 //
432 ParaList.Head.OpCode = DHCP_TAG_PARA_LIST;
433 ParaList.Head.Length = 2;
434 ParaList.Head.Data[0] = DHCP_TAG_NETMASK;
435 ParaList.Route = DHCP_TAG_ROUTER;
436 OptionList[0] = &ParaList.Head;
437 Dhcp4Mode.ConfigData.OptionCount = 1;
438 Dhcp4Mode.ConfigData.OptionList = OptionList;
439
440 Status = Dhcp4->Configure (Dhcp4, &Dhcp4Mode.ConfigData);
441
442 if (EFI_ERROR (Status)) {
443 goto ON_ERROR;
444 }
445
446 //
447 // Start the DHCP process
448 //
449 Status = gBS->CreateEvent (
450 EVT_NOTIFY_SIGNAL,
451 TPL_CALLBACK,
452 Ip4ConfigOnDhcp4Complete,
453 Instance,
454 &Instance->Dhcp4Event
455 );
456
457 if (EFI_ERROR (Status)) {
458 goto ON_ERROR;
459 }
460
461 Status = Dhcp4->Start (Dhcp4, Instance->Dhcp4Event);
462
463 if (EFI_ERROR (Status)) {
464 goto ON_ERROR;
465 }
466
467 Instance->State = IP4_CONFIG_STATE_STARTED;
468 Instance->Result = EFI_NOT_READY;
469
470 ON_ERROR:
471 if (EFI_ERROR (Status)) {
472 Ip4ConfigCleanConfig (Instance);
473 }
474
475 ON_EXIT:
476 gBS->RestoreTPL (OldTpl);
477
478 DispatchDpc ();
479
480 return Status;
481 }
482
483
484 /**
485 Stops running the configuration policy for the EFI IPv4 Protocol driver.
486
487 The Stop() function stops the configuration policy for the EFI IPv4 Protocol driver.
488 All configuration data will be lost after calling Stop().
489
490 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
491
492 @retval EFI_SUCCESS The configuration policy for the EFI IPv4 Protocol
493 driver has been stopped.
494 @retval EFI_INVALID_PARAMETER This is NULL.
495 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
496 driver was not started.
497
498 **/
499 EFI_STATUS
500 EFIAPI
501 EfiIp4ConfigStop (
502 IN EFI_IP4_CONFIG_PROTOCOL *This
503 )
504 {
505 IP4_CONFIG_INSTANCE *Instance;
506 EFI_STATUS Status;
507 EFI_TPL OldTpl;
508
509 if (This == NULL) {
510 return EFI_INVALID_PARAMETER;
511 }
512
513 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
514
515 Status = EFI_SUCCESS;
516 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
517
518 if (Instance->State == IP4_CONFIG_STATE_IDLE) {
519 Status = EFI_NOT_STARTED;
520 goto ON_EXIT;
521 }
522
523 //
524 // Release all the configure parameters. Don't signal the user
525 // event. The user wants to abort the configuration, this isn't
526 // the configuration done or reconfiguration.
527 //
528 Ip4ConfigCleanConfig (Instance);
529
530 ON_EXIT:
531 gBS->RestoreTPL (OldTpl);
532
533 return Status;
534 }
535
536
537 /**
538 Returns the default configuration data (if any) for the EFI IPv4 Protocol driver.
539
540 The GetData() function returns the current configuration data for the EFI IPv4
541 Protocol driver after the configuration policy has completed.
542
543 @param This Pointer to the EFI_IP4_CONFIG_PROTOCOL instance.
544 @param ConfigDataSize On input, the size of the ConfigData buffer.
545 On output, the count of bytes that were written
546 into the ConfigData buffer.
547 @param ConfigData Pointer to the EFI IPv4 Configuration Protocol
548 driver configuration data structure.
549 Type EFI_IP4_IPCONFIG_DATA is defined in
550 "Related Definitions" below.
551
552 @retval EFI_SUCCESS The EFI IPv4 Protocol driver configuration has been returned.
553 @retval EFI_INVALID_PARAMETER This is NULL.
554 @retval EFI_NOT_STARTED The configuration policy for the EFI IPv4 Protocol
555 driver is not running.
556 @retval EFI_NOT_READY EFI IPv4 Protocol driver configuration is still running.
557 @retval EFI_ABORTED EFI IPv4 Protocol driver configuration could not complete.
558 Currently not implemented.
559 @retval EFI_BUFFER_TOO_SMALL *ConfigDataSize is smaller than the configuration
560 data buffer or ConfigData is NULL.
561
562 **/
563 EFI_STATUS
564 EFIAPI
565 EfiIp4ConfigGetData (
566 IN EFI_IP4_CONFIG_PROTOCOL *This,
567 IN OUT UINTN *ConfigDataSize,
568 OUT EFI_IP4_IPCONFIG_DATA *ConfigData OPTIONAL
569 )
570 {
571 IP4_CONFIG_INSTANCE *Instance;
572 NIC_IP4_CONFIG_INFO *NicConfig;
573 EFI_STATUS Status;
574 EFI_TPL OldTpl;
575 UINTN Len;
576
577 if ((This == NULL) || (ConfigDataSize == NULL)) {
578 return EFI_INVALID_PARAMETER;
579 }
580
581 Instance = IP4_CONFIG_INSTANCE_FROM_IP4CONFIG (This);
582
583 Status = EFI_SUCCESS;
584 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
585
586 if (Instance->State == IP4_CONFIG_STATE_IDLE) {
587 Status = EFI_NOT_STARTED;
588 } else if (Instance->State == IP4_CONFIG_STATE_STARTED) {
589 Status = EFI_NOT_READY;
590 }
591
592 if (EFI_ERROR (Status)) {
593 goto ON_EXIT;
594 }
595
596 //
597 // Copy the configure data if auto configuration succeeds.
598 //
599 Status = Instance->Result;
600
601 if (Status == EFI_SUCCESS) {
602 ASSERT (Instance->NicConfig != NULL);
603
604 NicConfig = Instance->NicConfig;
605 Len = SIZEOF_IP4_CONFIG_INFO (&NicConfig->Ip4Info);
606
607 if ((*ConfigDataSize < Len) || (ConfigData == NULL)) {
608 Status = EFI_BUFFER_TOO_SMALL;
609 } else {
610 CopyMem (ConfigData, &NicConfig->Ip4Info, Len);
611 Ip4ConfigFixRouteTablePointer (ConfigData);
612 }
613
614 *ConfigDataSize = Len;
615 }
616
617 ON_EXIT:
618 gBS->RestoreTPL (OldTpl);
619
620 return Status;
621 }
622
623 /**
624 Release all the DHCP related resources.
625
626 @param This The IP4 configure instance
627
628 @return None
629
630 **/
631 VOID
632 Ip4ConfigCleanDhcp4 (
633 IN IP4_CONFIG_INSTANCE *This
634 )
635 {
636 if (This->Dhcp4 != NULL) {
637 This->Dhcp4->Stop (This->Dhcp4);
638
639 gBS->CloseProtocol (
640 This->Dhcp4Handle,
641 &gEfiDhcp4ProtocolGuid,
642 This->Image,
643 This->Controller
644 );
645
646 This->Dhcp4 = NULL;
647 }
648
649 if (This->Dhcp4Handle != NULL) {
650 NetLibDestroyServiceChild (
651 This->Controller,
652 This->Image,
653 &gEfiDhcp4ServiceBindingProtocolGuid,
654 This->Dhcp4Handle
655 );
656
657 This->Dhcp4Handle = NULL;
658 }
659
660 if (This->Dhcp4Event != NULL) {
661 gBS->CloseEvent (This->Dhcp4Event);
662 This->Dhcp4Event = NULL;
663 }
664 }
665
666
667 /**
668 Clean up all the configuration parameters.
669
670 @param Instance The IP4 configure instance
671
672 @return None
673
674 **/
675 VOID
676 Ip4ConfigCleanConfig (
677 IN IP4_CONFIG_INSTANCE *Instance
678 )
679 {
680 if (Instance->NicConfig != NULL) {
681 FreePool (Instance->NicConfig);
682 Instance->NicConfig = NULL;
683 }
684
685 Instance->State = IP4_CONFIG_STATE_IDLE;
686 Instance->DoneEvent = NULL;
687 Instance->ReconfigEvent = NULL;
688
689 Ip4ConfigCleanDhcp4 (Instance);
690 }
691
692
693 /**
694 A dedicated timer is used to poll underlying media status. In case of
695 cable swap, a new round auto configuration will be initiated. The timer
696 will signal the IP4 to run the auto configuration again. IP4 driver will free
697 old IP address related resource, such as route table and Interface, then
698 initiate a DHCP process by IP4Config->Start to acquire new IP, eventually
699 create route table for new IP address.
700
701 @param[in] Event The IP4 service instance's heart beat timer.
702 @param[in] Context The IP4 service instance.
703
704 **/
705 VOID
706 EFIAPI
707 MediaChangeDetect (
708 IN EFI_EVENT Event,
709 IN VOID *Context
710 )
711 {
712 BOOLEAN OldMediaPresent;
713 EFI_STATUS Status;
714 EFI_SIMPLE_NETWORK_MODE SnpModeData;
715 IP4_CONFIG_INSTANCE *Instance;
716
717 Instance = (IP4_CONFIG_INSTANCE *) Context;
718
719 OldMediaPresent = Instance->MediaPresent;
720
721 //
722 // Get fresh mode data from MNP, since underlying media status may change
723 //
724 Status = Instance->Mnp->GetModeData (Instance->Mnp, NULL, &SnpModeData);
725 if (EFI_ERROR (Status) && (Status != EFI_NOT_STARTED)) {
726 return;
727 }
728
729 Instance->MediaPresent = SnpModeData.MediaPresent;
730 //
731 // Media transimit Unpresent to Present means new link movement is detected.
732 //
733 if (!OldMediaPresent && Instance->MediaPresent) {
734 //
735 // Signal the IP4 to run the auto configuration again. IP4 driver will free
736 // old IP address related resource, such as route table and Interface, then
737 // initiate a DHCP round by IP4Config->Start to acquire new IP, eventually
738 // create route table for new IP address.
739 //
740 if (Instance->ReconfigEvent != NULL) {
741 Status = gBS->SignalEvent (Instance->ReconfigEvent);
742 DispatchDpc ();
743 }
744 }
745 }