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