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