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