]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
Sync the latest version from R8.
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
CommitLineData
772db4bb 1/** @file\r
2\r
3Copyright (c) 2005 - 2006, Intel Corporation\r
4All rights reserved. This program and the accompanying materials\r
5are licensed and made available under the terms and conditions of the BSD License\r
6which accompanies this distribution. The full text of the license may be found at\r
7http://opensource.org/licenses/bsd-license.php\r
8\r
9THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
10WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
11\r
12Module Name:\r
13\r
14 Ip4Driver.c\r
15\r
16Abstract:\r
17\r
18 The driver binding and service binding protocol for IP4 driver.\r
19\r
20\r
21**/\r
22\r
23#include "Ip4Impl.h"\r
24\r
25EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
26 Ip4DriverBindingSupported,\r
27 Ip4DriverBindingStart,\r
28 Ip4DriverBindingStop,\r
29 0xa,\r
30 NULL,\r
31 NULL\r
32};\r
33\r
772db4bb 34EFI_STATUS\r
35EFIAPI\r
36Ip4DriverEntryPoint (\r
37 IN EFI_HANDLE ImageHandle,\r
38 IN EFI_SYSTEM_TABLE *SystemTable\r
39 )\r
40/*++\r
41\r
42Routine Description:\r
43\r
44 The entry point for IP4 driver which install the driver\r
45 binding and component name protocol on its image.\r
46\r
47Arguments:\r
48\r
49 ImageHandle - The image handle of the driver\r
50 SystemTable - The system table\r
51\r
52Returns:\r
53\r
54 EFI_SUCCESS if the driver binding and component name protocols\r
55 are successfully installed, otherwise if failed.\r
56\r
57--*/\r
58{\r
83cbd279 59 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 60 ImageHandle,\r
61 SystemTable,\r
62 &gIp4DriverBinding,\r
63 ImageHandle,\r
64 &gIp4ComponentName,\r
83cbd279 65 &gIp4ComponentName2\r
772db4bb 66 );\r
67}\r
68\r
69\r
70/**\r
71 Test to see if this driver supports ControllerHandle.\r
72\r
73 @param This Protocol instance pointer.\r
74 @param ControllerHandle Handle of device to test\r
75 @param RemainingDevicePath Optional parameter use to pick a specific child\r
76 device to start.\r
77\r
78 @retval EFI_SUCCES This driver supports this device\r
79 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
80 @retval other This driver does not support this device\r
81\r
82**/\r
83EFI_STATUS\r
84EFIAPI\r
85Ip4DriverBindingSupported (\r
86 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
87 IN EFI_HANDLE ControllerHandle,\r
88 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
89 )\r
90{\r
91 EFI_STATUS Status;\r
92\r
93 //\r
94 // Test for the MNP service binding Protocol\r
95 //\r
96 Status = gBS->OpenProtocol (\r
97 ControllerHandle,\r
98 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
99 NULL,\r
100 This->DriverBindingHandle,\r
101 ControllerHandle,\r
102 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
103 );\r
104\r
105 if (EFI_ERROR (Status)) {\r
106 return Status;\r
107 }\r
108\r
109 //\r
110 // Test for the Arp service binding Protocol\r
111 //\r
112 Status = gBS->OpenProtocol (\r
113 ControllerHandle,\r
114 &gEfiArpServiceBindingProtocolGuid,\r
115 NULL,\r
116 This->DriverBindingHandle,\r
117 ControllerHandle,\r
118 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
119 );\r
120\r
121 return Status;\r
122}\r
123\r
124STATIC\r
125EFI_STATUS\r
126Ip4CleanService (\r
127 IN IP4_SERVICE *IpSb\r
128 );\r
129\r
130\r
131/**\r
132 Create a new IP4 driver service binding protocol\r
133\r
134 @param Controller The controller that has MNP service binding\r
135 installed\r
136 @param ImageHandle The IP4 driver's image handle\r
137 @param Service The variable to receive the newly created IP4\r
138 service.\r
139\r
140 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource\r
141 @retval EFI_SUCCESS A new IP4 service binding private is created.\r
142\r
143**/\r
144STATIC\r
145EFI_STATUS\r
146Ip4CreateService (\r
147 IN EFI_HANDLE Controller,\r
148 IN EFI_HANDLE ImageHandle,\r
149 OUT IP4_SERVICE **Service\r
150 )\r
151{\r
152 IP4_SERVICE *IpSb;\r
153 EFI_STATUS Status;\r
154\r
155 ASSERT (Service != NULL);\r
156\r
157 *Service = NULL;\r
158\r
159 //\r
160 // allocate a service private data then initialize all the filed to\r
161 // empty resources, so if any thing goes wrong when allocating\r
162 // resources, Ip4CleanService can be called to clean it up.\r
163 //\r
164 IpSb = NetAllocatePool (sizeof (IP4_SERVICE));\r
165\r
166 if (IpSb == NULL) {\r
167 return EFI_OUT_OF_RESOURCES;\r
168 }\r
169\r
170 IpSb->Signature = IP4_SERVICE_SIGNATURE;\r
171 IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;\r
172 IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
173 IpSb->State = IP4_SERVICE_UNSTARTED;\r
174 IpSb->InDestory = FALSE;\r
175\r
176 IpSb->NumChildren = 0;\r
177 NetListInit (&IpSb->Children);\r
178\r
179 NetListInit (&IpSb->Interfaces);\r
180 IpSb->DefaultInterface = NULL;\r
181 IpSb->DefaultRouteTable = NULL;\r
182\r
183 Ip4InitAssembleTable (&IpSb->Assemble);\r
184\r
185 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
186 NetListInit (&IpSb->IgmpCtrl.Groups);\r
187\r
188 IpSb->Image = ImageHandle;\r
189 IpSb->Controller = Controller;\r
190\r
191 IpSb->MnpChildHandle = NULL;\r
192 IpSb->Mnp = NULL;\r
193\r
194 IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
195 IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
196 IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
197 IpSb->MnpConfigData.EnableUnicastReceive = TRUE;\r
198 IpSb->MnpConfigData.EnableMulticastReceive = TRUE;\r
199 IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;\r
200 IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
201 IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;\r
202 IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
203 IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;\r
204\r
205 NetZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
206\r
207 IpSb->Timer = NULL;\r
208 IpSb->Ip4Config = NULL;\r
209 IpSb->DoneEvent = NULL;\r
210 IpSb->ReconfigEvent = NULL;\r
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
36ee91ca 227 NET_TPL_TIMER,\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
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
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
388 Start this driver on ControllerHandle.\r
389\r
390 @param This Protocol instance pointer.\r
391 @param ControllerHandle Handle of device to bind driver to\r
392 @param RemainingDevicePath Optional parameter use to pick a specific child\r
393 device to start.\r
394\r
395 @retval EFI_SUCCES This driver is added to ControllerHandle\r
396 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
397 @retval other This driver does not support this device\r
398\r
399**/\r
400EFI_STATUS\r
401EFIAPI\r
402Ip4DriverBindingStart (\r
403 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
404 IN EFI_HANDLE ControllerHandle,\r
405 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
406 )\r
407{\r
408 IP4_SERVICE *IpSb;\r
409 EFI_STATUS Status;\r
410\r
411 //\r
412 // Test for the Ip4 service binding protocol\r
413 //\r
414 Status = gBS->OpenProtocol (\r
415 ControllerHandle,\r
416 &gEfiIp4ServiceBindingProtocolGuid,\r
417 NULL,\r
418 This->DriverBindingHandle,\r
419 ControllerHandle,\r
420 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
421 );\r
422\r
423 if (Status == EFI_SUCCESS) {\r
424 return EFI_ALREADY_STARTED;\r
425 }\r
426\r
427 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
428\r
429 if (EFI_ERROR (Status)) {\r
430 return Status;\r
431 }\r
432\r
433 //\r
434 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
435 //\r
436 Status = gBS->InstallMultipleProtocolInterfaces (\r
437 &ControllerHandle,\r
438 &gEfiIp4ServiceBindingProtocolGuid,\r
439 &IpSb->ServiceBinding,\r
440 NULL\r
441 );\r
442\r
443 if (EFI_ERROR (Status)) {\r
444 goto FREE_SERVICE;\r
445 }\r
446\r
447 //\r
448 // ready to go: start the receiving and timer\r
449 //\r
450 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
451\r
452 if (EFI_ERROR (Status)) {\r
453 goto UNINSTALL_PROTOCOL;\r
454 }\r
455\r
456 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
457\r
458 if (EFI_ERROR (Status)) {\r
459 goto UNINSTALL_PROTOCOL;\r
460 }\r
461\r
462 //\r
463 // Initialize the IP4 ID\r
464 //\r
465 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
466\r
467 Ip4SetVariableData (IpSb);\r
468\r
469 return Status;\r
470\r
471UNINSTALL_PROTOCOL:\r
472 gBS->UninstallProtocolInterface (\r
473 ControllerHandle,\r
474 &gEfiIp4ServiceBindingProtocolGuid,\r
475 &IpSb->ServiceBinding\r
476 );\r
477\r
478FREE_SERVICE:\r
479 Ip4CleanService (IpSb);\r
480 NetFreePool (IpSb);\r
481\r
482 return Status;\r
483}\r
484\r
485\r
486/**\r
487 Stop this driver on ControllerHandle.\r
488\r
489 @param This Protocol instance pointer.\r
490 @param ControllerHandle Handle of device to stop driver on\r
491 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
492 of children is zero stop the entire bus driver.\r
493 @param ChildHandleBuffer List of Child Handles to Stop.\r
494\r
495 @retval EFI_SUCCES This driver is removed ControllerHandle\r
496 @retval other This driver was not removed from this device\r
497\r
498**/\r
499EFI_STATUS\r
500EFIAPI\r
501Ip4DriverBindingStop (\r
502 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
503 IN EFI_HANDLE ControllerHandle,\r
504 IN UINTN NumberOfChildren,\r
505 IN EFI_HANDLE *ChildHandleBuffer\r
506 )\r
507{\r
508 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
509 IP4_SERVICE *IpSb;\r
510 IP4_PROTOCOL *IpInstance;\r
511 EFI_HANDLE NicHandle;\r
512 EFI_STATUS Status;\r
513 EFI_TPL OldTpl;\r
514 INTN State;\r
c4a62a12 515 BOOLEAN IsArp;\r
772db4bb 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
c4a62a12 553 return EFI_DEVICE_ERROR;\r
772db4bb 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
c4a62a12 598 IsArp = FALSE;\r
772db4bb 599 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
600\r
601 if (NicHandle == NULL) {\r
602 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
c4a62a12 603 IsArp = TRUE;\r
772db4bb 604 }\r
605\r
606 if (NicHandle == NULL) {\r
c4a62a12 607 return EFI_DEVICE_ERROR;\r
772db4bb 608 }\r
609\r
610 //\r
611 // Retrieve the IP4 service binding protocol\r
612 //\r
613 Status = gBS->OpenProtocol (\r
614 NicHandle,\r
615 &gEfiIp4ServiceBindingProtocolGuid,\r
616 (VOID **) &ServiceBinding,\r
617 This->DriverBindingHandle,\r
618 NicHandle,\r
619 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
620 );\r
621\r
622 if (EFI_ERROR (Status)) {\r
623 return EFI_DEVICE_ERROR;\r
624 }\r
625\r
626 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
627\r
628 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
629\r
630 if (IpSb->InDestory) {\r
631 NET_RESTORE_TPL (OldTpl);\r
632 return EFI_SUCCESS;\r
633 }\r
634\r
c4a62a12 635 if (IsArp) {\r
636 while (!NetListIsEmpty (&IpSb->Children)) {\r
637 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
772db4bb 638\r
c4a62a12 639 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
640 }\r
772db4bb 641\r
c4a62a12 642 if (IpSb->NumChildren != 0) {\r
643 Status = EFI_DEVICE_ERROR;\r
644 goto ON_ERROR;\r
645 }\r
772db4bb 646\r
c4a62a12 647 IpSb->InDestory = TRUE;\r
772db4bb 648\r
c4a62a12 649 State = IpSb->State;\r
650 IpSb->State = IP4_SERVICE_DESTORY;\r
772db4bb 651\r
c4a62a12 652 //\r
653 // Clear the variable data.\r
654 //\r
655 Ip4ClearVariableData (IpSb);\r
772db4bb 656\r
c4a62a12 657 //\r
658 // OK, clean other resources then uninstall the service binding protocol.\r
659 //\r
660 Status = Ip4CleanService (IpSb);\r
772db4bb 661\r
c4a62a12 662 if (EFI_ERROR (Status)) {\r
663 IpSb->State = State;\r
664 goto ON_ERROR;\r
665 }\r
772db4bb 666\r
c4a62a12 667 gBS->UninstallProtocolInterface (\r
668 NicHandle,\r
669 &gEfiIp4ServiceBindingProtocolGuid,\r
670 ServiceBinding\r
671 );\r
772db4bb 672\r
c4a62a12 673 NetFreePool (IpSb);\r
674 } else if (NumberOfChildren == 0) {\r
675 IpSb->InDestory = TRUE;\r
676\r
677 State = IpSb->State;\r
678 IpSb->State = IP4_SERVICE_DESTORY;\r
679\r
680 //\r
681 // Clear the variable data.\r
682 //\r
683 Ip4ClearVariableData (IpSb);\r
684\r
685 //\r
686 // OK, clean other resources then uninstall the service binding protocol.\r
687 //\r
688 Status = Ip4CleanService (IpSb);\r
689\r
690 if (EFI_ERROR (Status)) {\r
691 IpSb->State = State;\r
692 goto ON_ERROR;\r
693 }\r
694\r
695 gBS->UninstallProtocolInterface (\r
696 NicHandle,\r
697 &gEfiIp4ServiceBindingProtocolGuid,\r
698 ServiceBinding\r
699 );\r
700\r
701 NetFreePool (IpSb);\r
702 } else {\r
703\r
704 while (!NetListIsEmpty (&IpSb->Children)) {\r
705 IpInstance = NET_LIST_HEAD (&IpSb->Children, IP4_PROTOCOL, Link);\r
706\r
707 ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
708 }\r
709\r
710 if (IpSb->NumChildren != 0) {\r
711 Status = EFI_DEVICE_ERROR;\r
712 }\r
713 }\r
772db4bb 714\r
715ON_ERROR:\r
c4a62a12 716\r
772db4bb 717 NET_RESTORE_TPL (OldTpl);\r
718 return Status;\r
719}\r
720\r
721\r
722/**\r
723 Creates a child handle with a set of I/O services.\r
724\r
725 @param This Protocol instance pointer.\r
726 @param ChildHandle Pointer to the handle of the child to create. If\r
727 it is NULL, then a new handle is created. If it\r
728 is not NULL, then the I/O services are added to\r
729 the existing child handle.\r
730\r
731 @retval EFI_SUCCES The child handle was created with the I/O services\r
732 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
733 the child\r
734 @retval other The child handle was not created\r
735\r
736**/\r
737EFI_STATUS\r
738EFIAPI\r
739Ip4ServiceBindingCreateChild (\r
740 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
741 IN EFI_HANDLE *ChildHandle\r
742 )\r
743{\r
744 IP4_SERVICE *IpSb;\r
745 IP4_PROTOCOL *IpInstance;\r
746 EFI_TPL OldTpl;\r
747 EFI_STATUS Status;\r
748 VOID *Mnp;\r
749\r
750 if ((This == NULL) || (ChildHandle == NULL)) {\r
751 return EFI_INVALID_PARAMETER;\r
752 }\r
753\r
754 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
755 IpInstance = NetAllocatePool (sizeof (IP4_PROTOCOL));\r
756\r
757 if (IpInstance == NULL) {\r
758 return EFI_OUT_OF_RESOURCES;\r
759 }\r
760\r
761 Ip4InitProtocol (IpSb, IpInstance);\r
762\r
763 //\r
764 // Install Ip4 onto ChildHandle\r
765 //\r
766 Status = gBS->InstallMultipleProtocolInterfaces (\r
767 ChildHandle,\r
768 &gEfiIp4ProtocolGuid,\r
769 &IpInstance->Ip4Proto,\r
770 NULL\r
771 );\r
772\r
773 if (EFI_ERROR (Status)) {\r
774 goto ON_ERROR;\r
775 }\r
776\r
777 IpInstance->Handle = *ChildHandle;\r
778\r
779 //\r
780 // Open the Managed Network protocol BY_CHILD.\r
781 //\r
782 Status = gBS->OpenProtocol (\r
783 IpSb->MnpChildHandle,\r
784 &gEfiManagedNetworkProtocolGuid,\r
785 (VOID **) &Mnp,\r
786 gIp4DriverBinding.DriverBindingHandle,\r
787 IpInstance->Handle,\r
788 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
789 );\r
790 if (EFI_ERROR (Status)) {\r
791 gBS->UninstallMultipleProtocolInterfaces (\r
792 ChildHandle,\r
793 &gEfiIp4ProtocolGuid,\r
794 &IpInstance->Ip4Proto,\r
795 NULL\r
796 );\r
797\r
798 goto ON_ERROR;\r
799 }\r
800\r
801 //\r
802 // Insert it into the service binding instance.\r
803 //\r
804 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
805\r
806 NetListInsertTail (&IpSb->Children, &IpInstance->Link);\r
807 IpSb->NumChildren++;\r
808\r
809 NET_RESTORE_TPL (OldTpl);\r
810\r
811ON_ERROR:\r
812\r
813 if (EFI_ERROR (Status)) {\r
814\r
815 Ip4CleanProtocol (IpInstance);\r
816\r
817 NetFreePool (IpInstance);\r
818 }\r
819\r
820 return Status;\r
821}\r
822\r
823\r
824/**\r
825 Destroys a child handle with a set of I/O services.\r
826\r
827 @param This Protocol instance pointer.\r
828 @param ChildHandle Handle of the child to destroy\r
829\r
830 @retval EFI_SUCCES The I/O services were removed from the child\r
831 handle\r
832 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
833 that are being removed\r
834 @retval EFI_INVALID_PARAMETER Child handle is not a valid EFI Handle.\r
835 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
836 its I/O services are being used.\r
837 @retval other The child handle was not destroyed\r
838\r
839**/\r
840EFI_STATUS\r
841EFIAPI\r
842Ip4ServiceBindingDestroyChild (\r
843 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
844 IN EFI_HANDLE ChildHandle\r
845 )\r
846{\r
847 EFI_STATUS Status;\r
848 IP4_SERVICE *IpSb;\r
849 IP4_PROTOCOL *IpInstance;\r
850 EFI_IP4_PROTOCOL *Ip4;\r
851 EFI_TPL OldTpl;\r
852 INTN State;\r
853\r
854 if ((This == NULL) || (ChildHandle == NULL)) {\r
855 return EFI_INVALID_PARAMETER;\r
856 }\r
857\r
858 //\r
859 // Retrieve the private context data structures\r
860 //\r
861 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
862\r
863 Status = gBS->OpenProtocol (\r
864 ChildHandle,\r
865 &gEfiIp4ProtocolGuid,\r
866 (VOID **) &Ip4,\r
867 gIp4DriverBinding.DriverBindingHandle,\r
868 ChildHandle,\r
869 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
870 );\r
871\r
872 if (EFI_ERROR (Status)) {\r
873 return EFI_UNSUPPORTED;\r
874 }\r
875\r
876 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
877\r
878 if (IpInstance->Service != IpSb) {\r
879 return EFI_INVALID_PARAMETER;\r
880 }\r
881\r
882 OldTpl = NET_RAISE_TPL (NET_TPL_LOCK);\r
883\r
884 //\r
885 // A child can be destoried more than once. For example,\r
886 // Ip4DriverBindingStop will destory all of its children.\r
887 // when UDP driver is being stopped, it will destory all\r
888 // the IP child it opens.\r
889 //\r
890 if (IpInstance->State == IP4_STATE_DESTORY) {\r
891 NET_RESTORE_TPL (OldTpl);\r
892 return EFI_SUCCESS;\r
893 }\r
894\r
895 State = IpInstance->State;\r
896 IpInstance->State = IP4_STATE_DESTORY;\r
897\r
898 //\r
899 // Close the Managed Network protocol.\r
900 //\r
901 gBS->CloseProtocol (\r
902 IpSb->MnpChildHandle,\r
903 &gEfiManagedNetworkProtocolGuid,\r
904 gIp4DriverBinding.DriverBindingHandle,\r
905 ChildHandle\r
906 );\r
907\r
908 //\r
909 // Uninstall the IP4 protocol first. Many thing happens during\r
910 // this:\r
911 // 1. The consumer of the IP4 protocol will be stopped if it\r
912 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
913 // stopped, IP driver's stop function will be called, and uninstall\r
914 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
915 // makes it possible to create the network stack bottom up, and\r
916 // stop it top down.\r
917 // 2. the upper layer will recycle the received packet. The recycle\r
918 // event's TPL is higher than this function. The recycle events\r
919 // will be called back before preceeding. If any packets not recycled,\r
920 // that means there is a resource leak.\r
921 //\r
922 Status = gBS->UninstallProtocolInterface (\r
923 ChildHandle,\r
924 &gEfiIp4ProtocolGuid,\r
925 &IpInstance->Ip4Proto\r
926 );\r
927\r
928 if (EFI_ERROR (Status)) {\r
929 goto ON_ERROR;\r
930 }\r
931\r
932 Status = Ip4CleanProtocol (IpInstance);\r
933\r
934 Ip4SetVariableData (IpSb);\r
935\r
936 if (EFI_ERROR (Status)) {\r
937 gBS->InstallMultipleProtocolInterfaces (\r
938 &ChildHandle,\r
939 &gEfiIp4ProtocolGuid,\r
940 Ip4,\r
941 NULL\r
942 );\r
943\r
944 goto ON_ERROR;\r
945 }\r
946\r
947 NetListRemoveEntry (&IpInstance->Link);\r
948 IpSb->NumChildren--;\r
949\r
950 NET_RESTORE_TPL (OldTpl);\r
951\r
952 NetFreePool (IpInstance);\r
953 return EFI_SUCCESS;\r
954\r
955ON_ERROR:\r
956 IpInstance->State = State;\r
957 NET_RESTORE_TPL (OldTpl);\r
958\r
959 return Status;\r
960}\r