]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg: Replace BSD License with BSD+Patent License
[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
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
13EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
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
5aae2d35 38 EFI_STATUS Status;\r
c79de074 39 //\r
5aae2d35
FS
40 // Test if protocol was even found.\r
41 // Notification function will be called at least once.\r
c79de074 42 //\r
5f74808d 43 Status = gBS->LocateProtocol (&gEfiIpSec2ProtocolGuid, NULL, (VOID **)&mIpSec);\r
5aae2d35
FS
44 if (Status == EFI_SUCCESS && mIpSec != NULL) {\r
45 //\r
46 // Close the event so it does not get called again.\r
47 //\r
48 gBS->CloseEvent (Event);\r
49\r
50 mIpSec2Installed = TRUE;\r
51 }\r
c79de074
SEHM
52}\r
53\r
5405e9a6 54/**\r
55 This is the declaration of an EFI image entry point. This entry point is\r
56 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
57 both device drivers and bus drivers.\r
e2851998 58\r
5405e9a6 59 The entry point for IP4 driver which install the driver\r
60 binding and component name protocol on its image.\r
61\r
3e8c18da 62 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
63 @param[in] SystemTable A pointer to the EFI System Table.\r
5405e9a6 64\r
65 @retval EFI_SUCCESS The operation completed successfully.\r
66 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
67\r
68**/\r
772db4bb 69EFI_STATUS\r
70EFIAPI\r
71Ip4DriverEntryPoint (\r
72 IN EFI_HANDLE ImageHandle,\r
73 IN EFI_SYSTEM_TABLE *SystemTable\r
74 )\r
772db4bb 75{\r
c79de074
SEHM
76 VOID *Registration;\r
77\r
78 EfiCreateProtocolNotifyEvent (\r
79 &gEfiIpSec2ProtocolGuid,\r
80 TPL_CALLBACK,\r
81 IpSec2InstalledCallback,\r
82 NULL,\r
83 &Registration\r
84 );\r
85\r
83cbd279 86 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 87 ImageHandle,\r
88 SystemTable,\r
89 &gIp4DriverBinding,\r
90 ImageHandle,\r
91 &gIp4ComponentName,\r
83cbd279 92 &gIp4ComponentName2\r
772db4bb 93 );\r
94}\r
95\r
772db4bb 96/**\r
5405e9a6 97 Test to see if this driver supports ControllerHandle. This service\r
98 is called by the EFI boot service ConnectController(). In\r
99 order to make drivers as small as possible, there are a few calling\r
100 restrictions for this service. ConnectController() must\r
101 follow these calling restrictions. If any other agent wishes to call\r
102 Supported() it must also follow these calling restrictions.\r
103\r
3e8c18da 104 @param[in] This Protocol instance pointer.\r
105 @param[in] ControllerHandle Handle of device to test\r
106 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
107 device to start.\r
5405e9a6 108\r
109 @retval EFI_SUCCESS This driver supports this device\r
110 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
111 @retval other This driver does not support this device\r
772db4bb 112\r
113**/\r
114EFI_STATUS\r
115EFIAPI\r
116Ip4DriverBindingSupported (\r
117 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
118 IN EFI_HANDLE ControllerHandle,\r
119 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
120 )\r
121{\r
122 EFI_STATUS Status;\r
123\r
124 //\r
125 // Test for the MNP service binding Protocol\r
126 //\r
127 Status = gBS->OpenProtocol (\r
128 ControllerHandle,\r
129 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
130 NULL,\r
131 This->DriverBindingHandle,\r
132 ControllerHandle,\r
133 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
134 );\r
135\r
136 if (EFI_ERROR (Status)) {\r
137 return Status;\r
138 }\r
139\r
140 //\r
141 // Test for the Arp service binding Protocol\r
142 //\r
143 Status = gBS->OpenProtocol (\r
144 ControllerHandle,\r
145 &gEfiArpServiceBindingProtocolGuid,\r
146 NULL,\r
147 This->DriverBindingHandle,\r
148 ControllerHandle,\r
149 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
150 );\r
151\r
152 return Status;\r
153}\r
154\r
2ff29212 155/**\r
156 Clean up a IP4 service binding instance. It will release all\r
157 the resource allocated by the instance. The instance may be\r
158 partly initialized, or partly destroyed. If a resource is\r
75dce340 159 destroyed, it is marked as that in case the destroy failed and\r
2ff29212 160 being called again later.\r
161\r
1f6729ff 162 @param[in] IpSb The IP4 service binding instance to clean up\r
2ff29212 163\r
164 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
165 @retval other Failed to clean up some of the resources.\r
166\r
167**/\r
772db4bb 168EFI_STATUS\r
169Ip4CleanService (\r
170 IN IP4_SERVICE *IpSb\r
171 );\r
172\r
173\r
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
190 IN EFI_HANDLE Controller,\r
191 IN EFI_HANDLE ImageHandle,\r
192 OUT IP4_SERVICE **Service\r
193 )\r
194{\r
195 IP4_SERVICE *IpSb;\r
196 EFI_STATUS Status;\r
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
218 IpSb->NumChildren = 0;\r
e48e37fc 219 InitializeListHead (&IpSb->Children);\r
772db4bb 220\r
e48e37fc 221 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 222 IpSb->DefaultInterface = NULL;\r
223 IpSb->DefaultRouteTable = NULL;\r
224\r
225 Ip4InitAssembleTable (&IpSb->Assemble);\r
226\r
227 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
e48e37fc 228 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 229\r
230 IpSb->Image = ImageHandle;\r
231 IpSb->Controller = Controller;\r
232\r
233 IpSb->MnpChildHandle = NULL;\r
234 IpSb->Mnp = NULL;\r
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
1f6729ff 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
319 (VOID **) &IpSb->Mnp,\r
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
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
9e375eb1 378 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
772db4bb 379 *Service = IpSb;\r
1f6729ff 380\r
772db4bb 381 return EFI_SUCCESS;\r
382\r
383ON_ERROR:\r
384 Ip4CleanService (IpSb);\r
766c7483 385 FreePool (IpSb);\r
772db4bb 386\r
387 return Status;\r
388}\r
389\r
390\r
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
406 IN IP4_SERVICE *IpSb\r
407 )\r
408{\r
409 EFI_STATUS Status;\r
410\r
524813f3
FS
411 IpSb->State = IP4_SERVICE_DESTROY;\r
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
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
505 if (Entry == NULL || Context == NULL) {\r
506 return EFI_INVALID_PARAMETER;\r
507 }\r
508\r
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
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
1f6729ff 547 EFI_STATUS Status;\r
548 IP4_SERVICE *IpSb;\r
7648748e
JW
549 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;\r
550 UINTN Index;\r
551 IP4_CONFIG2_DATA_ITEM *DataItem;\r
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
7648748e
JW
581 Ip4Cfg2 = &IpSb->Ip4Config2Instance.Ip4Config2;\r
582\r
772db4bb 583 //\r
584 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
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
620 if (EFI_ERROR(Status)) {\r
621 goto UNINSTALL_PROTOCOL;\r
622 }\r
d1102dba 623\r
eab40164
JW
624 if (Index == Ip4Config2DataTypePolicy && (*(DataItem->Data.Policy) == Ip4Config2PolicyDhcp)) {\r
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
1f6729ff 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
676\r
677/**\r
5405e9a6 678 Stop this driver on ControllerHandle. This service is called by the\r
679 EFI boot service DisconnectController(). In order to\r
680 make drivers as small as possible, there are a few calling\r
681 restrictions for this service. DisconnectController()\r
682 must follow these calling restrictions. If any other agent wishes\r
683 to call Stop() it must also follow these calling restrictions.\r
e2851998 684\r
3e8c18da 685 @param[in] This Protocol instance pointer.\r
686 @param[in] ControllerHandle Handle of device to stop driver on\r
687 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
688 of children is zero stop the entire bus driver.\r
689 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
5405e9a6 690\r
3e8c18da 691 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
692 @retval other This driver was not removed from this device\r
772db4bb 693\r
694**/\r
695EFI_STATUS\r
696EFIAPI\r
697Ip4DriverBindingStop (\r
698 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
699 IN EFI_HANDLE ControllerHandle,\r
700 IN UINTN NumberOfChildren,\r
701 IN EFI_HANDLE *ChildHandleBuffer\r
702 )\r
703{\r
216f7970 704 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
d1102dba 705 IP4_SERVICE *IpSb;\r
216f7970 706 EFI_HANDLE NicHandle;\r
d1102dba 707 EFI_STATUS Status;\r
216f7970 708 INTN State;\r
709 LIST_ENTRY *List;\r
710 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
d0ccf55e 711 IP4_INTERFACE *IpIf;\r
712 IP4_ROUTE_TABLE *RouteTable;\r
772db4bb 713\r
1f6729ff 714 BOOLEAN IsDhcp4;\r
772db4bb 715\r
1f6729ff 716 IsDhcp4 = FALSE;\r
d1102dba 717\r
772db4bb 718 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
772db4bb 719 if (NicHandle == NULL) {\r
720 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
216f7970 721 if (NicHandle == NULL) {\r
1f6729ff 722 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
723 if (NicHandle != NULL) {\r
d1102dba 724 IsDhcp4 = TRUE;\r
1f6729ff 725 } else {\r
726 return EFI_SUCCESS;\r
727 }\r
216f7970 728 }\r
772db4bb 729 }\r
d1102dba 730\r
772db4bb 731 Status = gBS->OpenProtocol (\r
732 NicHandle,\r
733 &gEfiIp4ServiceBindingProtocolGuid,\r
734 (VOID **) &ServiceBinding,\r
735 This->DriverBindingHandle,\r
736 NicHandle,\r
737 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
738 );\r
772db4bb 739 if (EFI_ERROR (Status)) {\r
740 return EFI_DEVICE_ERROR;\r
741 }\r
d1102dba 742\r
1f6729ff 743 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
772db4bb 744\r
1f6729ff 745 if (IsDhcp4) {\r
746 Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
747 gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
748 IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
749 } else if (NumberOfChildren != 0) {\r
216f7970 750 List = &IpSb->Children;\r
751 Context.ServiceBinding = ServiceBinding;\r
752 Context.NumberOfChildren = NumberOfChildren;\r
753 Context.ChildHandleBuffer = ChildHandleBuffer;\r
754 Status = NetDestroyLinkList (\r
755 List,\r
756 Ip4DestroyChildEntryInHandleBuffer,\r
757 &Context,\r
758 NULL\r
759 );\r
d0ccf55e 760 } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
d1102dba 761\r
d0ccf55e 762 //\r
763 // The ARP protocol for the default interface is being uninstalled and all\r
764 // its IP child handles should have been destroyed before. So, release the\r
765 // default interface and route table, create a new one and mark it as not started.\r
766 //\r
767 Ip4CancelReceive (IpSb->DefaultInterface);\r
768 Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
769 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
d1102dba 770\r
d0ccf55e 771 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
772 if (IpIf == NULL) {\r
773 goto ON_ERROR;\r
774 }\r
775 RouteTable = Ip4CreateRouteTable ();\r
776 if (RouteTable == NULL) {\r
777 Ip4FreeInterface (IpIf, NULL);\r
778 goto ON_ERROR;;\r
779 }\r
d1102dba 780\r
d0ccf55e 781 IpSb->DefaultInterface = IpIf;\r
782 InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
783 IpSb->DefaultRouteTable = RouteTable;\r
784 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
785\r
d0ccf55e 786 IpSb->State = IP4_SERVICE_UNSTARTED;\r
1f6729ff 787\r
216f7970 788 } else if (IsListEmpty (&IpSb->Children)) {\r
c4a62a12 789 State = IpSb->State;\r
c4a62a12 790 //\r
791 // OK, clean other resources then uninstall the service binding protocol.\r
792 //\r
793 Status = Ip4CleanService (IpSb);\r
c4a62a12 794 if (EFI_ERROR (Status)) {\r
795 IpSb->State = State;\r
796 goto ON_ERROR;\r
797 }\r
772db4bb 798\r
1f6729ff 799 gBS->UninstallMultipleProtocolInterfaces (\r
c4a62a12 800 NicHandle,\r
801 &gEfiIp4ServiceBindingProtocolGuid,\r
1f6729ff 802 ServiceBinding,\r
803 &gEfiIp4Config2ProtocolGuid,\r
804 &IpSb->Ip4Config2Instance.Ip4Config2,\r
805 NULL\r
c4a62a12 806 );\r
d1102dba 807\r
216f7970 808 if (gIp4ControllerNameTable != NULL) {\r
809 FreeUnicodeStringTable (gIp4ControllerNameTable);\r
810 gIp4ControllerNameTable = NULL;\r
c4a62a12 811 }\r
766c7483 812 FreePool (IpSb);\r
c4a62a12 813 }\r
772db4bb 814\r
815ON_ERROR:\r
772db4bb 816 return Status;\r
817}\r
818\r
819\r
820/**\r
3e8c18da 821 Creates a child handle and installs a protocol.\r
e2851998 822\r
823 The CreateChild() function installs a protocol on ChildHandle.\r
824 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
3e8c18da 825 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
772db4bb 826\r
3e8c18da 827 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
828 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
e2851998 829 then a new handle is created. If it is a pointer to an existing UEFI handle,\r
3e8c18da 830 then the protocol is added to the existing UEFI handle.\r
772db4bb 831\r
3e8c18da 832 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
5405e9a6 833 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
2048c585 834 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
5405e9a6 835 the child\r
836 @retval other The child handle was not created\r
772db4bb 837\r
838**/\r
839EFI_STATUS\r
840EFIAPI\r
841Ip4ServiceBindingCreateChild (\r
842 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
5405e9a6 843 IN OUT EFI_HANDLE *ChildHandle\r
772db4bb 844 )\r
845{\r
846 IP4_SERVICE *IpSb;\r
847 IP4_PROTOCOL *IpInstance;\r
848 EFI_TPL OldTpl;\r
849 EFI_STATUS Status;\r
850 VOID *Mnp;\r
851\r
852 if ((This == NULL) || (ChildHandle == NULL)) {\r
853 return EFI_INVALID_PARAMETER;\r
854 }\r
855\r
856 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 857 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 858\r
859 if (IpInstance == NULL) {\r
860 return EFI_OUT_OF_RESOURCES;\r
861 }\r
862\r
863 Ip4InitProtocol (IpSb, IpInstance);\r
864\r
865 //\r
866 // Install Ip4 onto ChildHandle\r
867 //\r
868 Status = gBS->InstallMultipleProtocolInterfaces (\r
869 ChildHandle,\r
870 &gEfiIp4ProtocolGuid,\r
871 &IpInstance->Ip4Proto,\r
872 NULL\r
873 );\r
874\r
875 if (EFI_ERROR (Status)) {\r
876 goto ON_ERROR;\r
877 }\r
878\r
879 IpInstance->Handle = *ChildHandle;\r
880\r
881 //\r
882 // Open the Managed Network protocol BY_CHILD.\r
883 //\r
884 Status = gBS->OpenProtocol (\r
885 IpSb->MnpChildHandle,\r
886 &gEfiManagedNetworkProtocolGuid,\r
887 (VOID **) &Mnp,\r
888 gIp4DriverBinding.DriverBindingHandle,\r
889 IpInstance->Handle,\r
890 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
891 );\r
892 if (EFI_ERROR (Status)) {\r
893 gBS->UninstallMultipleProtocolInterfaces (\r
894 ChildHandle,\r
895 &gEfiIp4ProtocolGuid,\r
896 &IpInstance->Ip4Proto,\r
897 NULL\r
898 );\r
899\r
900 goto ON_ERROR;\r
901 }\r
902\r
903 //\r
904 // Insert it into the service binding instance.\r
905 //\r
e48e37fc 906 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 907\r
e48e37fc 908 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 909 IpSb->NumChildren++;\r
910\r
e48e37fc 911 gBS->RestoreTPL (OldTpl);\r
772db4bb 912\r
913ON_ERROR:\r
914\r
915 if (EFI_ERROR (Status)) {\r
916\r
917 Ip4CleanProtocol (IpInstance);\r
918\r
766c7483 919 FreePool (IpInstance);\r
772db4bb 920 }\r
921\r
922 return Status;\r
923}\r
924\r
925\r
926/**\r
3e8c18da 927 Destroys a child handle with a protocol installed on it.\r
e2851998 928\r
929 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
930 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
3e8c18da 931 last protocol on ChildHandle, then ChildHandle is destroyed.\r
772db4bb 932\r
3e8c18da 933 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
5405e9a6 934 @param ChildHandle Handle of the child to destroy\r
935\r
3e8c18da 936 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
937 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
284ee2e8 938 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
3e8c18da 939 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
940 because its services are being used.\r
5405e9a6 941 @retval other The child handle was not destroyed\r
772db4bb 942\r
943**/\r
944EFI_STATUS\r
945EFIAPI\r
946Ip4ServiceBindingDestroyChild (\r
947 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
948 IN EFI_HANDLE ChildHandle\r
949 )\r
950{\r
951 EFI_STATUS Status;\r
952 IP4_SERVICE *IpSb;\r
953 IP4_PROTOCOL *IpInstance;\r
954 EFI_IP4_PROTOCOL *Ip4;\r
955 EFI_TPL OldTpl;\r
772db4bb 956\r
957 if ((This == NULL) || (ChildHandle == NULL)) {\r
958 return EFI_INVALID_PARAMETER;\r
959 }\r
960\r
961 //\r
962 // Retrieve the private context data structures\r
963 //\r
964 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
965\r
966 Status = gBS->OpenProtocol (\r
967 ChildHandle,\r
968 &gEfiIp4ProtocolGuid,\r
969 (VOID **) &Ip4,\r
970 gIp4DriverBinding.DriverBindingHandle,\r
971 ChildHandle,\r
972 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
973 );\r
974\r
975 if (EFI_ERROR (Status)) {\r
976 return EFI_UNSUPPORTED;\r
977 }\r
978\r
979 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
980\r
981 if (IpInstance->Service != IpSb) {\r
982 return EFI_INVALID_PARAMETER;\r
983 }\r
984\r
e48e37fc 985 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 986\r
987 //\r
75dce340 988 // A child can be destroyed more than once. For example,\r
989 // Ip4DriverBindingStop will destroy all of its children.\r
990 // when UDP driver is being stopped, it will destroy all\r
772db4bb 991 // the IP child it opens.\r
992 //\r
4bb89650 993 if (IpInstance->InDestroy) {\r
e48e37fc 994 gBS->RestoreTPL (OldTpl);\r
772db4bb 995 return EFI_SUCCESS;\r
996 }\r
997\r
4bb89650 998 IpInstance->InDestroy = TRUE;\r
772db4bb 999\r
1000 //\r
1001 // Close the Managed Network protocol.\r
1002 //\r
1003 gBS->CloseProtocol (\r
1004 IpSb->MnpChildHandle,\r
1005 &gEfiManagedNetworkProtocolGuid,\r
1006 gIp4DriverBinding.DriverBindingHandle,\r
1007 ChildHandle\r
1008 );\r
1009\r
216f7970 1010 if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {\r
1011 gBS->CloseProtocol (\r
1012 IpInstance->Interface->ArpHandle,\r
1013 &gEfiArpProtocolGuid,\r
1014 gIp4DriverBinding.DriverBindingHandle,\r
1015 ChildHandle\r
1016 );\r
1017 }\r
1018\r
772db4bb 1019 //\r
1020 // Uninstall the IP4 protocol first. Many thing happens during\r
1021 // this:\r
1022 // 1. The consumer of the IP4 protocol will be stopped if it\r
1023 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
1024 // stopped, IP driver's stop function will be called, and uninstall\r
1025 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
1026 // makes it possible to create the network stack bottom up, and\r
1027 // stop it top down.\r
1028 // 2. the upper layer will recycle the received packet. The recycle\r
1029 // event's TPL is higher than this function. The recycle events\r
1030 // will be called back before preceeding. If any packets not recycled,\r
1031 // that means there is a resource leak.\r
1032 //\r
216f7970 1033 gBS->RestoreTPL (OldTpl);\r
772db4bb 1034 Status = gBS->UninstallProtocolInterface (\r
1035 ChildHandle,\r
1036 &gEfiIp4ProtocolGuid,\r
1037 &IpInstance->Ip4Proto\r
1038 );\r
216f7970 1039 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1040 if (EFI_ERROR (Status)) {\r
4bb89650 1041 IpInstance->InDestroy = FALSE;\r
772db4bb 1042 goto ON_ERROR;\r
1043 }\r
1044\r
1045 Status = Ip4CleanProtocol (IpInstance);\r
772db4bb 1046 if (EFI_ERROR (Status)) {\r
1047 gBS->InstallMultipleProtocolInterfaces (\r
1048 &ChildHandle,\r
1049 &gEfiIp4ProtocolGuid,\r
1050 Ip4,\r
1051 NULL\r
1052 );\r
1053\r
1054 goto ON_ERROR;\r
1055 }\r
1056\r
e48e37fc 1057 RemoveEntryList (&IpInstance->Link);\r
772db4bb 1058 IpSb->NumChildren--;\r
1059\r
e48e37fc 1060 gBS->RestoreTPL (OldTpl);\r
772db4bb 1061\r
766c7483 1062 FreePool (IpInstance);\r
772db4bb 1063 return EFI_SUCCESS;\r
1064\r
1065ON_ERROR:\r
e48e37fc 1066 gBS->RestoreTPL (OldTpl);\r
772db4bb 1067\r
1068 return Status;\r
1069}\r