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