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