]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Scrubbed more.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2005 - 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Ip4Driver.c\r
15\r
16Abstract:\r
17\r
18 The driver binding and service binding protocol for IP4 driver.\r
19\r
20\r
21**/\r
22\r
23#include "Ip4Impl.h"\r
24\r
25EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
26 Ip4DriverBindingSupported,\r
27 Ip4DriverBindingStart,\r
28 Ip4DriverBindingStop,\r
29 0xa,\r
30 NULL,\r
31 NULL\r
32};\r
33\r
5405e9a6 34/**\r
35 This is the declaration of an EFI image entry point. This entry point is\r
36 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
37 both device drivers and bus drivers.\r
38 \r
39 The entry point for IP4 driver which install the driver\r
40 binding and component name protocol on its image.\r
41\r
42 @param ImageHandle The firmware allocated handle for the UEFI image.\r
43 @param SystemTable A pointer to the EFI System Table.\r
44\r
45 @retval EFI_SUCCESS The operation completed successfully.\r
46 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
47\r
48**/\r
772db4bb 49EFI_STATUS\r
50EFIAPI\r
51Ip4DriverEntryPoint (\r
52 IN EFI_HANDLE ImageHandle,\r
53 IN EFI_SYSTEM_TABLE *SystemTable\r
54 )\r
772db4bb 55{\r
83cbd279 56 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 57 ImageHandle,\r
58 SystemTable,\r
59 &gIp4DriverBinding,\r
60 ImageHandle,\r
61 &gIp4ComponentName,\r
83cbd279 62 &gIp4ComponentName2\r
772db4bb 63 );\r
64}\r
65\r
772db4bb 66/**\r
5405e9a6 67 Test to see if this driver supports ControllerHandle. This service\r
68 is called by the EFI boot service ConnectController(). In\r
69 order to make drivers as small as possible, there are a few calling\r
70 restrictions for this service. ConnectController() must\r
71 follow these calling restrictions. If any other agent wishes to call\r
72 Supported() it must also follow these calling restrictions.\r
73\r
74 @param This Protocol instance pointer.\r
75 @param ControllerHandle Handle of device to test\r
76 @param RemainingDevicePath Optional parameter use to pick a specific child\r
77 device to start.\r
78\r
79 @retval EFI_SUCCESS This driver supports this device\r
80 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
81 @retval other This driver does not support this device\r
772db4bb 82\r
83**/\r
84EFI_STATUS\r
85EFIAPI\r
86Ip4DriverBindingSupported (\r
87 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
88 IN EFI_HANDLE ControllerHandle,\r
89 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
90 )\r
91{\r
92 EFI_STATUS Status;\r
93\r
94 //\r
95 // Test for the MNP service binding Protocol\r
96 //\r
97 Status = gBS->OpenProtocol (\r
98 ControllerHandle,\r
99 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
100 NULL,\r
101 This->DriverBindingHandle,\r
102 ControllerHandle,\r
103 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
104 );\r
105\r
106 if (EFI_ERROR (Status)) {\r
107 return Status;\r
108 }\r
109\r
110 //\r
111 // Test for the Arp service binding Protocol\r
112 //\r
113 Status = gBS->OpenProtocol (\r
114 ControllerHandle,\r
115 &gEfiArpServiceBindingProtocolGuid,\r
116 NULL,\r
117 This->DriverBindingHandle,\r
118 ControllerHandle,\r
119 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
120 );\r
121\r
122 return Status;\r
123}\r
124\r
772db4bb 125EFI_STATUS\r
126Ip4CleanService (\r
127 IN IP4_SERVICE *IpSb\r
128 );\r
129\r
130\r
131/**\r
5405e9a6 132 Create a new IP4 driver service binding private instance.\r
772db4bb 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
5405e9a6 142 @retval other Other error occurs.\r
772db4bb 143\r
144**/\r
772db4bb 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
e48e37fc 164 IpSb = AllocatePool (sizeof (IP4_SERVICE));\r
772db4bb 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
e48e37fc 177 InitializeListHead (&IpSb->Children);\r
772db4bb 178\r
e48e37fc 179 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 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
e48e37fc 186 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 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
e48e37fc 205 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
772db4bb 206\r
207 IpSb->Timer = NULL;\r
208 IpSb->Ip4Config = NULL;\r
209 IpSb->DoneEvent = NULL;\r
210 IpSb->ReconfigEvent = NULL;\r
36ee91ca 211 IpSb->ActiveEvent = NULL;\r
772db4bb 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
e48e37fc 227 TPL_CALLBACK,\r
772db4bb 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
e48e37fc 286 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
772db4bb 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
e48e37fc 295 gBS->FreePool (IpSb);\r
772db4bb 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
5405e9a6 304 partly initialized, or partly destroyed. If a resource is\r
305 destroyed, it is marked as that in case the destory failed and\r
772db4bb 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
5405e9a6 311 @retval other Failed to clean up some of the resources.\r
772db4bb 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
5405e9a6 339 if (IpSb->Mnp != NULL) {\r
772db4bb 340 gBS->CloseProtocol (\r
5405e9a6 341 IpSb->MnpChildHandle,\r
342 &gEfiManagedNetworkProtocolGuid,\r
343 IpSb->Image,\r
344 IpSb->Controller\r
345 );\r
772db4bb 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
36ee91ca 379 IpSb->ActiveEvent = NULL;\r
772db4bb 380 IpSb->Ip4Config = NULL;\r
381 }\r
382\r
383 return EFI_SUCCESS;\r
384}\r
385\r
386\r
387/**\r
5405e9a6 388 Start this driver on ControllerHandle. This service is called by the\r
389 EFI boot service ConnectController(). In order to make\r
390 drivers as small as possible, there are a few calling restrictions for\r
391 this service. ConnectController() must follow these\r
392 calling restrictions. If any other agent wishes to call Start() it\r
393 must also follow these calling restrictions.\r
394\r
395 @param This Protocol instance pointer.\r
396 @param ControllerHandle Handle of device to bind driver to\r
397 @param RemainingDevicePath Optional parameter use to pick a specific child\r
398 device to start.\r
399\r
400 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
401 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
402 @retval other This driver does not support this device\r
772db4bb 403\r
404**/\r
405EFI_STATUS\r
406EFIAPI\r
407Ip4DriverBindingStart (\r
408 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
409 IN EFI_HANDLE ControllerHandle,\r
410 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
411 )\r
412{\r
413 IP4_SERVICE *IpSb;\r
414 EFI_STATUS Status;\r
415\r
416 //\r
417 // Test for the Ip4 service binding protocol\r
418 //\r
419 Status = gBS->OpenProtocol (\r
420 ControllerHandle,\r
421 &gEfiIp4ServiceBindingProtocolGuid,\r
422 NULL,\r
423 This->DriverBindingHandle,\r
424 ControllerHandle,\r
425 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
426 );\r
427\r
428 if (Status == EFI_SUCCESS) {\r
429 return EFI_ALREADY_STARTED;\r
430 }\r
431\r
432 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
433\r
434 if (EFI_ERROR (Status)) {\r
435 return Status;\r
436 }\r
437\r
438 //\r
439 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
440 //\r
441 Status = gBS->InstallMultipleProtocolInterfaces (\r
442 &ControllerHandle,\r
443 &gEfiIp4ServiceBindingProtocolGuid,\r
444 &IpSb->ServiceBinding,\r
445 NULL\r
446 );\r
447\r
448 if (EFI_ERROR (Status)) {\r
449 goto FREE_SERVICE;\r
450 }\r
451\r
452 //\r
453 // ready to go: start the receiving and timer\r
454 //\r
455 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
456\r
457 if (EFI_ERROR (Status)) {\r
458 goto UNINSTALL_PROTOCOL;\r
459 }\r
460\r
461 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
462\r
463 if (EFI_ERROR (Status)) {\r
464 goto UNINSTALL_PROTOCOL;\r
465 }\r
466\r
467 //\r
468 // Initialize the IP4 ID\r
469 //\r
470 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
471\r
472 Ip4SetVariableData (IpSb);\r
473\r
474 return Status;\r
475\r
476UNINSTALL_PROTOCOL:\r
477 gBS->UninstallProtocolInterface (\r
478 ControllerHandle,\r
479 &gEfiIp4ServiceBindingProtocolGuid,\r
480 &IpSb->ServiceBinding\r
481 );\r
482\r
483FREE_SERVICE:\r
484 Ip4CleanService (IpSb);\r
e48e37fc 485 gBS->FreePool (IpSb);\r
772db4bb 486\r
487 return Status;\r
488}\r
489\r
490\r
491/**\r
5405e9a6 492 Stop this driver on ControllerHandle. This service is called by the\r
493 EFI boot service DisconnectController(). In order to\r
494 make drivers as small as possible, there are a few calling\r
495 restrictions for this service. DisconnectController()\r
496 must follow these calling restrictions. If any other agent wishes\r
497 to call Stop() it must also follow these calling restrictions.\r
498 \r
499 @param This Protocol instance pointer.\r
500 @param ControllerHandle Handle of device to stop driver on\r
501 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of\r
502 children is zero stop the entire bus driver.\r
503 @param ChildHandleBuffer List of Child Handles to Stop.\r
504\r
505 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
506 @retval other This driver was not removed from this device\r
772db4bb 507\r
508**/\r
509EFI_STATUS\r
510EFIAPI\r
511Ip4DriverBindingStop (\r
512 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
513 IN EFI_HANDLE ControllerHandle,\r
514 IN UINTN NumberOfChildren,\r
515 IN EFI_HANDLE *ChildHandleBuffer\r
516 )\r
517{\r
518 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
519 IP4_SERVICE *IpSb;\r
520 IP4_PROTOCOL *IpInstance;\r
521 EFI_HANDLE NicHandle;\r
522 EFI_STATUS Status;\r
523 EFI_TPL OldTpl;\r
524 INTN State;\r
c4a62a12 525 BOOLEAN IsArp;\r
772db4bb 526\r
527 //\r
528 // IP4 driver opens the MNP child, ARP children or the IP4_CONFIG protocol\r
529 // by driver. So the ControllerHandle may be the MNP child handle, ARP child\r
530 // handle, or the NIC (UNDI) handle because IP4_CONFIG protocol is installed\r
531 // in the NIC handle.\r
532 //\r
533 //\r
534 // First, check whether it is the IP4_CONFIG protocol being uninstalled.\r
535 // IP4_CONFIG protocol is installed on the NIC handle. It isn't necessary\r
536 // to clean up the default configuration if IP4_CONFIG is being stopped.\r
537 //\r
538 Status = gBS->OpenProtocol (\r
539 ControllerHandle,\r
540 &gEfiIp4ConfigProtocolGuid,\r
541 NULL,\r
542 This->DriverBindingHandle,\r
543 ControllerHandle,\r
544 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
545 );\r
546\r
547 if (Status == EFI_SUCCESS) {\r
548 //\r
549 // Retrieve the IP4 service binding protocol. If failed, it is\r
550 // likely that Ip4 ServiceBinding is uninstalled already. In this\r
551 // case, return immediately.\r
552 //\r
553 Status = gBS->OpenProtocol (\r
554 ControllerHandle,\r
555 &gEfiIp4ServiceBindingProtocolGuid,\r
556 (VOID **) &ServiceBinding,\r
557 This->DriverBindingHandle,\r
558 ControllerHandle,\r
559 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
560 );\r
561\r
562 if (EFI_ERROR (Status)) {\r
c4a62a12 563 return EFI_DEVICE_ERROR;\r
772db4bb 564 }\r
565\r
566 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
567\r
e48e37fc 568 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 569\r
5405e9a6 570 if (IpSb->Ip4Config != NULL && (IpSb->State != IP4_SERVICE_DESTORY)) {\r
772db4bb 571\r
572 IpSb->Ip4Config->Stop (IpSb->Ip4Config);\r
573\r
574 Status = gBS->CloseProtocol (\r
575 ControllerHandle,\r
576 &gEfiIp4ConfigProtocolGuid,\r
577 IpSb->Image,\r
578 ControllerHandle\r
579 );\r
580\r
581 if (EFI_ERROR (Status)) {\r
e48e37fc 582 gBS->RestoreTPL (OldTpl);\r
772db4bb 583 return Status;\r
584 }\r
585\r
586 //\r
587 // If the auto configure hasn't complete, mark it as not started.\r
588 //\r
589 if (IpSb->State == IP4_SERVICE_STARTED) {\r
590 IpSb->State = IP4_SERVICE_UNSTARTED;\r
591 }\r
592\r
593 IpSb->Ip4Config = NULL;\r
594 gBS->CloseEvent (IpSb->DoneEvent);\r
595 gBS->CloseEvent (IpSb->ReconfigEvent);\r
596 }\r
597\r
e48e37fc 598 gBS->RestoreTPL (OldTpl);\r
772db4bb 599 return EFI_SUCCESS;\r
600 }\r
601\r
602 //\r
603 // Either MNP or ARP protocol is being uninstalled. The controller\r
604 // handle is either the MNP child or ARP child. But, the IP4's\r
605 // service binding is installed on the NIC handle. So, need to open\r
606 // the protocol info to find the NIC handle.\r
607 //\r
c4a62a12 608 IsArp = FALSE;\r
772db4bb 609 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
610\r
611 if (NicHandle == NULL) {\r
612 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
c4a62a12 613 IsArp = TRUE;\r
772db4bb 614 }\r
615\r
616 if (NicHandle == NULL) {\r
c4a62a12 617 return EFI_DEVICE_ERROR;\r
772db4bb 618 }\r
619\r
620 //\r
621 // Retrieve the IP4 service binding protocol\r
622 //\r
623 Status = gBS->OpenProtocol (\r
624 NicHandle,\r
625 &gEfiIp4ServiceBindingProtocolGuid,\r
626 (VOID **) &ServiceBinding,\r
627 This->DriverBindingHandle,\r
628 NicHandle,\r
629 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
630 );\r
631\r
632 if (EFI_ERROR (Status)) {\r
633 return EFI_DEVICE_ERROR;\r
634 }\r
635\r
636 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
637\r
e48e37fc 638 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 639\r
640 if (IpSb->InDestory) {\r
e48e37fc 641 gBS->RestoreTPL (OldTpl);\r
772db4bb 642 return EFI_SUCCESS;\r
643 }\r
644\r
c4a62a12 645 if (IsArp) {\r
e48e37fc 646 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 647 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
772db4bb 648\r
c4a62a12 649 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
650 }\r
772db4bb 651\r
c4a62a12 652 if (IpSb->NumChildren != 0) {\r
653 Status = EFI_DEVICE_ERROR;\r
654 goto ON_ERROR;\r
655 }\r
772db4bb 656\r
c4a62a12 657 IpSb->InDestory = TRUE;\r
772db4bb 658\r
c4a62a12 659 State = IpSb->State;\r
660 IpSb->State = IP4_SERVICE_DESTORY;\r
772db4bb 661\r
c4a62a12 662 //\r
663 // Clear the variable data.\r
664 //\r
665 Ip4ClearVariableData (IpSb);\r
772db4bb 666\r
c4a62a12 667 //\r
668 // OK, clean other resources then uninstall the service binding protocol.\r
669 //\r
670 Status = Ip4CleanService (IpSb);\r
772db4bb 671\r
c4a62a12 672 if (EFI_ERROR (Status)) {\r
673 IpSb->State = State;\r
674 goto ON_ERROR;\r
675 }\r
772db4bb 676\r
c4a62a12 677 gBS->UninstallProtocolInterface (\r
678 NicHandle,\r
679 &gEfiIp4ServiceBindingProtocolGuid,\r
680 ServiceBinding\r
681 );\r
772db4bb 682\r
e48e37fc 683 gBS->FreePool (IpSb);\r
c4a62a12 684 } else if (NumberOfChildren == 0) {\r
685 IpSb->InDestory = TRUE;\r
686\r
687 State = IpSb->State;\r
688 IpSb->State = IP4_SERVICE_DESTORY;\r
689\r
690 //\r
691 // Clear the variable data.\r
692 //\r
693 Ip4ClearVariableData (IpSb);\r
694\r
695 //\r
696 // OK, clean other resources then uninstall the service binding protocol.\r
697 //\r
698 Status = Ip4CleanService (IpSb);\r
699\r
700 if (EFI_ERROR (Status)) {\r
701 IpSb->State = State;\r
702 goto ON_ERROR;\r
703 }\r
704\r
705 gBS->UninstallProtocolInterface (\r
706 NicHandle,\r
707 &gEfiIp4ServiceBindingProtocolGuid,\r
708 ServiceBinding\r
709 );\r
710\r
e48e37fc 711 gBS->FreePool (IpSb);\r
c4a62a12 712 } else {\r
713\r
e48e37fc 714 while (!IsListEmpty (&IpSb->Children)) {\r
c4a62a12 715 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
716\r
717 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
718 }\r
719\r
720 if (IpSb->NumChildren != 0) {\r
721 Status = EFI_DEVICE_ERROR;\r
722 }\r
723 }\r
772db4bb 724\r
725ON_ERROR:\r
c4a62a12 726\r
e48e37fc 727 gBS->RestoreTPL (OldTpl);\r
772db4bb 728 return Status;\r
729}\r
730\r
731\r
732/**\r
733 Creates a child handle with a set of I/O services.\r
734\r
5405e9a6 735 @param This Protocol instance pointer.\r
736 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
737 then a new handle is created. If it is not NULL, then the\r
738 I/O services are added to the existing child handle.\r
772db4bb 739\r
5405e9a6 740 @retval EFI_SUCCES The child handle was created with the I/O services\r
741 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
742 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
743 the child\r
744 @retval other The child handle was not created\r
772db4bb 745\r
746**/\r
747EFI_STATUS\r
748EFIAPI\r
749Ip4ServiceBindingCreateChild (\r
750 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
5405e9a6 751 IN OUT EFI_HANDLE *ChildHandle\r
772db4bb 752 )\r
753{\r
754 IP4_SERVICE *IpSb;\r
755 IP4_PROTOCOL *IpInstance;\r
756 EFI_TPL OldTpl;\r
757 EFI_STATUS Status;\r
758 VOID *Mnp;\r
759\r
760 if ((This == NULL) || (ChildHandle == NULL)) {\r
761 return EFI_INVALID_PARAMETER;\r
762 }\r
763\r
764 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 765 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 766\r
767 if (IpInstance == NULL) {\r
768 return EFI_OUT_OF_RESOURCES;\r
769 }\r
770\r
771 Ip4InitProtocol (IpSb, IpInstance);\r
772\r
773 //\r
774 // Install Ip4 onto ChildHandle\r
775 //\r
776 Status = gBS->InstallMultipleProtocolInterfaces (\r
777 ChildHandle,\r
778 &gEfiIp4ProtocolGuid,\r
779 &IpInstance->Ip4Proto,\r
780 NULL\r
781 );\r
782\r
783 if (EFI_ERROR (Status)) {\r
784 goto ON_ERROR;\r
785 }\r
786\r
787 IpInstance->Handle = *ChildHandle;\r
788\r
789 //\r
790 // Open the Managed Network protocol BY_CHILD.\r
791 //\r
792 Status = gBS->OpenProtocol (\r
793 IpSb->MnpChildHandle,\r
794 &gEfiManagedNetworkProtocolGuid,\r
795 (VOID **) &Mnp,\r
796 gIp4DriverBinding.DriverBindingHandle,\r
797 IpInstance->Handle,\r
798 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
799 );\r
800 if (EFI_ERROR (Status)) {\r
801 gBS->UninstallMultipleProtocolInterfaces (\r
802 ChildHandle,\r
803 &gEfiIp4ProtocolGuid,\r
804 &IpInstance->Ip4Proto,\r
805 NULL\r
806 );\r
807\r
808 goto ON_ERROR;\r
809 }\r
810\r
811 //\r
812 // Insert it into the service binding instance.\r
813 //\r
e48e37fc 814 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 815\r
e48e37fc 816 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 817 IpSb->NumChildren++;\r
818\r
e48e37fc 819 gBS->RestoreTPL (OldTpl);\r
772db4bb 820\r
821ON_ERROR:\r
822\r
823 if (EFI_ERROR (Status)) {\r
824\r
825 Ip4CleanProtocol (IpInstance);\r
826\r
e48e37fc 827 gBS->FreePool (IpInstance);\r
772db4bb 828 }\r
829\r
830 return Status;\r
831}\r
832\r
833\r
834/**\r
835 Destroys a child handle with a set of I/O services.\r
836\r
5405e9a6 837 @param This Protocol instance pointer.\r
838 @param ChildHandle Handle of the child to destroy\r
839\r
840 @retval EFI_SUCCES The I/O services were removed from the child handle\r
841 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
842 that are being removed.\r
843 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
844 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because its\r
845 I/O services are being used.\r
846 @retval other The child handle was not destroyed\r
772db4bb 847\r
848**/\r
849EFI_STATUS\r
850EFIAPI\r
851Ip4ServiceBindingDestroyChild (\r
852 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
853 IN EFI_HANDLE ChildHandle\r
854 )\r
855{\r
856 EFI_STATUS Status;\r
857 IP4_SERVICE *IpSb;\r
858 IP4_PROTOCOL *IpInstance;\r
859 EFI_IP4_PROTOCOL *Ip4;\r
860 EFI_TPL OldTpl;\r
861 INTN State;\r
862\r
863 if ((This == NULL) || (ChildHandle == NULL)) {\r
864 return EFI_INVALID_PARAMETER;\r
865 }\r
866\r
867 //\r
868 // Retrieve the private context data structures\r
869 //\r
870 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
871\r
872 Status = gBS->OpenProtocol (\r
873 ChildHandle,\r
874 &gEfiIp4ProtocolGuid,\r
875 (VOID **) &Ip4,\r
876 gIp4DriverBinding.DriverBindingHandle,\r
877 ChildHandle,\r
878 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
879 );\r
880\r
881 if (EFI_ERROR (Status)) {\r
882 return EFI_UNSUPPORTED;\r
883 }\r
884\r
885 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
886\r
887 if (IpInstance->Service != IpSb) {\r
888 return EFI_INVALID_PARAMETER;\r
889 }\r
890\r
e48e37fc 891 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 892\r
893 //\r
894 // A child can be destoried more than once. For example,\r
895 // Ip4DriverBindingStop will destory all of its children.\r
896 // when UDP driver is being stopped, it will destory all\r
897 // the IP child it opens.\r
898 //\r
899 if (IpInstance->State == IP4_STATE_DESTORY) {\r
e48e37fc 900 gBS->RestoreTPL (OldTpl);\r
772db4bb 901 return EFI_SUCCESS;\r
902 }\r
903\r
904 State = IpInstance->State;\r
905 IpInstance->State = IP4_STATE_DESTORY;\r
906\r
907 //\r
908 // Close the Managed Network protocol.\r
909 //\r
910 gBS->CloseProtocol (\r
911 IpSb->MnpChildHandle,\r
912 &gEfiManagedNetworkProtocolGuid,\r
913 gIp4DriverBinding.DriverBindingHandle,\r
914 ChildHandle\r
915 );\r
916\r
917 //\r
918 // Uninstall the IP4 protocol first. Many thing happens during\r
919 // this:\r
920 // 1. The consumer of the IP4 protocol will be stopped if it\r
921 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
922 // stopped, IP driver's stop function will be called, and uninstall\r
923 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
924 // makes it possible to create the network stack bottom up, and\r
925 // stop it top down.\r
926 // 2. the upper layer will recycle the received packet. The recycle\r
927 // event's TPL is higher than this function. The recycle events\r
928 // will be called back before preceeding. If any packets not recycled,\r
929 // that means there is a resource leak.\r
930 //\r
931 Status = gBS->UninstallProtocolInterface (\r
932 ChildHandle,\r
933 &gEfiIp4ProtocolGuid,\r
934 &IpInstance->Ip4Proto\r
935 );\r
936\r
937 if (EFI_ERROR (Status)) {\r
938 goto ON_ERROR;\r
939 }\r
940\r
941 Status = Ip4CleanProtocol (IpInstance);\r
942\r
943 Ip4SetVariableData (IpSb);\r
944\r
945 if (EFI_ERROR (Status)) {\r
946 gBS->InstallMultipleProtocolInterfaces (\r
947 &ChildHandle,\r
948 &gEfiIp4ProtocolGuid,\r
949 Ip4,\r
950 NULL\r
951 );\r
952\r
953 goto ON_ERROR;\r
954 }\r
955\r
e48e37fc 956 RemoveEntryList (&IpInstance->Link);\r
772db4bb 957 IpSb->NumChildren--;\r
958\r
e48e37fc 959 gBS->RestoreTPL (OldTpl);\r
772db4bb 960\r
e48e37fc 961 gBS->FreePool (IpInstance);\r
772db4bb 962 return EFI_SUCCESS;\r
963\r
964ON_ERROR:\r
965 IpInstance->State = State;\r
e48e37fc 966 gBS->RestoreTPL (OldTpl);\r
772db4bb 967\r
968 return Status;\r
969}\r