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