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