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