]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg: Clean up source files
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
CommitLineData
772db4bb 1/** @file\r
3e8c18da 2 The driver binding and service binding protocol for IP4 driver.\r
e2851998 3\r
018432f0 4Copyright (c) 2005 - 2018, Intel Corporation. All rights reserved.<BR>\r
c79de074
SEHM
5(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
6\r
e5eed7d3 7This program and the accompanying materials\r
772db4bb 8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
772db4bb 15**/\r
16\r
17#include "Ip4Impl.h"\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
20 Ip4DriverBindingSupported,\r
21 Ip4DriverBindingStart,\r
22 Ip4DriverBindingStop,\r
23 0xa,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
c79de074
SEHM
28BOOLEAN mIpSec2Installed = FALSE;\r
29\r
30/**\r
31 Callback function for IpSec2 Protocol install.\r
32\r
33 @param[in] Event Event whose notification function is being invoked\r
34 @param[in] Context Pointer to the notification function's context\r
35\r
36**/\r
37VOID\r
38EFIAPI\r
39IpSec2InstalledCallback (\r
40 IN EFI_EVENT Event,\r
41 IN VOID *Context\r
42 )\r
43{\r
5aae2d35 44 EFI_STATUS Status;\r
c79de074 45 //\r
5aae2d35
FS
46 // Test if protocol was even found.\r
47 // Notification function will be called at least once.\r
c79de074 48 //\r
5f74808d 49 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **)&mIpSec);\r
5aae2d35
FS
50 if (Status == EFI_SUCCESS && mIpSec != NULL) {\r
51 //\r
52 // Close the event so it does not get called again.\r
53 //\r
54 gBS->CloseEvent (Event);\r
55\r
56 mIpSec2Installed = TRUE;\r
57 }\r
c79de074
SEHM
58}\r
59\r
5405e9a6 60/**\r
61 This is the declaration of an EFI image entry point. This entry point is\r
62 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
63 both device drivers and bus drivers.\r
e2851998 64\r
5405e9a6 65 The entry point for IP4 driver which install the driver\r
66 binding and component name protocol on its image.\r
67\r
3e8c18da 68 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
69 @param[in] SystemTable A pointer to the EFI System Table.\r
5405e9a6 70\r
71 @retval EFI_SUCCESS The operation completed successfully.\r
72 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
73\r
74**/\r
772db4bb 75EFI_STATUS\r
76EFIAPI\r
77Ip4DriverEntryPoint (\r
78 IN EFI_HANDLE ImageHandle,\r
79 IN EFI_SYSTEM_TABLE *SystemTable\r
80 )\r
772db4bb 81{\r
c79de074
SEHM
82 VOID *Registration;\r
83\r
84 EfiCreateProtocolNotifyEvent (\r
85 &gEfiIpSec2ProtocolGuid,\r
86 TPL_CALLBACK,\r
87 IpSec2InstalledCallback,\r
88 NULL,\r
89 &Registration\r
90 );\r
91\r
83cbd279 92 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 93 ImageHandle,\r
94 SystemTable,\r
95 &gIp4DriverBinding,\r
96 ImageHandle,\r
97 &gIp4ComponentName,\r
83cbd279 98 &gIp4ComponentName2\r
772db4bb 99 );\r
100}\r
101\r
772db4bb 102/**\r
5405e9a6 103 Test to see if this driver supports ControllerHandle. This service\r
104 is called by the EFI boot service ConnectController(). In\r
105 order to make drivers as small as possible, there are a few calling\r
106 restrictions for this service. ConnectController() must\r
107 follow these calling restrictions. If any other agent wishes to call\r
108 Supported() it must also follow these calling restrictions.\r
109\r
3e8c18da 110 @param[in] This Protocol instance pointer.\r
111 @param[in] ControllerHandle Handle of device to test\r
112 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
113 device to start.\r
5405e9a6 114\r
115 @retval EFI_SUCCESS This driver supports this device\r
116 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
117 @retval other This driver does not support this device\r
772db4bb 118\r
119**/\r
120EFI_STATUS\r
121EFIAPI\r
122Ip4DriverBindingSupported (\r
123 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
124 IN EFI_HANDLE ControllerHandle,\r
125 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
126 )\r
127{\r
128 EFI_STATUS Status;\r
129\r
130 //\r
131 // Test for the MNP service binding Protocol\r
132 //\r
133 Status = gBS->OpenProtocol (\r
134 ControllerHandle,\r
135 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
136 NULL,\r
137 This->DriverBindingHandle,\r
138 ControllerHandle,\r
139 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
140 );\r
141\r
142 if (EFI_ERROR (Status)) {\r
143 return Status;\r
144 }\r
145\r
146 //\r
147 // Test for the Arp service binding Protocol\r
148 //\r
149 Status = gBS->OpenProtocol (\r
150 ControllerHandle,\r
151 &gEfiArpServiceBindingProtocolGuid,\r
152 NULL,\r
153 This->DriverBindingHandle,\r
154 ControllerHandle,\r
155 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
156 );\r
157\r
158 return Status;\r
159}\r
160\r
2ff29212 161/**\r
162 Clean up a IP4 service binding instance. It will release all\r
163 the resource allocated by the instance. The instance may be\r
164 partly initialized, or partly destroyed. If a resource is\r
75dce340 165 destroyed, it is marked as that in case the destroy failed and\r
2ff29212 166 being called again later.\r
167\r
1f6729ff 168 @param[in] IpSb The IP4 service binding instance to clean up\r
2ff29212 169\r
170 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
171 @retval other Failed to clean up some of the resources.\r
172\r
173**/\r
772db4bb 174EFI_STATUS\r
175Ip4CleanService (\r
176 IN IP4_SERVICE *IpSb\r
177 );\r
178\r
179\r
180/**\r
5405e9a6 181 Create a new IP4 driver service binding private instance.\r
772db4bb 182\r
3e8c18da 183 @param Controller The controller that has MNP service binding\r
184 installed\r
185 @param ImageHandle The IP4 driver's image handle\r
186 @param Service The variable to receive the newly created IP4\r
187 service.\r
772db4bb 188\r
189 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource\r
190 @retval EFI_SUCCESS A new IP4 service binding private is created.\r
5405e9a6 191 @retval other Other error occurs.\r
772db4bb 192\r
193**/\r
772db4bb 194EFI_STATUS\r
195Ip4CreateService (\r
196 IN EFI_HANDLE Controller,\r
197 IN EFI_HANDLE ImageHandle,\r
198 OUT IP4_SERVICE **Service\r
199 )\r
200{\r
201 IP4_SERVICE *IpSb;\r
202 EFI_STATUS Status;\r
203\r
204 ASSERT (Service != NULL);\r
205\r
206 *Service = NULL;\r
207\r
208 //\r
209 // allocate a service private data then initialize all the filed to\r
210 // empty resources, so if any thing goes wrong when allocating\r
211 // resources, Ip4CleanService can be called to clean it up.\r
212 //\r
1f6729ff 213 IpSb = AllocateZeroPool (sizeof (IP4_SERVICE));\r
772db4bb 214\r
215 if (IpSb == NULL) {\r
216 return EFI_OUT_OF_RESOURCES;\r
217 }\r
218\r
219 IpSb->Signature = IP4_SERVICE_SIGNATURE;\r
220 IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;\r
221 IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
222 IpSb->State = IP4_SERVICE_UNSTARTED;\r
772db4bb 223\r
224 IpSb->NumChildren = 0;\r
e48e37fc 225 InitializeListHead (&IpSb->Children);\r
772db4bb 226\r
e48e37fc 227 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 228 IpSb->DefaultInterface = NULL;\r
229 IpSb->DefaultRouteTable = NULL;\r
230\r
231 Ip4InitAssembleTable (&IpSb->Assemble);\r
232\r
233 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
e48e37fc 234 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 235\r
236 IpSb->Image = ImageHandle;\r
237 IpSb->Controller = Controller;\r
238\r
239 IpSb->MnpChildHandle = NULL;\r
240 IpSb->Mnp = NULL;\r
241\r
242 IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
243 IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
244 IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
245 IpSb->MnpConfigData.EnableUnicastReceive = TRUE;\r
246 IpSb->MnpConfigData.EnableMulticastReceive = TRUE;\r
247 IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;\r
248 IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
249 IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;\r
250 IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
251 IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;\r
252\r
e48e37fc 253 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
772db4bb 254\r
1f6729ff 255 IpSb->Timer = NULL;\r
018432f0 256 IpSb->ReconfigCheckTimer = NULL;\r
772db4bb 257\r
2c320007 258 IpSb->ReconfigEvent = NULL;\r
e371cc14
JW
259\r
260 IpSb->Reconfig = FALSE;\r
d1102dba 261\r
2c320007
JW
262 IpSb->MediaPresent = TRUE;\r
263\r
772db4bb 264 //\r
265 // Create various resources. First create the route table, timer\r
7648748e 266 // event, ReconfigEvent and MNP child. IGMP, interface's initialization depend\r
772db4bb 267 // on the MNP child.\r
268 //\r
269 IpSb->DefaultRouteTable = Ip4CreateRouteTable ();\r
270\r
271 if (IpSb->DefaultRouteTable == NULL) {\r
272 Status = EFI_OUT_OF_RESOURCES;\r
273 goto ON_ERROR;\r
274 }\r
275\r
276 Status = gBS->CreateEvent (\r
277 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 278 TPL_CALLBACK,\r
772db4bb 279 Ip4TimerTicking,\r
280 IpSb,\r
281 &IpSb->Timer\r
282 );\r
283\r
284 if (EFI_ERROR (Status)) {\r
285 goto ON_ERROR;\r
286 }\r
287\r
018432f0
WF
288 Status = gBS->CreateEvent (\r
289 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
290 TPL_CALLBACK,\r
291 Ip4TimerReconfigChecking,\r
292 IpSb,\r
293 &IpSb->ReconfigCheckTimer\r
294 );\r
295\r
296 if (EFI_ERROR (Status)) {\r
297 goto ON_ERROR;\r
298 }\r
299\r
7648748e
JW
300 Status = gBS->CreateEvent (\r
301 EVT_NOTIFY_SIGNAL,\r
302 TPL_NOTIFY,\r
303 Ip4AutoReconfigCallBack,\r
304 IpSb,\r
305 &IpSb->ReconfigEvent\r
306 );\r
307 if (EFI_ERROR (Status)) {\r
308 goto ON_ERROR;\r
309 }\r
310\r
772db4bb 311 Status = NetLibCreateServiceChild (\r
312 Controller,\r
313 ImageHandle,\r
314 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
315 &IpSb->MnpChildHandle\r
316 );\r
317\r
318 if (EFI_ERROR (Status)) {\r
319 goto ON_ERROR;\r
320 }\r
321\r
322 Status = gBS->OpenProtocol (\r
323 IpSb->MnpChildHandle,\r
324 &gEfiManagedNetworkProtocolGuid,\r
325 (VOID **) &IpSb->Mnp,\r
326 ImageHandle,\r
327 Controller,\r
328 EFI_OPEN_PROTOCOL_BY_DRIVER\r
329 );\r
330\r
331 if (EFI_ERROR (Status)) {\r
332 goto ON_ERROR;\r
333 }\r
334\r
335 Status = Ip4ServiceConfigMnp (IpSb, TRUE);\r
336\r
337 if (EFI_ERROR (Status)) {\r
338 goto ON_ERROR;\r
339 }\r
340\r
341 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
342\r
343 if (EFI_ERROR (Status)) {\r
344 goto ON_ERROR;\r
345 }\r
346\r
347 Status = Ip4InitIgmp (IpSb);\r
348\r
349 if (EFI_ERROR (Status)) {\r
350 goto ON_ERROR;\r
351 }\r
352\r
1f6729ff 353 IpSb->MacString = NULL;\r
354 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
d1102dba 355\r
1f6729ff 356 if (EFI_ERROR (Status)) {\r
357 goto ON_ERROR;\r
358 }\r
359\r
772db4bb 360 IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
361\r
362 if (IpSb->DefaultInterface == NULL) {\r
363 Status = EFI_OUT_OF_RESOURCES;\r
364 goto ON_ERROR;\r
365 }\r
366\r
e48e37fc 367 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
772db4bb 368\r
1f6729ff 369 ZeroMem (&IpSb->Ip4Config2Instance, sizeof (IP4_CONFIG2_INSTANCE));\r
d1102dba 370\r
1f6729ff 371 Status = Ip4Config2InitInstance (&IpSb->Ip4Config2Instance);\r
372\r
373 if (EFI_ERROR (Status)) {\r
374 goto ON_ERROR;\r
375 }\r
376\r
a1503a32 377 IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
779ae357 378 if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
379 //\r
380 // This is a VLAN device, reduce MTU by VLAN tag length\r
381 //\r
382 IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
383 }\r
9e375eb1 384 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
772db4bb 385 *Service = IpSb;\r
1f6729ff 386\r
772db4bb 387 return EFI_SUCCESS;\r
388\r
389ON_ERROR:\r
390 Ip4CleanService (IpSb);\r
766c7483 391 FreePool (IpSb);\r
772db4bb 392\r
393 return Status;\r
394}\r
395\r
396\r
397/**\r
398 Clean up a IP4 service binding instance. It will release all\r
399 the resource allocated by the instance. The instance may be\r
5405e9a6 400 partly initialized, or partly destroyed. If a resource is\r
75dce340 401 destroyed, it is marked as that in case the destroy failed and\r
772db4bb 402 being called again later.\r
403\r
1f6729ff 404 @param[in] IpSb The IP4 service binding instance to clean up\r
772db4bb 405\r
406 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
5405e9a6 407 @retval other Failed to clean up some of the resources.\r
772db4bb 408\r
409**/\r
410EFI_STATUS\r
411Ip4CleanService (\r
412 IN IP4_SERVICE *IpSb\r
413 )\r
414{\r
415 EFI_STATUS Status;\r
416\r
524813f3
FS
417 IpSb->State = IP4_SERVICE_DESTROY;\r
418\r
419 if (IpSb->Timer != NULL) {\r
420 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
421 gBS->CloseEvent (IpSb->Timer);\r
422\r
423 IpSb->Timer = NULL;\r
424 }\r
425\r
018432f0
WF
426 if (IpSb->ReconfigCheckTimer != NULL) {\r
427 gBS->SetTimer (IpSb->ReconfigCheckTimer, TimerCancel, 0);\r
428 gBS->CloseEvent (IpSb->ReconfigCheckTimer);\r
429\r
430 IpSb->ReconfigCheckTimer = NULL;\r
431 }\r
432\r
772db4bb 433 if (IpSb->DefaultInterface != NULL) {\r
434 Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
435\r
436 if (EFI_ERROR (Status)) {\r
437 return Status;\r
438 }\r
439\r
440 IpSb->DefaultInterface = NULL;\r
441 }\r
442\r
443 if (IpSb->DefaultRouteTable != NULL) {\r
444 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
445 IpSb->DefaultRouteTable = NULL;\r
446 }\r
447\r
448 Ip4CleanAssembleTable (&IpSb->Assemble);\r
449\r
450 if (IpSb->MnpChildHandle != NULL) {\r
5405e9a6 451 if (IpSb->Mnp != NULL) {\r
772db4bb 452 gBS->CloseProtocol (\r
5405e9a6 453 IpSb->MnpChildHandle,\r
454 &gEfiManagedNetworkProtocolGuid,\r
455 IpSb->Image,\r
456 IpSb->Controller\r
457 );\r
772db4bb 458\r
459 IpSb->Mnp = NULL;\r
460 }\r
461\r
462 NetLibDestroyServiceChild (\r
463 IpSb->Controller,\r
464 IpSb->Image,\r
465 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
466 IpSb->MnpChildHandle\r
467 );\r
468\r
469 IpSb->MnpChildHandle = NULL;\r
470 }\r
471\r
2c320007
JW
472 if (IpSb->ReconfigEvent != NULL) {\r
473 gBS->CloseEvent (IpSb->ReconfigEvent);\r
474\r
475 IpSb->ReconfigEvent = NULL;\r
476 }\r
477\r
e371cc14
JW
478 IpSb->Reconfig = FALSE;\r
479\r
1f6729ff 480 if (IpSb->MacString != NULL) {\r
481 FreePool (IpSb->MacString);\r
772db4bb 482 }\r
483\r
1f6729ff 484 Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
485\r
772db4bb 486 return EFI_SUCCESS;\r
487}\r
488\r
216f7970 489/**\r
490 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
d1102dba 491\r
216f7970 492 @param[in] Entry The entry to be removed.\r
493 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
494\r
495 @retval EFI_SUCCESS The entry has been removed successfully.\r
496 @retval Others Fail to remove the entry.\r
497\r
498**/\r
499EFI_STATUS\r
1f7eb561 500EFIAPI\r
216f7970 501Ip4DestroyChildEntryInHandleBuffer (\r
502 IN LIST_ENTRY *Entry,\r
503 IN VOID *Context\r
1f7eb561 504 )\r
216f7970 505{\r
506 IP4_PROTOCOL *IpInstance;\r
507 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
508 UINTN NumberOfChildren;\r
509 EFI_HANDLE *ChildHandleBuffer;\r
510\r
511 if (Entry == NULL || Context == NULL) {\r
512 return EFI_INVALID_PARAMETER;\r
513 }\r
514\r
515 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
516 ServiceBinding = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
517 NumberOfChildren = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
518 ChildHandleBuffer = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
519\r
520 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
521 return EFI_SUCCESS;\r
522 }\r
523\r
524 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
525}\r
772db4bb 526\r
527/**\r
5405e9a6 528 Start this driver on ControllerHandle. This service is called by the\r
529 EFI boot service ConnectController(). In order to make\r
530 drivers as small as possible, there are a few calling restrictions for\r
531 this service. ConnectController() must follow these\r
532 calling restrictions. If any other agent wishes to call Start() it\r
533 must also follow these calling restrictions.\r
534\r
3e8c18da 535 @param[in] This Protocol instance pointer.\r
536 @param[in] ControllerHandle Handle of device to bind driver to\r
537 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
538 device to start.\r
5405e9a6 539\r
540 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
541 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
542 @retval other This driver does not support this device\r
772db4bb 543\r
544**/\r
545EFI_STATUS\r
546EFIAPI\r
547Ip4DriverBindingStart (\r
1f6729ff 548 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
772db4bb 549 IN EFI_HANDLE ControllerHandle,\r
1f6729ff 550 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
772db4bb 551 )\r
d1102dba 552{\r
1f6729ff 553 EFI_STATUS Status;\r
554 IP4_SERVICE *IpSb;\r
7648748e
JW
555 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;\r
556 UINTN Index;\r
557 IP4_CONFIG2_DATA_ITEM *DataItem;\r
558\r
559 IpSb = NULL;\r
560 Ip4Cfg2 = NULL;\r
561 DataItem = NULL;\r
772db4bb 562\r
563 //\r
564 // Test for the Ip4 service binding protocol\r
565 //\r
566 Status = gBS->OpenProtocol (\r
567 ControllerHandle,\r
568 &gEfiIp4ServiceBindingProtocolGuid,\r
569 NULL,\r
570 This->DriverBindingHandle,\r
571 ControllerHandle,\r
572 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
573 );\r
574\r
575 if (Status == EFI_SUCCESS) {\r
576 return EFI_ALREADY_STARTED;\r
577 }\r
d1102dba 578\r
772db4bb 579 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
d1102dba 580\r
772db4bb 581 if (EFI_ERROR (Status)) {\r
582 return Status;\r
583 }\r
d1102dba 584\r
e2851998 585 ASSERT (IpSb != NULL);\r
772db4bb 586\r
7648748e
JW
587 Ip4Cfg2 = &IpSb->Ip4Config2Instance.Ip4Config2;\r
588\r
772db4bb 589 //\r
590 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
591 //\r
592 Status = gBS->InstallMultipleProtocolInterfaces (\r
593 &ControllerHandle,\r
594 &gEfiIp4ServiceBindingProtocolGuid,\r
595 &IpSb->ServiceBinding,\r
1f6729ff 596 &gEfiIp4Config2ProtocolGuid,\r
7648748e 597 Ip4Cfg2,\r
772db4bb 598 NULL\r
599 );\r
600\r
601 if (EFI_ERROR (Status)) {\r
602 goto FREE_SERVICE;\r
603 }\r
7648748e
JW
604\r
605 //\r
d1102dba 606 // Read the config data from NV variable again.\r
7648748e
JW
607 // The default data can be changed by other drivers.\r
608 //\r
609 Status = Ip4Config2ReadConfigData (IpSb->MacString, &IpSb->Ip4Config2Instance);\r
610 if (EFI_ERROR (Status)) {\r
611 goto UNINSTALL_PROTOCOL;\r
612 }\r
d1102dba 613\r
7648748e 614 //\r
d1102dba 615 // Consume the installed EFI_IP4_CONFIG2_PROTOCOL to set the default data items.\r
7648748e
JW
616 //\r
617 for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
618 DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
619 if (DataItem->Data.Ptr != NULL) {\r
620 Status = Ip4Cfg2->SetData (\r
621 Ip4Cfg2,\r
622 Index,\r
623 DataItem->DataSize,\r
624 DataItem->Data.Ptr\r
625 );\r
626 if (EFI_ERROR(Status)) {\r
627 goto UNINSTALL_PROTOCOL;\r
628 }\r
d1102dba 629\r
eab40164
JW
630 if (Index == Ip4Config2DataTypePolicy && (*(DataItem->Data.Policy) == Ip4Config2PolicyDhcp)) {\r
631 break;\r
d1102dba 632 }\r
7648748e
JW
633 }\r
634 }\r
d1102dba 635\r
772db4bb 636 //\r
1f6729ff 637 // Ready to go: start the receiving and timer.\r
638 // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
639 // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
772db4bb 640 //\r
641 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
642\r
1f6729ff 643 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
772db4bb 644 goto UNINSTALL_PROTOCOL;\r
645 }\r
646\r
647 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
648\r
649 if (EFI_ERROR (Status)) {\r
650 goto UNINSTALL_PROTOCOL;\r
651 }\r
652\r
018432f0
WF
653 Status = gBS->SetTimer (IpSb->ReconfigCheckTimer, TimerPeriodic, 500 * TICKS_PER_MS);\r
654\r
655 if (EFI_ERROR (Status)) {\r
656 goto UNINSTALL_PROTOCOL;\r
657 }\r
658\r
772db4bb 659 //\r
660 // Initialize the IP4 ID\r
661 //\r
662 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
663\r
772db4bb 664 return Status;\r
665\r
666UNINSTALL_PROTOCOL:\r
667 gBS->UninstallProtocolInterface (\r
668 ControllerHandle,\r
669 &gEfiIp4ServiceBindingProtocolGuid,\r
670 &IpSb->ServiceBinding\r
671 );\r
672\r
673FREE_SERVICE:\r
674 Ip4CleanService (IpSb);\r
766c7483 675 FreePool (IpSb);\r
772db4bb 676 return Status;\r
677}\r
678\r
679\r
680/**\r
5405e9a6 681 Stop this driver on ControllerHandle. This service is called by the\r
682 EFI boot service DisconnectController(). In order to\r
683 make drivers as small as possible, there are a few calling\r
684 restrictions for this service. DisconnectController()\r
685 must follow these calling restrictions. If any other agent wishes\r
686 to call Stop() it must also follow these calling restrictions.\r
e2851998 687\r
3e8c18da 688 @param[in] This Protocol instance pointer.\r
689 @param[in] ControllerHandle Handle of device to stop driver on\r
690 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
691 of children is zero stop the entire bus driver.\r
692 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
5405e9a6 693\r
3e8c18da 694 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
695 @retval other This driver was not removed from this device\r
772db4bb 696\r
697**/\r
698EFI_STATUS\r
699EFIAPI\r
700Ip4DriverBindingStop (\r
701 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
702 IN EFI_HANDLE ControllerHandle,\r
703 IN UINTN NumberOfChildren,\r
704 IN EFI_HANDLE *ChildHandleBuffer\r
705 )\r
706{\r
216f7970 707 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
d1102dba 708 IP4_SERVICE *IpSb;\r
216f7970 709 EFI_HANDLE NicHandle;\r
d1102dba 710 EFI_STATUS Status;\r
216f7970 711 INTN State;\r
712 LIST_ENTRY *List;\r
713 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
d0ccf55e 714 IP4_INTERFACE *IpIf;\r
715 IP4_ROUTE_TABLE *RouteTable;\r
772db4bb 716\r
1f6729ff 717 BOOLEAN IsDhcp4;\r
772db4bb 718\r
1f6729ff 719 IsDhcp4 = FALSE;\r
d1102dba 720\r
772db4bb 721 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
772db4bb 722 if (NicHandle == NULL) {\r
723 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
216f7970 724 if (NicHandle == NULL) {\r
1f6729ff 725 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
726 if (NicHandle != NULL) {\r
d1102dba 727 IsDhcp4 = TRUE;\r
1f6729ff 728 } else {\r
729 return EFI_SUCCESS;\r
730 }\r
216f7970 731 }\r
772db4bb 732 }\r
d1102dba 733\r
772db4bb 734 Status = gBS->OpenProtocol (\r
735 NicHandle,\r
736 &gEfiIp4ServiceBindingProtocolGuid,\r
737 (VOID **) &ServiceBinding,\r
738 This->DriverBindingHandle,\r
739 NicHandle,\r
740 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
741 );\r
772db4bb 742 if (EFI_ERROR (Status)) {\r
743 return EFI_DEVICE_ERROR;\r
744 }\r
d1102dba 745\r
1f6729ff 746 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
772db4bb 747\r
1f6729ff 748 if (IsDhcp4) {\r
749 Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
750 gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
751 IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
752 } else if (NumberOfChildren != 0) {\r
216f7970 753 List = &IpSb->Children;\r
754 Context.ServiceBinding = ServiceBinding;\r
755 Context.NumberOfChildren = NumberOfChildren;\r
756 Context.ChildHandleBuffer = ChildHandleBuffer;\r
757 Status = NetDestroyLinkList (\r
758 List,\r
759 Ip4DestroyChildEntryInHandleBuffer,\r
760 &Context,\r
761 NULL\r
762 );\r
d0ccf55e 763 } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
d1102dba 764\r
d0ccf55e 765 //\r
766 // The ARP protocol for the default interface is being uninstalled and all\r
767 // its IP child handles should have been destroyed before. So, release the\r
768 // default interface and route table, create a new one and mark it as not started.\r
769 //\r
770 Ip4CancelReceive (IpSb->DefaultInterface);\r
771 Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
772 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
d1102dba 773\r
d0ccf55e 774 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
775 if (IpIf == NULL) {\r
776 goto ON_ERROR;\r
777 }\r
778 RouteTable = Ip4CreateRouteTable ();\r
779 if (RouteTable == NULL) {\r
780 Ip4FreeInterface (IpIf, NULL);\r
781 goto ON_ERROR;;\r
782 }\r
d1102dba 783\r
d0ccf55e 784 IpSb->DefaultInterface = IpIf;\r
785 InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
786 IpSb->DefaultRouteTable = RouteTable;\r
787 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
788\r
d0ccf55e 789 IpSb->State = IP4_SERVICE_UNSTARTED;\r
1f6729ff 790\r
216f7970 791 } else if (IsListEmpty (&IpSb->Children)) {\r
c4a62a12 792 State = IpSb->State;\r
c4a62a12 793 //\r
794 // OK, clean other resources then uninstall the service binding protocol.\r
795 //\r
796 Status = Ip4CleanService (IpSb);\r
c4a62a12 797 if (EFI_ERROR (Status)) {\r
798 IpSb->State = State;\r
799 goto ON_ERROR;\r
800 }\r
772db4bb 801\r
1f6729ff 802 gBS->UninstallMultipleProtocolInterfaces (\r
c4a62a12 803 NicHandle,\r
804 &gEfiIp4ServiceBindingProtocolGuid,\r
1f6729ff 805 ServiceBinding,\r
806 &gEfiIp4Config2ProtocolGuid,\r
807 &IpSb->Ip4Config2Instance.Ip4Config2,\r
808 NULL\r
c4a62a12 809 );\r
d1102dba 810\r
216f7970 811 if (gIp4ControllerNameTable != NULL) {\r
812 FreeUnicodeStringTable (gIp4ControllerNameTable);\r
813 gIp4ControllerNameTable = NULL;\r
c4a62a12 814 }\r
766c7483 815 FreePool (IpSb);\r
c4a62a12 816 }\r
772db4bb 817\r
818ON_ERROR:\r
772db4bb 819 return Status;\r
820}\r
821\r
822\r
823/**\r
3e8c18da 824 Creates a child handle and installs a protocol.\r
e2851998 825\r
826 The CreateChild() function installs a protocol on ChildHandle.\r
827 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
3e8c18da 828 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
772db4bb 829\r
3e8c18da 830 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
831 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
e2851998 832 then a new handle is created. If it is a pointer to an existing UEFI handle,\r
3e8c18da 833 then the protocol is added to the existing UEFI handle.\r
772db4bb 834\r
3e8c18da 835 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
5405e9a6 836 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
2048c585 837 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
5405e9a6 838 the child\r
839 @retval other The child handle was not created\r
772db4bb 840\r
841**/\r
842EFI_STATUS\r
843EFIAPI\r
844Ip4ServiceBindingCreateChild (\r
845 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
5405e9a6 846 IN OUT EFI_HANDLE *ChildHandle\r
772db4bb 847 )\r
848{\r
849 IP4_SERVICE *IpSb;\r
850 IP4_PROTOCOL *IpInstance;\r
851 EFI_TPL OldTpl;\r
852 EFI_STATUS Status;\r
853 VOID *Mnp;\r
854\r
855 if ((This == NULL) || (ChildHandle == NULL)) {\r
856 return EFI_INVALID_PARAMETER;\r
857 }\r
858\r
859 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 860 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 861\r
862 if (IpInstance == NULL) {\r
863 return EFI_OUT_OF_RESOURCES;\r
864 }\r
865\r
866 Ip4InitProtocol (IpSb, IpInstance);\r
867\r
868 //\r
869 // Install Ip4 onto ChildHandle\r
870 //\r
871 Status = gBS->InstallMultipleProtocolInterfaces (\r
872 ChildHandle,\r
873 &gEfiIp4ProtocolGuid,\r
874 &IpInstance->Ip4Proto,\r
875 NULL\r
876 );\r
877\r
878 if (EFI_ERROR (Status)) {\r
879 goto ON_ERROR;\r
880 }\r
881\r
882 IpInstance->Handle = *ChildHandle;\r
883\r
884 //\r
885 // Open the Managed Network protocol BY_CHILD.\r
886 //\r
887 Status = gBS->OpenProtocol (\r
888 IpSb->MnpChildHandle,\r
889 &gEfiManagedNetworkProtocolGuid,\r
890 (VOID **) &Mnp,\r
891 gIp4DriverBinding.DriverBindingHandle,\r
892 IpInstance->Handle,\r
893 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
894 );\r
895 if (EFI_ERROR (Status)) {\r
896 gBS->UninstallMultipleProtocolInterfaces (\r
897 ChildHandle,\r
898 &gEfiIp4ProtocolGuid,\r
899 &IpInstance->Ip4Proto,\r
900 NULL\r
901 );\r
902\r
903 goto ON_ERROR;\r
904 }\r
905\r
906 //\r
907 // Insert it into the service binding instance.\r
908 //\r
e48e37fc 909 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 910\r
e48e37fc 911 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 912 IpSb->NumChildren++;\r
913\r
e48e37fc 914 gBS->RestoreTPL (OldTpl);\r
772db4bb 915\r
916ON_ERROR:\r
917\r
918 if (EFI_ERROR (Status)) {\r
919\r
920 Ip4CleanProtocol (IpInstance);\r
921\r
766c7483 922 FreePool (IpInstance);\r
772db4bb 923 }\r
924\r
925 return Status;\r
926}\r
927\r
928\r
929/**\r
3e8c18da 930 Destroys a child handle with a protocol installed on it.\r
e2851998 931\r
932 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
933 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
3e8c18da 934 last protocol on ChildHandle, then ChildHandle is destroyed.\r
772db4bb 935\r
3e8c18da 936 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
5405e9a6 937 @param ChildHandle Handle of the child to destroy\r
938\r
3e8c18da 939 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
940 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
284ee2e8 941 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
3e8c18da 942 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
943 because its services are being used.\r
5405e9a6 944 @retval other The child handle was not destroyed\r
772db4bb 945\r
946**/\r
947EFI_STATUS\r
948EFIAPI\r
949Ip4ServiceBindingDestroyChild (\r
950 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
951 IN EFI_HANDLE ChildHandle\r
952 )\r
953{\r
954 EFI_STATUS Status;\r
955 IP4_SERVICE *IpSb;\r
956 IP4_PROTOCOL *IpInstance;\r
957 EFI_IP4_PROTOCOL *Ip4;\r
958 EFI_TPL OldTpl;\r
772db4bb 959\r
960 if ((This == NULL) || (ChildHandle == NULL)) {\r
961 return EFI_INVALID_PARAMETER;\r
962 }\r
963\r
964 //\r
965 // Retrieve the private context data structures\r
966 //\r
967 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
968\r
969 Status = gBS->OpenProtocol (\r
970 ChildHandle,\r
971 &gEfiIp4ProtocolGuid,\r
972 (VOID **) &Ip4,\r
973 gIp4DriverBinding.DriverBindingHandle,\r
974 ChildHandle,\r
975 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
976 );\r
977\r
978 if (EFI_ERROR (Status)) {\r
979 return EFI_UNSUPPORTED;\r
980 }\r
981\r
982 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
983\r
984 if (IpInstance->Service != IpSb) {\r
985 return EFI_INVALID_PARAMETER;\r
986 }\r
987\r
e48e37fc 988 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 989\r
990 //\r
75dce340 991 // A child can be destroyed more than once. For example,\r
992 // Ip4DriverBindingStop will destroy all of its children.\r
993 // when UDP driver is being stopped, it will destroy all\r
772db4bb 994 // the IP child it opens.\r
995 //\r
4bb89650 996 if (IpInstance->InDestroy) {\r
e48e37fc 997 gBS->RestoreTPL (OldTpl);\r
772db4bb 998 return EFI_SUCCESS;\r
999 }\r
1000\r
4bb89650 1001 IpInstance->InDestroy = TRUE;\r
772db4bb 1002\r
1003 //\r
1004 // Close the Managed Network protocol.\r
1005 //\r
1006 gBS->CloseProtocol (\r
1007 IpSb->MnpChildHandle,\r
1008 &gEfiManagedNetworkProtocolGuid,\r
1009 gIp4DriverBinding.DriverBindingHandle,\r
1010 ChildHandle\r
1011 );\r
1012\r
216f7970 1013 if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {\r
1014 gBS->CloseProtocol (\r
1015 IpInstance->Interface->ArpHandle,\r
1016 &gEfiArpProtocolGuid,\r
1017 gIp4DriverBinding.DriverBindingHandle,\r
1018 ChildHandle\r
1019 );\r
1020 }\r
1021\r
772db4bb 1022 //\r
1023 // Uninstall the IP4 protocol first. Many thing happens during\r
1024 // this:\r
1025 // 1. The consumer of the IP4 protocol will be stopped if it\r
1026 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
1027 // stopped, IP driver's stop function will be called, and uninstall\r
1028 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
1029 // makes it possible to create the network stack bottom up, and\r
1030 // stop it top down.\r
1031 // 2. the upper layer will recycle the received packet. The recycle\r
1032 // event's TPL is higher than this function. The recycle events\r
1033 // will be called back before preceeding. If any packets not recycled,\r
1034 // that means there is a resource leak.\r
1035 //\r
216f7970 1036 gBS->RestoreTPL (OldTpl);\r
772db4bb 1037 Status = gBS->UninstallProtocolInterface (\r
1038 ChildHandle,\r
1039 &gEfiIp4ProtocolGuid,\r
1040 &IpInstance->Ip4Proto\r
1041 );\r
216f7970 1042 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1043 if (EFI_ERROR (Status)) {\r
4bb89650 1044 IpInstance->InDestroy = FALSE;\r
772db4bb 1045 goto ON_ERROR;\r
1046 }\r
1047\r
1048 Status = Ip4CleanProtocol (IpInstance);\r
772db4bb 1049 if (EFI_ERROR (Status)) {\r
1050 gBS->InstallMultipleProtocolInterfaces (\r
1051 &ChildHandle,\r
1052 &gEfiIp4ProtocolGuid,\r
1053 Ip4,\r
1054 NULL\r
1055 );\r
1056\r
1057 goto ON_ERROR;\r
1058 }\r
1059\r
e48e37fc 1060 RemoveEntryList (&IpInstance->Link);\r
772db4bb 1061 IpSb->NumChildren--;\r
1062\r
e48e37fc 1063 gBS->RestoreTPL (OldTpl);\r
772db4bb 1064\r
766c7483 1065 FreePool (IpInstance);\r
772db4bb 1066 return EFI_SUCCESS;\r
1067\r
1068ON_ERROR:\r
e48e37fc 1069 gBS->RestoreTPL (OldTpl);\r
772db4bb 1070\r
1071 return Status;\r
1072}\r