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