]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Code clean up in NetLib:
[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
3 \r
a1503a32 4Copyright (c) 2005 - 2009, Intel Corporation.<BR>\r
772db4bb 5All rights reserved. This program and the accompanying materials\r
6are licensed and made available under the terms and conditions of the BSD License\r
7which accompanies this distribution. The full text of the license may be found at\r
8http://opensource.org/licenses/bsd-license.php\r
9\r
10THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
11WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
12\r
772db4bb 13**/\r
14\r
15#include "Ip4Impl.h"\r
16\r
17EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
18 Ip4DriverBindingSupported,\r
19 Ip4DriverBindingStart,\r
20 Ip4DriverBindingStop,\r
21 0xa,\r
22 NULL,\r
23 NULL\r
24};\r
25\r
5405e9a6 26/**\r
27 This is the declaration of an EFI image entry point. This entry point is\r
28 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
29 both device drivers and bus drivers.\r
30 \r
31 The entry point for IP4 driver which install the driver\r
32 binding and component name protocol on its image.\r
33\r
3e8c18da 34 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
35 @param[in] SystemTable A pointer to the EFI System Table.\r
5405e9a6 36\r
37 @retval EFI_SUCCESS The operation completed successfully.\r
38 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
39\r
40**/\r
772db4bb 41EFI_STATUS\r
42EFIAPI\r
43Ip4DriverEntryPoint (\r
44 IN EFI_HANDLE ImageHandle,\r
45 IN EFI_SYSTEM_TABLE *SystemTable\r
46 )\r
772db4bb 47{\r
83cbd279 48 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 49 ImageHandle,\r
50 SystemTable,\r
51 &gIp4DriverBinding,\r
52 ImageHandle,\r
53 &gIp4ComponentName,\r
83cbd279 54 &gIp4ComponentName2\r
772db4bb 55 );\r
56}\r
57\r
772db4bb 58/**\r
5405e9a6 59 Test to see if this driver supports ControllerHandle. This service\r
60 is called by the EFI boot service ConnectController(). In\r
61 order to make drivers as small as possible, there are a few calling\r
62 restrictions for this service. ConnectController() must\r
63 follow these calling restrictions. If any other agent wishes to call\r
64 Supported() it must also follow these calling restrictions.\r
65\r
3e8c18da 66 @param[in] This Protocol instance pointer.\r
67 @param[in] ControllerHandle Handle of device to test\r
68 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
69 device to start.\r
5405e9a6 70\r
71 @retval EFI_SUCCESS This driver supports this device\r
72 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
73 @retval other This driver does not support this device\r
772db4bb 74\r
75**/\r
76EFI_STATUS\r
77EFIAPI\r
78Ip4DriverBindingSupported (\r
79 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
80 IN EFI_HANDLE ControllerHandle,\r
81 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
82 )\r
83{\r
84 EFI_STATUS Status;\r
85\r
86 //\r
87 // Test for the MNP service binding Protocol\r
88 //\r
89 Status = gBS->OpenProtocol (\r
90 ControllerHandle,\r
91 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
92 NULL,\r
93 This->DriverBindingHandle,\r
94 ControllerHandle,\r
95 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
96 );\r
97\r
98 if (EFI_ERROR (Status)) {\r
99 return Status;\r
100 }\r
101\r
102 //\r
103 // Test for the Arp service binding Protocol\r
104 //\r
105 Status = gBS->OpenProtocol (\r
106 ControllerHandle,\r
107 &gEfiArpServiceBindingProtocolGuid,\r
108 NULL,\r
109 This->DriverBindingHandle,\r
110 ControllerHandle,\r
111 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
112 );\r
113\r
114 return Status;\r
115}\r
116\r
2ff29212 117/**\r
118 Clean up a IP4 service binding instance. It will release all\r
119 the resource allocated by the instance. The instance may be\r
120 partly initialized, or partly destroyed. If a resource is\r
121 destroyed, it is marked as that in case the destory failed and\r
122 being called again later.\r
123\r
3e8c18da 124 @param[in] IpSb The IP4 serviceing binding instance to clean up\r
2ff29212 125\r
126 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
127 @retval other Failed to clean up some of the resources.\r
128\r
129**/\r
772db4bb 130EFI_STATUS\r
131Ip4CleanService (\r
132 IN IP4_SERVICE *IpSb\r
133 );\r
134\r
135\r
136/**\r
5405e9a6 137 Create a new IP4 driver service binding private instance.\r
772db4bb 138\r
3e8c18da 139 @param Controller The controller that has MNP service binding\r
140 installed\r
141 @param ImageHandle The IP4 driver's image handle\r
142 @param Service The variable to receive the newly created IP4\r
143 service.\r
772db4bb 144\r
145 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource\r
146 @retval EFI_SUCCESS A new IP4 service binding private is created.\r
5405e9a6 147 @retval other Other error occurs.\r
772db4bb 148\r
149**/\r
772db4bb 150EFI_STATUS\r
151Ip4CreateService (\r
152 IN EFI_HANDLE Controller,\r
153 IN EFI_HANDLE ImageHandle,\r
154 OUT IP4_SERVICE **Service\r
155 )\r
156{\r
157 IP4_SERVICE *IpSb;\r
158 EFI_STATUS Status;\r
159\r
160 ASSERT (Service != NULL);\r
161\r
162 *Service = NULL;\r
163\r
164 //\r
165 // allocate a service private data then initialize all the filed to\r
166 // empty resources, so if any thing goes wrong when allocating\r
167 // resources, Ip4CleanService can be called to clean it up.\r
168 //\r
e48e37fc 169 IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
772db4bb 170\r
171 if (IpSb == NULL) {\r
172 return EFI_OUT_OF_RESOURCES;\r
173 }\r
174\r
175 IpSb->Signature = IP4_SERVICE_SIGNATURE;\r
176 IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;\r
177 IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
178 IpSb->State = IP4_SERVICE_UNSTARTED;\r
179 IpSb->InDestory = FALSE;\r
180\r
181 IpSb->NumChildren = 0;\r
e48e37fc 182 InitializeListHead (&IpSb->Children);\r
772db4bb 183\r
e48e37fc 184 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 185 IpSb->DefaultInterface = NULL;\r
186 IpSb->DefaultRouteTable = NULL;\r
187\r
188 Ip4InitAssembleTable (&IpSb->Assemble);\r
189\r
190 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
e48e37fc 191 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 192\r
193 IpSb->Image = ImageHandle;\r
194 IpSb->Controller = Controller;\r
195\r
196 IpSb->MnpChildHandle = NULL;\r
197 IpSb->Mnp = NULL;\r
198\r
199 IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
200 IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
201 IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
202 IpSb->MnpConfigData.EnableUnicastReceive = TRUE;\r
203 IpSb->MnpConfigData.EnableMulticastReceive = TRUE;\r
204 IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;\r
205 IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
206 IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;\r
207 IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
208 IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;\r
209\r
e48e37fc 210 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
772db4bb 211\r
212 IpSb->Timer = NULL;\r
213 IpSb->Ip4Config = NULL;\r
214 IpSb->DoneEvent = NULL;\r
215 IpSb->ReconfigEvent = NULL;\r
36ee91ca 216 IpSb->ActiveEvent = NULL;\r
772db4bb 217\r
218 //\r
219 // Create various resources. First create the route table, timer\r
220 // event and MNP child. IGMP, interface's initialization depend\r
221 // on the MNP child.\r
222 //\r
223 IpSb->DefaultRouteTable = Ip4CreateRouteTable ();\r
224\r
225 if (IpSb->DefaultRouteTable == NULL) {\r
226 Status = EFI_OUT_OF_RESOURCES;\r
227 goto ON_ERROR;\r
228 }\r
229\r
230 Status = gBS->CreateEvent (\r
231 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 232 TPL_CALLBACK,\r
772db4bb 233 Ip4TimerTicking,\r
234 IpSb,\r
235 &IpSb->Timer\r
236 );\r
237\r
238 if (EFI_ERROR (Status)) {\r
239 goto ON_ERROR;\r
240 }\r
241\r
242 Status = NetLibCreateServiceChild (\r
243 Controller,\r
244 ImageHandle,\r
245 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
246 &IpSb->MnpChildHandle\r
247 );\r
248\r
249 if (EFI_ERROR (Status)) {\r
250 goto ON_ERROR;\r
251 }\r
252\r
253 Status = gBS->OpenProtocol (\r
254 IpSb->MnpChildHandle,\r
255 &gEfiManagedNetworkProtocolGuid,\r
256 (VOID **) &IpSb->Mnp,\r
257 ImageHandle,\r
258 Controller,\r
259 EFI_OPEN_PROTOCOL_BY_DRIVER\r
260 );\r
261\r
262 if (EFI_ERROR (Status)) {\r
263 goto ON_ERROR;\r
264 }\r
265\r
266 Status = Ip4ServiceConfigMnp (IpSb, TRUE);\r
267\r
268 if (EFI_ERROR (Status)) {\r
269 goto ON_ERROR;\r
270 }\r
271\r
272 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
273\r
274 if (EFI_ERROR (Status)) {\r
275 goto ON_ERROR;\r
276 }\r
277\r
278 Status = Ip4InitIgmp (IpSb);\r
279\r
280 if (EFI_ERROR (Status)) {\r
281 goto ON_ERROR;\r
282 }\r
283\r
284 IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
285\r
286 if (IpSb->DefaultInterface == NULL) {\r
287 Status = EFI_OUT_OF_RESOURCES;\r
288 goto ON_ERROR;\r
289 }\r
290\r
e48e37fc 291 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
772db4bb 292\r
a1503a32 293 IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
772db4bb 294 IpSb->MacString = NULL;\r
295\r
296 *Service = IpSb;\r
297 return EFI_SUCCESS;\r
298\r
299ON_ERROR:\r
300 Ip4CleanService (IpSb);\r
766c7483 301 FreePool (IpSb);\r
772db4bb 302\r
303 return Status;\r
304}\r
305\r
306\r
307/**\r
308 Clean up a IP4 service binding instance. It will release all\r
309 the resource allocated by the instance. The instance may be\r
5405e9a6 310 partly initialized, or partly destroyed. If a resource is\r
311 destroyed, it is marked as that in case the destory failed and\r
772db4bb 312 being called again later.\r
313\r
3e8c18da 314 @param[in] IpSb The IP4 serviceing binding instance to clean up\r
772db4bb 315\r
316 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
5405e9a6 317 @retval other Failed to clean up some of the resources.\r
772db4bb 318\r
319**/\r
320EFI_STATUS\r
321Ip4CleanService (\r
322 IN IP4_SERVICE *IpSb\r
323 )\r
324{\r
325 EFI_STATUS Status;\r
326\r
327 if (IpSb->DefaultInterface != NULL) {\r
328 Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
329\r
330 if (EFI_ERROR (Status)) {\r
331 return Status;\r
332 }\r
333\r
334 IpSb->DefaultInterface = NULL;\r
335 }\r
336\r
337 if (IpSb->DefaultRouteTable != NULL) {\r
338 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
339 IpSb->DefaultRouteTable = NULL;\r
340 }\r
341\r
342 Ip4CleanAssembleTable (&IpSb->Assemble);\r
343\r
344 if (IpSb->MnpChildHandle != NULL) {\r
5405e9a6 345 if (IpSb->Mnp != NULL) {\r
772db4bb 346 gBS->CloseProtocol (\r
5405e9a6 347 IpSb->MnpChildHandle,\r
348 &gEfiManagedNetworkProtocolGuid,\r
349 IpSb->Image,\r
350 IpSb->Controller\r
351 );\r
772db4bb 352\r
353 IpSb->Mnp = NULL;\r
354 }\r
355\r
356 NetLibDestroyServiceChild (\r
357 IpSb->Controller,\r
358 IpSb->Image,\r
359 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
360 IpSb->MnpChildHandle\r
361 );\r
362\r
363 IpSb->MnpChildHandle = NULL;\r
364 }\r
365\r
366 if (IpSb->Timer != NULL) {\r
367 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
368 gBS->CloseEvent (IpSb->Timer);\r
369\r
370 IpSb->Timer = NULL;\r
371 }\r
372\r
373 if (IpSb->Ip4Config != NULL) {\r
374 IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
375\r
376 gBS->CloseProtocol (\r
377 IpSb->Controller,\r
378 &gEfiIp4ConfigProtocolGuid,\r
379 IpSb->Image,\r
380 IpSb->Controller\r
381 );\r
382\r
383 gBS->CloseEvent (IpSb->DoneEvent);\r
384 gBS->CloseEvent (IpSb->ReconfigEvent);\r
36ee91ca 385 IpSb->ActiveEvent = NULL;\r
772db4bb 386 IpSb->Ip4Config = NULL;\r
387 }\r
388\r
389 return EFI_SUCCESS;\r
390}\r
391\r
392\r
393/**\r
5405e9a6 394 Start this driver on ControllerHandle. This service is called by the\r
395 EFI boot service ConnectController(). In order to make\r
396 drivers as small as possible, there are a few calling restrictions for\r
397 this service. ConnectController() must follow these\r
398 calling restrictions. If any other agent wishes to call Start() it\r
399 must also follow these calling restrictions.\r
400\r
3e8c18da 401 @param[in] This Protocol instance pointer.\r
402 @param[in] ControllerHandle Handle of device to bind driver to\r
403 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
404 device to start.\r
5405e9a6 405\r
406 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
407 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
408 @retval other This driver does not support this device\r
772db4bb 409\r
410**/\r
411EFI_STATUS\r
412EFIAPI\r
413Ip4DriverBindingStart (\r
414 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
415 IN EFI_HANDLE ControllerHandle,\r
416 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
417 )\r
418{\r
419 IP4_SERVICE *IpSb;\r
420 EFI_STATUS Status;\r
421\r
422 //\r
423 // Test for the Ip4 service binding protocol\r
424 //\r
425 Status = gBS->OpenProtocol (\r
426 ControllerHandle,\r
427 &gEfiIp4ServiceBindingProtocolGuid,\r
428 NULL,\r
429 This->DriverBindingHandle,\r
430 ControllerHandle,\r
431 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
432 );\r
433\r
434 if (Status == EFI_SUCCESS) {\r
435 return EFI_ALREADY_STARTED;\r
436 }\r
437\r
438 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
439\r
440 if (EFI_ERROR (Status)) {\r
441 return Status;\r
442 }\r
443\r
444 //\r
445 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
446 //\r
447 Status = gBS->InstallMultipleProtocolInterfaces (\r
448 &ControllerHandle,\r
449 &gEfiIp4ServiceBindingProtocolGuid,\r
450 &IpSb->ServiceBinding,\r
451 NULL\r
452 );\r
453\r
454 if (EFI_ERROR (Status)) {\r
455 goto FREE_SERVICE;\r
456 }\r
457\r
458 //\r
459 // ready to go: start the receiving and timer\r
460 //\r
461 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
462\r
463 if (EFI_ERROR (Status)) {\r
464 goto UNINSTALL_PROTOCOL;\r
465 }\r
466\r
467 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
468\r
469 if (EFI_ERROR (Status)) {\r
470 goto UNINSTALL_PROTOCOL;\r
471 }\r
472\r
473 //\r
474 // Initialize the IP4 ID\r
475 //\r
476 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
477\r
478 Ip4SetVariableData (IpSb);\r
479\r
480 return Status;\r
481\r
482UNINSTALL_PROTOCOL:\r
483 gBS->UninstallProtocolInterface (\r
484 ControllerHandle,\r
485 &gEfiIp4ServiceBindingProtocolGuid,\r
486 &IpSb->ServiceBinding\r
487 );\r
488\r
489FREE_SERVICE:\r
490 Ip4CleanService (IpSb);\r
766c7483 491 FreePool (IpSb);\r
772db4bb 492\r
493 return Status;\r
494}\r
495\r
496\r
497/**\r
5405e9a6 498 Stop this driver on ControllerHandle. This service is called by the\r
499 EFI boot service DisconnectController(). In order to\r
500 make drivers as small as possible, there are a few calling\r
501 restrictions for this service. DisconnectController()\r
502 must follow these calling restrictions. If any other agent wishes\r
503 to call Stop() it must also follow these calling restrictions.\r
504 \r
3e8c18da 505 @param[in] This Protocol instance pointer.\r
506 @param[in] ControllerHandle Handle of device to stop driver on\r
507 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
508 of children is zero stop the entire bus driver.\r
509 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
5405e9a6 510\r
3e8c18da 511 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
512 @retval other This driver was not removed from this device\r
772db4bb 513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517Ip4DriverBindingStop (\r
518 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
519 IN EFI_HANDLE ControllerHandle,\r
520 IN UINTN NumberOfChildren,\r
521 IN EFI_HANDLE *ChildHandleBuffer\r
522 )\r
523{\r
524 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
525 IP4_SERVICE *IpSb;\r
526 IP4_PROTOCOL *IpInstance;\r
527 EFI_HANDLE NicHandle;\r
528 EFI_STATUS Status;\r
529 EFI_TPL OldTpl;\r
530 INTN State;\r
c4a62a12 531 BOOLEAN IsArp;\r
772db4bb 532\r
533 //\r
534 // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol\r
535 // by driver. So the ControllerHandle may be the MNP child handle, ARP child\r
536 // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed\r
537 // in the NIC handle.\r
538 //\r
539 //\r
540 // First, check whether it is the IP4_CONFIG protocol being uninstalled.\r
541 // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary\r
542 // to clean up the default configuration if IP4_CONFIG is being stopped.\r
543 //\r
544 Status = gBS->OpenProtocol (\r
545 ControllerHandle,\r
546 &gEfiIp4ConfigProtocolGuid,\r
547 NULL,\r
548 This->DriverBindingHandle,\r
549 ControllerHandle,\r
550 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
551 );\r
552\r
553 if (Status == EFI_SUCCESS) {\r
554 //\r
555 // Retrieve the IP4 service binding protocol. If failed, it is\r
556 // likely that Ip4 ServiceBinding is uninstalled already. In this\r
557 // case, return immediately.\r
558 //\r
559 Status = gBS->OpenProtocol (\r
560 ControllerHandle,\r
561 &gEfiIp4ServiceBindingProtocolGuid,\r
562 (VOID **) &ServiceBinding,\r
563 This->DriverBindingHandle,\r
564 ControllerHandle,\r
565 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
566 );\r
567\r
568 if (EFI_ERROR (Status)) {\r
c4a62a12 569 return EFI_DEVICE_ERROR;\r
772db4bb 570 }\r
571\r
572 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
573\r
e48e37fc 574 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 575\r
5405e9a6 576 if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTORY)) {\r
772db4bb 577\r
578 IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
579\r
580 Status = gBS->CloseProtocol (\r
581 ControllerHandle,\r
582 &gEfiIp4ConfigProtocolGuid,\r
583 IpSb->Image,\r
584 ControllerHandle\r
585 );\r
586\r
587 if (EFI_ERROR (Status)) {\r
e48e37fc 588 gBS->RestoreTPL (OldTpl);\r
772db4bb 589 return Status;\r
590 }\r
591\r
592 //\r
593 // If the auto configure hasn't complete, mark it as not started.\r
594 //\r
595 if (IpSb->State == IP4_SERVICE_STARTED) {\r
596 IpSb->State = IP4_SERVICE_UNSTARTED;\r
597 }\r
598\r
599 IpSb->Ip4Config = NULL;\r
600 gBS->CloseEvent (IpSb->DoneEvent);\r
601 gBS->CloseEvent (IpSb->ReconfigEvent);\r
602 }\r
603\r
e48e37fc 604 gBS->RestoreTPL (OldTpl);\r
772db4bb 605 return EFI_SUCCESS;\r
606 }\r
607\r
608 //\r
609 // Either MNP or ARP protocol is being uninstalled. The controller\r
610 // handle is either the MNP child or ARP child. But, the IP4's\r
611 // service binding is installed on the NIC handle. So, need to open\r
612 // the protocol info to find the NIC handle.\r
613 //\r
c4a62a12 614 IsArp = FALSE;\r
772db4bb 615 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
616\r
617 if (NicHandle == NULL) {\r
618 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
c4a62a12 619 IsArp = TRUE;\r
772db4bb 620 }\r
621\r
622 if (NicHandle == NULL) {\r
c4a62a12 623 return EFI_DEVICE_ERROR;\r
772db4bb 624 }\r
625\r
626 //\r
627 // Retrieve the IP4 service binding protocol\r
628 //\r
629 Status = gBS->OpenProtocol (\r
630 NicHandle,\r
631 &gEfiIp4ServiceBindingProtocolGuid,\r
632 (VOID **) &ServiceBinding,\r
633 This->DriverBindingHandle,\r
634 NicHandle,\r
635 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
636 );\r
637\r
638 if (EFI_ERROR (Status)) {\r
639 return EFI_DEVICE_ERROR;\r
640 }\r
641\r
642 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
643\r
e48e37fc 644 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 645\r
646 if (IpSb->InDestory) {\r
e48e37fc 647 gBS->RestoreTPL (OldTpl);\r
772db4bb 648 return EFI_SUCCESS;\r
649 }\r
650\r
c4a62a12 651 if (IsArp) {\r
e48e37fc 652 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 653 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
772db4bb 654\r
c4a62a12 655 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
656 }\r
772db4bb 657\r
c4a62a12 658 if (IpSb->NumChildren != 0) {\r
659 Status = EFI_DEVICE_ERROR;\r
660 goto ON_ERROR;\r
661 }\r
772db4bb 662\r
c4a62a12 663 IpSb->InDestory = TRUE;\r
772db4bb 664\r
c4a62a12 665 State = IpSb->State;\r
666 IpSb->State = IP4_SERVICE_DESTORY;\r
772db4bb 667\r
c4a62a12 668 //\r
669 // Clear the variable data.\r
670 //\r
671 Ip4ClearVariableData (IpSb);\r
772db4bb 672\r
c4a62a12 673 //\r
674 // OK, clean other resources then uninstall the service binding protocol.\r
675 //\r
676 Status = Ip4CleanService (IpSb);\r
772db4bb 677\r
c4a62a12 678 if (EFI_ERROR (Status)) {\r
679 IpSb->State = State;\r
680 goto ON_ERROR;\r
681 }\r
772db4bb 682\r
c4a62a12 683 gBS->UninstallProtocolInterface (\r
684 NicHandle,\r
685 &gEfiIp4ServiceBindingProtocolGuid,\r
686 ServiceBinding\r
687 );\r
772db4bb 688\r
766c7483 689 FreePool (IpSb);\r
c4a62a12 690 } else if (NumberOfChildren == 0) {\r
691 IpSb->InDestory = TRUE;\r
692\r
693 State = IpSb->State;\r
694 IpSb->State = IP4_SERVICE_DESTORY;\r
695\r
696 //\r
697 // Clear the variable data.\r
698 //\r
699 Ip4ClearVariableData (IpSb);\r
700\r
701 //\r
702 // OK, clean other resources then uninstall the service binding protocol.\r
703 //\r
704 Status = Ip4CleanService (IpSb);\r
705\r
706 if (EFI_ERROR (Status)) {\r
707 IpSb->State = State;\r
708 goto ON_ERROR;\r
709 }\r
710\r
711 gBS->UninstallProtocolInterface (\r
712 NicHandle,\r
713 &gEfiIp4ServiceBindingProtocolGuid,\r
714 ServiceBinding\r
715 );\r
716\r
766c7483 717 FreePool (IpSb);\r
c4a62a12 718 } else {\r
719\r
e48e37fc 720 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 721 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
722\r
723 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
724 }\r
725\r
726 if (IpSb->NumChildren != 0) {\r
727 Status = EFI_DEVICE_ERROR;\r
728 }\r
729 }\r
772db4bb 730\r
731ON_ERROR:\r
c4a62a12 732\r
e48e37fc 733 gBS->RestoreTPL (OldTpl);\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
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
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
747 then a new handle is created. If it is a pointer to an existing UEFI handle, \r
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
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
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
856 @retval EFI_INVALID_PARAMETER Child handle is not a valid UEFI Handle.\r
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
907 // A child can be destoried more than once. For example,\r
908 // Ip4DriverBindingStop will destory all of its children.\r
909 // when UDP driver is being stopped, it will destory all\r
910 // the IP child it opens.\r
911 //\r
912 if (IpInstance->State == IP4_STATE_DESTORY) {\r
e48e37fc 913 gBS->RestoreTPL (OldTpl);\r
772db4bb 914 return EFI_SUCCESS;\r
915 }\r
916\r
917 State = IpInstance->State;\r
918 IpInstance->State = IP4_STATE_DESTORY;\r
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
930 //\r
931 // Uninstall the IP4 protocol first. Many thing happens during\r
932 // this:\r
933 // 1. The consumer of the IP4 protocol will be stopped if it\r
934 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
935 // stopped, IP driver's stop function will be called, and uninstall\r
936 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
937 // makes it possible to create the network stack bottom up, and\r
938 // stop it top down.\r
939 // 2. the upper layer will recycle the received packet. The recycle\r
940 // event's TPL is higher than this function. The recycle events\r
941 // will be called back before preceeding. If any packets not recycled,\r
942 // that means there is a resource leak.\r
943 //\r
944 Status = gBS->UninstallProtocolInterface (\r
945 ChildHandle,\r
946 &gEfiIp4ProtocolGuid,\r
947 &IpInstance->Ip4Proto\r
948 );\r
949\r
950 if (EFI_ERROR (Status)) {\r
951 goto ON_ERROR;\r
952 }\r
953\r
954 Status = Ip4CleanProtocol (IpInstance);\r
955\r
956 Ip4SetVariableData (IpSb);\r
957\r
958 if (EFI_ERROR (Status)) {\r
959 gBS->InstallMultipleProtocolInterfaces (\r
960 &ChildHandle,\r
961 &gEfiIp4ProtocolGuid,\r
962 Ip4,\r
963 NULL\r
964 );\r
965\r
966 goto ON_ERROR;\r
967 }\r
968\r
e48e37fc 969 RemoveEntryList (&IpInstance->Link);\r
772db4bb 970 IpSb->NumChildren--;\r
971\r
e48e37fc 972 gBS->RestoreTPL (OldTpl);\r
772db4bb 973\r
766c7483 974 FreePool (IpInstance);\r
772db4bb 975 return EFI_SUCCESS;\r
976\r
977ON_ERROR:\r
978 IpInstance->State = State;\r
e48e37fc 979 gBS->RestoreTPL (OldTpl);\r
772db4bb 980\r
981 return Status;\r
982}\r