]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Patch to remove STATIC modifier. This is on longer recommended by EFI Framework codin...
[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
772db4bb 124EFI_STATUS\r
125Ip4CleanService (\r
126 IN IP4_SERVICE *IpSb\r
127 );\r
128\r
129\r
130/**\r
131 Create a new IP4 driver service binding protocol\r
132\r
133 @param Controller The controller that has MNP service binding\r
134 installed\r
135 @param ImageHandle The IP4 driver's image handle\r
136 @param Service The variable to receive the newly created IP4\r
137 service.\r
138\r
139 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource\r
140 @retval EFI_SUCCESS A new IP4 service binding private is created.\r
141\r
142**/\r
772db4bb 143EFI_STATUS\r
144Ip4CreateService (\r
145 IN EFI_HANDLE Controller,\r
146 IN EFI_HANDLE ImageHandle,\r
147 OUT IP4_SERVICE **Service\r
148 )\r
149{\r
150 IP4_SERVICE *IpSb;\r
151 EFI_STATUS Status;\r
152\r
153 ASSERT (Service != NULL);\r
154\r
155 *Service = NULL;\r
156\r
157 //\r
158 // allocate a service private data then initialize all the filed to\r
159 // empty resources, so if any thing goes wrong when allocating\r
160 // resources, Ip4CleanService can be called to clean it up.\r
161 //\r
e48e37fc 162 IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
772db4bb 163\r
164 if (IpSb == NULL) {\r
165 return EFI_OUT_OF_RESOURCES;\r
166 }\r
167\r
168 IpSb->Signature = IP4_SERVICE_SIGNATURE;\r
169 IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;\r
170 IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
171 IpSb->State = IP4_SERVICE_UNSTARTED;\r
172 IpSb->InDestory = FALSE;\r
173\r
174 IpSb->NumChildren = 0;\r
e48e37fc 175 InitializeListHead (&IpSb->Children);\r
772db4bb 176\r
e48e37fc 177 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 178 IpSb->DefaultInterface = NULL;\r
179 IpSb->DefaultRouteTable = NULL;\r
180\r
181 Ip4InitAssembleTable (&IpSb->Assemble);\r
182\r
183 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
e48e37fc 184 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 185\r
186 IpSb->Image = ImageHandle;\r
187 IpSb->Controller = Controller;\r
188\r
189 IpSb->MnpChildHandle = NULL;\r
190 IpSb->Mnp = NULL;\r
191\r
192 IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
193 IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
194 IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
195 IpSb->MnpConfigData.EnableUnicastReceive = TRUE;\r
196 IpSb->MnpConfigData.EnableMulticastReceive = TRUE;\r
197 IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;\r
198 IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
199 IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;\r
200 IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
201 IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;\r
202\r
e48e37fc 203 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
772db4bb 204\r
205 IpSb->Timer = NULL;\r
206 IpSb->Ip4Config = NULL;\r
207 IpSb->DoneEvent = NULL;\r
208 IpSb->ReconfigEvent = NULL;\r
36ee91ca 209 IpSb->ActiveEvent = NULL;\r
772db4bb 210\r
211 //\r
212 // Create various resources. First create the route table, timer\r
213 // event and MNP child. IGMP, interface's initialization depend\r
214 // on the MNP child.\r
215 //\r
216 IpSb->DefaultRouteTable = Ip4CreateRouteTable ();\r
217\r
218 if (IpSb->DefaultRouteTable == NULL) {\r
219 Status = EFI_OUT_OF_RESOURCES;\r
220 goto ON_ERROR;\r
221 }\r
222\r
223 Status = gBS->CreateEvent (\r
224 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 225 TPL_CALLBACK,\r
772db4bb 226 Ip4TimerTicking,\r
227 IpSb,\r
228 &IpSb->Timer\r
229 );\r
230\r
231 if (EFI_ERROR (Status)) {\r
232 goto ON_ERROR;\r
233 }\r
234\r
235 Status = NetLibCreateServiceChild (\r
236 Controller,\r
237 ImageHandle,\r
238 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
239 &IpSb->MnpChildHandle\r
240 );\r
241\r
242 if (EFI_ERROR (Status)) {\r
243 goto ON_ERROR;\r
244 }\r
245\r
246 Status = gBS->OpenProtocol (\r
247 IpSb->MnpChildHandle,\r
248 &gEfiManagedNetworkProtocolGuid,\r
249 (VOID **) &IpSb->Mnp,\r
250 ImageHandle,\r
251 Controller,\r
252 EFI_OPEN_PROTOCOL_BY_DRIVER\r
253 );\r
254\r
255 if (EFI_ERROR (Status)) {\r
256 goto ON_ERROR;\r
257 }\r
258\r
259 Status = Ip4ServiceConfigMnp (IpSb, TRUE);\r
260\r
261 if (EFI_ERROR (Status)) {\r
262 goto ON_ERROR;\r
263 }\r
264\r
265 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
266\r
267 if (EFI_ERROR (Status)) {\r
268 goto ON_ERROR;\r
269 }\r
270\r
271 Status = Ip4InitIgmp (IpSb);\r
272\r
273 if (EFI_ERROR (Status)) {\r
274 goto ON_ERROR;\r
275 }\r
276\r
277 IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
278\r
279 if (IpSb->DefaultInterface == NULL) {\r
280 Status = EFI_OUT_OF_RESOURCES;\r
281 goto ON_ERROR;\r
282 }\r
283\r
e48e37fc 284 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
772db4bb 285\r
286 IpSb->MacString = NULL;\r
287\r
288 *Service = IpSb;\r
289 return EFI_SUCCESS;\r
290\r
291ON_ERROR:\r
292 Ip4CleanService (IpSb);\r
e48e37fc 293 gBS->FreePool (IpSb);\r
772db4bb 294\r
295 return Status;\r
296}\r
297\r
298\r
299/**\r
300 Clean up a IP4 service binding instance. It will release all\r
301 the resource allocated by the instance. The instance may be\r
302 partly initialized, or partly destoried. If a resource is\r
303 destoried, it is marked as that in case the destory failed and\r
304 being called again later.\r
305\r
306 @param IpSb The IP4 serviceing binding instance to clean up\r
307\r
308 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
309 @retval Others Failed to clean up some of the resources.\r
310\r
311**/\r
312EFI_STATUS\r
313Ip4CleanService (\r
314 IN IP4_SERVICE *IpSb\r
315 )\r
316{\r
317 EFI_STATUS Status;\r
318\r
319 if (IpSb->DefaultInterface != NULL) {\r
320 Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
321\r
322 if (EFI_ERROR (Status)) {\r
323 return Status;\r
324 }\r
325\r
326 IpSb->DefaultInterface = NULL;\r
327 }\r
328\r
329 if (IpSb->DefaultRouteTable != NULL) {\r
330 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
331 IpSb->DefaultRouteTable = NULL;\r
332 }\r
333\r
334 Ip4CleanAssembleTable (&IpSb->Assemble);\r
335\r
336 if (IpSb->MnpChildHandle != NULL) {\r
337 if (IpSb->Mnp) {\r
338 gBS->CloseProtocol (\r
339 IpSb->MnpChildHandle,\r
340 &gEfiManagedNetworkProtocolGuid,\r
341 IpSb->Image,\r
342 IpSb->Controller\r
343 );\r
344\r
345 IpSb->Mnp = NULL;\r
346 }\r
347\r
348 NetLibDestroyServiceChild (\r
349 IpSb->Controller,\r
350 IpSb->Image,\r
351 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
352 IpSb->MnpChildHandle\r
353 );\r
354\r
355 IpSb->MnpChildHandle = NULL;\r
356 }\r
357\r
358 if (IpSb->Timer != NULL) {\r
359 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
360 gBS->CloseEvent (IpSb->Timer);\r
361\r
362 IpSb->Timer = NULL;\r
363 }\r
364\r
365 if (IpSb->Ip4Config != NULL) {\r
366 IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
367\r
368 gBS->CloseProtocol (\r
369 IpSb->Controller,\r
370 &gEfiIp4ConfigProtocolGuid,\r
371 IpSb->Image,\r
372 IpSb->Controller\r
373 );\r
374\r
375 gBS->CloseEvent (IpSb->DoneEvent);\r
376 gBS->CloseEvent (IpSb->ReconfigEvent);\r
36ee91ca 377 IpSb->ActiveEvent = NULL;\r
772db4bb 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
e48e37fc 478 gBS->FreePool (IpSb);\r
772db4bb 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
c4a62a12 513 BOOLEAN IsArp;\r
772db4bb 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
c4a62a12 551 return EFI_DEVICE_ERROR;\r
772db4bb 552 }\r
553\r
554 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
555\r
e48e37fc 556 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 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
e48e37fc 570 gBS->RestoreTPL (OldTpl);\r
772db4bb 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
e48e37fc 586 gBS->RestoreTPL (OldTpl);\r
772db4bb 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
c4a62a12 596 IsArp = FALSE;\r
772db4bb 597 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
598\r
599 if (NicHandle == NULL) {\r
600 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
c4a62a12 601 IsArp = TRUE;\r
772db4bb 602 }\r
603\r
604 if (NicHandle == NULL) {\r
c4a62a12 605 return EFI_DEVICE_ERROR;\r
772db4bb 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
e48e37fc 626 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 627\r
628 if (IpSb->InDestory) {\r
e48e37fc 629 gBS->RestoreTPL (OldTpl);\r
772db4bb 630 return EFI_SUCCESS;\r
631 }\r
632\r
c4a62a12 633 if (IsArp) {\r
e48e37fc 634 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 635 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
772db4bb 636\r
c4a62a12 637 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
638 }\r
772db4bb 639\r
c4a62a12 640 if (IpSb->NumChildren != 0) {\r
641 Status = EFI_DEVICE_ERROR;\r
642 goto ON_ERROR;\r
643 }\r
772db4bb 644\r
c4a62a12 645 IpSb->InDestory = TRUE;\r
772db4bb 646\r
c4a62a12 647 State = IpSb->State;\r
648 IpSb->State = IP4_SERVICE_DESTORY;\r
772db4bb 649\r
c4a62a12 650 //\r
651 // Clear the variable data.\r
652 //\r
653 Ip4ClearVariableData (IpSb);\r
772db4bb 654\r
c4a62a12 655 //\r
656 // OK, clean other resources then uninstall the service binding protocol.\r
657 //\r
658 Status = Ip4CleanService (IpSb);\r
772db4bb 659\r
c4a62a12 660 if (EFI_ERROR (Status)) {\r
661 IpSb->State = State;\r
662 goto ON_ERROR;\r
663 }\r
772db4bb 664\r
c4a62a12 665 gBS->UninstallProtocolInterface (\r
666 NicHandle,\r
667 &gEfiIp4ServiceBindingProtocolGuid,\r
668 ServiceBinding\r
669 );\r
772db4bb 670\r
e48e37fc 671 gBS->FreePool (IpSb);\r
c4a62a12 672 } else if (NumberOfChildren == 0) {\r
673 IpSb->InDestory = TRUE;\r
674\r
675 State = IpSb->State;\r
676 IpSb->State = IP4_SERVICE_DESTORY;\r
677\r
678 //\r
679 // Clear the variable data.\r
680 //\r
681 Ip4ClearVariableData (IpSb);\r
682\r
683 //\r
684 // OK, clean other resources then uninstall the service binding protocol.\r
685 //\r
686 Status = Ip4CleanService (IpSb);\r
687\r
688 if (EFI_ERROR (Status)) {\r
689 IpSb->State = State;\r
690 goto ON_ERROR;\r
691 }\r
692\r
693 gBS->UninstallProtocolInterface (\r
694 NicHandle,\r
695 &gEfiIp4ServiceBindingProtocolGuid,\r
696 ServiceBinding\r
697 );\r
698\r
e48e37fc 699 gBS->FreePool (IpSb);\r
c4a62a12 700 } else {\r
701\r
e48e37fc 702 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 703 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
704\r
705 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
706 }\r
707\r
708 if (IpSb->NumChildren != 0) {\r
709 Status = EFI_DEVICE_ERROR;\r
710 }\r
711 }\r
772db4bb 712\r
713ON_ERROR:\r
c4a62a12 714\r
e48e37fc 715 gBS->RestoreTPL (OldTpl);\r
772db4bb 716 return Status;\r
717}\r
718\r
719\r
720/**\r
721 Creates a child handle with a set of I/O services.\r
722\r
723 @param This Protocol instance pointer.\r
724 @param ChildHandle Pointer to the handle of the child to create. If\r
725 it is NULL, then a new handle is created. If it\r
726 is not NULL, then the I/O services are added to\r
727 the existing child handle.\r
728\r
729 @retval EFI_SUCCES The child handle was created with the I/O services\r
730 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
731 the child\r
732 @retval other The child handle was not created\r
733\r
734**/\r
735EFI_STATUS\r
736EFIAPI\r
737Ip4ServiceBindingCreateChild (\r
738 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
739 IN EFI_HANDLE *ChildHandle\r
740 )\r
741{\r
742 IP4_SERVICE *IpSb;\r
743 IP4_PROTOCOL *IpInstance;\r
744 EFI_TPL OldTpl;\r
745 EFI_STATUS Status;\r
746 VOID *Mnp;\r
747\r
748 if ((This == NULL) || (ChildHandle == NULL)) {\r
749 return EFI_INVALID_PARAMETER;\r
750 }\r
751\r
752 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 753 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 754\r
755 if (IpInstance == NULL) {\r
756 return EFI_OUT_OF_RESOURCES;\r
757 }\r
758\r
759 Ip4InitProtocol (IpSb, IpInstance);\r
760\r
761 //\r
762 // Install Ip4 onto ChildHandle\r
763 //\r
764 Status = gBS->InstallMultipleProtocolInterfaces (\r
765 ChildHandle,\r
766 &gEfiIp4ProtocolGuid,\r
767 &IpInstance->Ip4Proto,\r
768 NULL\r
769 );\r
770\r
771 if (EFI_ERROR (Status)) {\r
772 goto ON_ERROR;\r
773 }\r
774\r
775 IpInstance->Handle = *ChildHandle;\r
776\r
777 //\r
778 // Open the Managed Network protocol BY_CHILD.\r
779 //\r
780 Status = gBS->OpenProtocol (\r
781 IpSb->MnpChildHandle,\r
782 &gEfiManagedNetworkProtocolGuid,\r
783 (VOID **) &Mnp,\r
784 gIp4DriverBinding.DriverBindingHandle,\r
785 IpInstance->Handle,\r
786 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
787 );\r
788 if (EFI_ERROR (Status)) {\r
789 gBS->UninstallMultipleProtocolInterfaces (\r
790 ChildHandle,\r
791 &gEfiIp4ProtocolGuid,\r
792 &IpInstance->Ip4Proto,\r
793 NULL\r
794 );\r
795\r
796 goto ON_ERROR;\r
797 }\r
798\r
799 //\r
800 // Insert it into the service binding instance.\r
801 //\r
e48e37fc 802 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 803\r
e48e37fc 804 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 805 IpSb->NumChildren++;\r
806\r
e48e37fc 807 gBS->RestoreTPL (OldTpl);\r
772db4bb 808\r
809ON_ERROR:\r
810\r
811 if (EFI_ERROR (Status)) {\r
812\r
813 Ip4CleanProtocol (IpInstance);\r
814\r
e48e37fc 815 gBS->FreePool (IpInstance);\r
772db4bb 816 }\r
817\r
818 return Status;\r
819}\r
820\r
821\r
822/**\r
823 Destroys a child handle with a set of I/O services.\r
824\r
825 @param This Protocol instance pointer.\r
826 @param ChildHandle Handle of the child to destroy\r
827\r
828 @retval EFI_SUCCES The I/O services were removed from the child\r
829 handle\r
830 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
831 that are being removed\r
832 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
833 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
834 its I/O services are being used.\r
835 @retval other The child handle was not destroyed\r
836\r
837**/\r
838EFI_STATUS\r
839EFIAPI\r
840Ip4ServiceBindingDestroyChild (\r
841 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
842 IN EFI_HANDLE ChildHandle\r
843 )\r
844{\r
845 EFI_STATUS Status;\r
846 IP4_SERVICE *IpSb;\r
847 IP4_PROTOCOL *IpInstance;\r
848 EFI_IP4_PROTOCOL *Ip4;\r
849 EFI_TPL OldTpl;\r
850 INTN State;\r
851\r
852 if ((This == NULL) || (ChildHandle == NULL)) {\r
853 return EFI_INVALID_PARAMETER;\r
854 }\r
855\r
856 //\r
857 // Retrieve the private context data structures\r
858 //\r
859 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
860\r
861 Status = gBS->OpenProtocol (\r
862 ChildHandle,\r
863 &gEfiIp4ProtocolGuid,\r
864 (VOID **) &Ip4,\r
865 gIp4DriverBinding.DriverBindingHandle,\r
866 ChildHandle,\r
867 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
868 );\r
869\r
870 if (EFI_ERROR (Status)) {\r
871 return EFI_UNSUPPORTED;\r
872 }\r
873\r
874 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
875\r
876 if (IpInstance->Service != IpSb) {\r
877 return EFI_INVALID_PARAMETER;\r
878 }\r
879\r
e48e37fc 880 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 881\r
882 //\r
883 // A child can be destoried more than once. For example,\r
884 // Ip4DriverBindingStop will destory all of its children.\r
885 // when UDP driver is being stopped, it will destory all\r
886 // the IP child it opens.\r
887 //\r
888 if (IpInstance->State == IP4_STATE_DESTORY) {\r
e48e37fc 889 gBS->RestoreTPL (OldTpl);\r
772db4bb 890 return EFI_SUCCESS;\r
891 }\r
892\r
893 State = IpInstance->State;\r
894 IpInstance->State = IP4_STATE_DESTORY;\r
895\r
896 //\r
897 // Close the Managed Network protocol.\r
898 //\r
899 gBS->CloseProtocol (\r
900 IpSb->MnpChildHandle,\r
901 &gEfiManagedNetworkProtocolGuid,\r
902 gIp4DriverBinding.DriverBindingHandle,\r
903 ChildHandle\r
904 );\r
905\r
906 //\r
907 // Uninstall the IP4 protocol first. Many thing happens during\r
908 // this:\r
909 // 1. The consumer of the IP4 protocol will be stopped if it\r
910 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
911 // stopped, IP driver's stop function will be called, and uninstall\r
912 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
913 // makes it possible to create the network stack bottom up, and\r
914 // stop it top down.\r
915 // 2. the upper layer will recycle the received packet. The recycle\r
916 // event's TPL is higher than this function. The recycle events\r
917 // will be called back before preceeding. If any packets not recycled,\r
918 // that means there is a resource leak.\r
919 //\r
920 Status = gBS->UninstallProtocolInterface (\r
921 ChildHandle,\r
922 &gEfiIp4ProtocolGuid,\r
923 &IpInstance->Ip4Proto\r
924 );\r
925\r
926 if (EFI_ERROR (Status)) {\r
927 goto ON_ERROR;\r
928 }\r
929\r
930 Status = Ip4CleanProtocol (IpInstance);\r
931\r
932 Ip4SetVariableData (IpSb);\r
933\r
934 if (EFI_ERROR (Status)) {\r
935 gBS->InstallMultipleProtocolInterfaces (\r
936 &ChildHandle,\r
937 &gEfiIp4ProtocolGuid,\r
938 Ip4,\r
939 NULL\r
940 );\r
941\r
942 goto ON_ERROR;\r
943 }\r
944\r
e48e37fc 945 RemoveEntryList (&IpInstance->Link);\r
772db4bb 946 IpSb->NumChildren--;\r
947\r
e48e37fc 948 gBS->RestoreTPL (OldTpl);\r
772db4bb 949\r
e48e37fc 950 gBS->FreePool (IpInstance);\r
772db4bb 951 return EFI_SUCCESS;\r
952\r
953ON_ERROR:\r
954 IpInstance->State = State;\r
e48e37fc 955 gBS->RestoreTPL (OldTpl);\r
772db4bb 956\r
957 return Status;\r
958}\r