]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg: Fix typos in comments and variables
[mirror_edk2.git] / MdeModulePkg / Universal / Network / Ip4Dxe / Ip4Driver.c
CommitLineData
772db4bb 1/** @file\r
3e8c18da 2 The driver binding and service binding protocol for IP4 driver.\r
e2851998 3\r
7648748e 4Copyright (c) 2005 - 2016, Intel Corporation. All rights reserved.<BR>\r
c79de074
SEHM
5(C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
6\r
e5eed7d3 7This program and the accompanying materials\r
772db4bb 8are licensed and made available under the terms and conditions of the BSD License\r
9which accompanies this distribution. The full text of the license may be found at\r
10http://opensource.org/licenses/bsd-license.php\r
11\r
12THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
772db4bb 15**/\r
16\r
17#include "Ip4Impl.h"\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gIp4DriverBinding = {\r
20 Ip4DriverBindingSupported,\r
21 Ip4DriverBindingStart,\r
22 Ip4DriverBindingStop,\r
23 0xa,\r
24 NULL,\r
25 NULL\r
26};\r
27\r
c79de074
SEHM
28BOOLEAN mIpSec2Installed = FALSE;\r
29\r
30/**\r
31 Callback function for IpSec2 Protocol install.\r
32\r
33 @param[in] Event Event whose notification function is being invoked\r
34 @param[in] Context Pointer to the notification function's context\r
35\r
36**/\r
37VOID\r
38EFIAPI\r
39IpSec2InstalledCallback (\r
40 IN EFI_EVENT Event,\r
41 IN VOID *Context\r
42 )\r
43{\r
44 //\r
45 // Close the event so it does not get called again.\r
46 //\r
47 gBS->CloseEvent (Event);\r
48\r
49 mIpSec2Installed = TRUE;\r
50}\r
51\r
5405e9a6 52/**\r
53 This is the declaration of an EFI image entry point. This entry point is\r
54 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
55 both device drivers and bus drivers.\r
e2851998 56\r
5405e9a6 57 The entry point for IP4 driver which install the driver\r
58 binding and component name protocol on its image.\r
59\r
3e8c18da 60 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
61 @param[in] SystemTable A pointer to the EFI System Table.\r
5405e9a6 62\r
63 @retval EFI_SUCCESS The operation completed successfully.\r
64 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
65\r
66**/\r
772db4bb 67EFI_STATUS\r
68EFIAPI\r
69Ip4DriverEntryPoint (\r
70 IN EFI_HANDLE ImageHandle,\r
71 IN EFI_SYSTEM_TABLE *SystemTable\r
72 )\r
772db4bb 73{\r
c79de074
SEHM
74 VOID *Registration;\r
75\r
76 EfiCreateProtocolNotifyEvent (\r
77 &gEfiIpSec2ProtocolGuid,\r
78 TPL_CALLBACK,\r
79 IpSec2InstalledCallback,\r
80 NULL,\r
81 &Registration\r
82 );\r
83\r
83cbd279 84 return EfiLibInstallDriverBindingComponentName2 (\r
772db4bb 85 ImageHandle,\r
86 SystemTable,\r
87 &gIp4DriverBinding,\r
88 ImageHandle,\r
89 &gIp4ComponentName,\r
83cbd279 90 &gIp4ComponentName2\r
772db4bb 91 );\r
92}\r
93\r
772db4bb 94/**\r
5405e9a6 95 Test to see if this driver supports ControllerHandle. This service\r
96 is called by the EFI boot service ConnectController(). In\r
97 order to make drivers as small as possible, there are a few calling\r
98 restrictions for this service. ConnectController() must\r
99 follow these calling restrictions. If any other agent wishes to call\r
100 Supported() it must also follow these calling restrictions.\r
101\r
3e8c18da 102 @param[in] This Protocol instance pointer.\r
103 @param[in] ControllerHandle Handle of device to test\r
104 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
105 device to start.\r
5405e9a6 106\r
107 @retval EFI_SUCCESS This driver supports this device\r
108 @retval EFI_ALREADY_STARTED This driver is already running on this device\r
109 @retval other This driver does not support this device\r
772db4bb 110\r
111**/\r
112EFI_STATUS\r
113EFIAPI\r
114Ip4DriverBindingSupported (\r
115 IN EFI_DRIVER_BINDING_PROTOCOL * This,\r
116 IN EFI_HANDLE ControllerHandle,\r
117 IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath OPTIONAL\r
118 )\r
119{\r
120 EFI_STATUS Status;\r
121\r
122 //\r
123 // Test for the MNP service binding Protocol\r
124 //\r
125 Status = gBS->OpenProtocol (\r
126 ControllerHandle,\r
127 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
128 NULL,\r
129 This->DriverBindingHandle,\r
130 ControllerHandle,\r
131 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
132 );\r
133\r
134 if (EFI_ERROR (Status)) {\r
135 return Status;\r
136 }\r
137\r
138 //\r
139 // Test for the Arp service binding Protocol\r
140 //\r
141 Status = gBS->OpenProtocol (\r
142 ControllerHandle,\r
143 &gEfiArpServiceBindingProtocolGuid,\r
144 NULL,\r
145 This->DriverBindingHandle,\r
146 ControllerHandle,\r
147 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
148 );\r
149\r
150 return Status;\r
151}\r
152\r
2ff29212 153/**\r
154 Clean up a IP4 service binding instance. It will release all\r
155 the resource allocated by the instance. The instance may be\r
156 partly initialized, or partly destroyed. If a resource is\r
75dce340 157 destroyed, it is marked as that in case the destroy failed and\r
2ff29212 158 being called again later.\r
159\r
1f6729ff 160 @param[in] IpSb The IP4 service binding instance to clean up\r
2ff29212 161\r
162 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
163 @retval other Failed to clean up some of the resources.\r
164\r
165**/\r
772db4bb 166EFI_STATUS\r
167Ip4CleanService (\r
168 IN IP4_SERVICE *IpSb\r
169 );\r
170\r
171\r
172/**\r
5405e9a6 173 Create a new IP4 driver service binding private instance.\r
772db4bb 174\r
3e8c18da 175 @param Controller The controller that has MNP service binding\r
176 installed\r
177 @param ImageHandle The IP4 driver's image handle\r
178 @param Service The variable to receive the newly created IP4\r
179 service.\r
772db4bb 180\r
181 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resource\r
182 @retval EFI_SUCCESS A new IP4 service binding private is created.\r
5405e9a6 183 @retval other Other error occurs.\r
772db4bb 184\r
185**/\r
772db4bb 186EFI_STATUS\r
187Ip4CreateService (\r
188 IN EFI_HANDLE Controller,\r
189 IN EFI_HANDLE ImageHandle,\r
190 OUT IP4_SERVICE **Service\r
191 )\r
192{\r
193 IP4_SERVICE *IpSb;\r
194 EFI_STATUS Status;\r
195\r
196 ASSERT (Service != NULL);\r
197\r
198 *Service = NULL;\r
199\r
200 //\r
201 // allocate a service private data then initialize all the filed to\r
202 // empty resources, so if any thing goes wrong when allocating\r
203 // resources, Ip4CleanService can be called to clean it up.\r
204 //\r
1f6729ff 205 IpSb = AllocateZeroPool (sizeof (IP4_SERVICE));\r
772db4bb 206\r
207 if (IpSb == NULL) {\r
208 return EFI_OUT_OF_RESOURCES;\r
209 }\r
210\r
211 IpSb->Signature = IP4_SERVICE_SIGNATURE;\r
212 IpSb->ServiceBinding.CreateChild = Ip4ServiceBindingCreateChild;\r
213 IpSb->ServiceBinding.DestroyChild = Ip4ServiceBindingDestroyChild;\r
214 IpSb->State = IP4_SERVICE_UNSTARTED;\r
772db4bb 215\r
216 IpSb->NumChildren = 0;\r
e48e37fc 217 InitializeListHead (&IpSb->Children);\r
772db4bb 218\r
e48e37fc 219 InitializeListHead (&IpSb->Interfaces);\r
772db4bb 220 IpSb->DefaultInterface = NULL;\r
221 IpSb->DefaultRouteTable = NULL;\r
222\r
223 Ip4InitAssembleTable (&IpSb->Assemble);\r
224\r
225 IpSb->IgmpCtrl.Igmpv1QuerySeen = 0;\r
e48e37fc 226 InitializeListHead (&IpSb->IgmpCtrl.Groups);\r
772db4bb 227\r
228 IpSb->Image = ImageHandle;\r
229 IpSb->Controller = Controller;\r
230\r
231 IpSb->MnpChildHandle = NULL;\r
232 IpSb->Mnp = NULL;\r
233\r
234 IpSb->MnpConfigData.ReceivedQueueTimeoutValue = 0;\r
235 IpSb->MnpConfigData.TransmitQueueTimeoutValue = 0;\r
236 IpSb->MnpConfigData.ProtocolTypeFilter = IP4_ETHER_PROTO;\r
237 IpSb->MnpConfigData.EnableUnicastReceive = TRUE;\r
238 IpSb->MnpConfigData.EnableMulticastReceive = TRUE;\r
239 IpSb->MnpConfigData.EnableBroadcastReceive = TRUE;\r
240 IpSb->MnpConfigData.EnablePromiscuousReceive = FALSE;\r
241 IpSb->MnpConfigData.FlushQueuesOnReset = TRUE;\r
242 IpSb->MnpConfigData.EnableReceiveTimestamps = FALSE;\r
243 IpSb->MnpConfigData.DisableBackgroundPolling = FALSE;\r
244\r
e48e37fc 245 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
772db4bb 246\r
1f6729ff 247 IpSb->Timer = NULL;\r
772db4bb 248\r
2c320007 249 IpSb->ReconfigEvent = NULL;\r
e371cc14
JW
250\r
251 IpSb->Reconfig = FALSE;\r
2c320007
JW
252 \r
253 IpSb->MediaPresent = TRUE;\r
254\r
772db4bb 255 //\r
256 // Create various resources. First create the route table, timer\r
7648748e 257 // event, ReconfigEvent and MNP child. IGMP, interface's initialization depend\r
772db4bb 258 // on the MNP child.\r
259 //\r
260 IpSb->DefaultRouteTable = Ip4CreateRouteTable ();\r
261\r
262 if (IpSb->DefaultRouteTable == NULL) {\r
263 Status = EFI_OUT_OF_RESOURCES;\r
264 goto ON_ERROR;\r
265 }\r
266\r
267 Status = gBS->CreateEvent (\r
268 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
e48e37fc 269 TPL_CALLBACK,\r
772db4bb 270 Ip4TimerTicking,\r
271 IpSb,\r
272 &IpSb->Timer\r
273 );\r
274\r
275 if (EFI_ERROR (Status)) {\r
276 goto ON_ERROR;\r
277 }\r
278\r
7648748e
JW
279 Status = gBS->CreateEvent (\r
280 EVT_NOTIFY_SIGNAL,\r
281 TPL_NOTIFY,\r
282 Ip4AutoReconfigCallBack,\r
283 IpSb,\r
284 &IpSb->ReconfigEvent\r
285 );\r
286 if (EFI_ERROR (Status)) {\r
287 goto ON_ERROR;\r
288 }\r
289\r
772db4bb 290 Status = NetLibCreateServiceChild (\r
291 Controller,\r
292 ImageHandle,\r
293 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
294 &IpSb->MnpChildHandle\r
295 );\r
296\r
297 if (EFI_ERROR (Status)) {\r
298 goto ON_ERROR;\r
299 }\r
300\r
301 Status = gBS->OpenProtocol (\r
302 IpSb->MnpChildHandle,\r
303 &gEfiManagedNetworkProtocolGuid,\r
304 (VOID **) &IpSb->Mnp,\r
305 ImageHandle,\r
306 Controller,\r
307 EFI_OPEN_PROTOCOL_BY_DRIVER\r
308 );\r
309\r
310 if (EFI_ERROR (Status)) {\r
311 goto ON_ERROR;\r
312 }\r
313\r
314 Status = Ip4ServiceConfigMnp (IpSb, TRUE);\r
315\r
316 if (EFI_ERROR (Status)) {\r
317 goto ON_ERROR;\r
318 }\r
319\r
320 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
321\r
322 if (EFI_ERROR (Status)) {\r
323 goto ON_ERROR;\r
324 }\r
325\r
326 Status = Ip4InitIgmp (IpSb);\r
327\r
328 if (EFI_ERROR (Status)) {\r
329 goto ON_ERROR;\r
330 }\r
331\r
1f6729ff 332 IpSb->MacString = NULL;\r
333 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
334 \r
335 if (EFI_ERROR (Status)) {\r
336 goto ON_ERROR;\r
337 }\r
338\r
772db4bb 339 IpSb->DefaultInterface = Ip4CreateInterface (IpSb->Mnp, Controller, ImageHandle);\r
340\r
341 if (IpSb->DefaultInterface == NULL) {\r
342 Status = EFI_OUT_OF_RESOURCES;\r
343 goto ON_ERROR;\r
344 }\r
345\r
e48e37fc 346 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
772db4bb 347\r
1f6729ff 348 ZeroMem (&IpSb->Ip4Config2Instance, sizeof (IP4_CONFIG2_INSTANCE));\r
349 \r
350 Status = Ip4Config2InitInstance (&IpSb->Ip4Config2Instance);\r
351\r
352 if (EFI_ERROR (Status)) {\r
353 goto ON_ERROR;\r
354 }\r
355\r
a1503a32 356 IpSb->MaxPacketSize = IpSb->SnpMode.MaxPacketSize - sizeof (IP4_HEAD);\r
779ae357 357 if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
358 //\r
359 // This is a VLAN device, reduce MTU by VLAN tag length\r
360 //\r
361 IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
362 }\r
9e375eb1 363 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
772db4bb 364 *Service = IpSb;\r
1f6729ff 365\r
772db4bb 366 return EFI_SUCCESS;\r
367\r
368ON_ERROR:\r
369 Ip4CleanService (IpSb);\r
766c7483 370 FreePool (IpSb);\r
772db4bb 371\r
372 return Status;\r
373}\r
374\r
375\r
376/**\r
377 Clean up a IP4 service binding instance. It will release all\r
378 the resource allocated by the instance. The instance may be\r
5405e9a6 379 partly initialized, or partly destroyed. If a resource is\r
75dce340 380 destroyed, it is marked as that in case the destroy failed and\r
772db4bb 381 being called again later.\r
382\r
1f6729ff 383 @param[in] IpSb The IP4 service binding instance to clean up\r
772db4bb 384\r
385 @retval EFI_SUCCESS The resource used by the instance are cleaned up\r
5405e9a6 386 @retval other Failed to clean up some of the resources.\r
772db4bb 387\r
388**/\r
389EFI_STATUS\r
390Ip4CleanService (\r
391 IN IP4_SERVICE *IpSb\r
392 )\r
393{\r
394 EFI_STATUS Status;\r
395\r
524813f3
FS
396 IpSb->State = IP4_SERVICE_DESTROY;\r
397\r
398 if (IpSb->Timer != NULL) {\r
399 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
400 gBS->CloseEvent (IpSb->Timer);\r
401\r
402 IpSb->Timer = NULL;\r
403 }\r
404\r
772db4bb 405 if (IpSb->DefaultInterface != NULL) {\r
406 Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
407\r
408 if (EFI_ERROR (Status)) {\r
409 return Status;\r
410 }\r
411\r
412 IpSb->DefaultInterface = NULL;\r
413 }\r
414\r
415 if (IpSb->DefaultRouteTable != NULL) {\r
416 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
417 IpSb->DefaultRouteTable = NULL;\r
418 }\r
419\r
420 Ip4CleanAssembleTable (&IpSb->Assemble);\r
421\r
422 if (IpSb->MnpChildHandle != NULL) {\r
5405e9a6 423 if (IpSb->Mnp != NULL) {\r
772db4bb 424 gBS->CloseProtocol (\r
5405e9a6 425 IpSb->MnpChildHandle,\r
426 &gEfiManagedNetworkProtocolGuid,\r
427 IpSb->Image,\r
428 IpSb->Controller\r
429 );\r
772db4bb 430\r
431 IpSb->Mnp = NULL;\r
432 }\r
433\r
434 NetLibDestroyServiceChild (\r
435 IpSb->Controller,\r
436 IpSb->Image,\r
437 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
438 IpSb->MnpChildHandle\r
439 );\r
440\r
441 IpSb->MnpChildHandle = NULL;\r
442 }\r
443\r
2c320007
JW
444 if (IpSb->ReconfigEvent != NULL) {\r
445 gBS->CloseEvent (IpSb->ReconfigEvent);\r
446\r
447 IpSb->ReconfigEvent = NULL;\r
448 }\r
449\r
e371cc14
JW
450 IpSb->Reconfig = FALSE;\r
451\r
1f6729ff 452 if (IpSb->MacString != NULL) {\r
453 FreePool (IpSb->MacString);\r
772db4bb 454 }\r
455\r
1f6729ff 456 Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
457\r
772db4bb 458 return EFI_SUCCESS;\r
459}\r
460\r
216f7970 461/**\r
462 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
463 \r
464 @param[in] Entry The entry to be removed.\r
465 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
466\r
467 @retval EFI_SUCCESS The entry has been removed successfully.\r
468 @retval Others Fail to remove the entry.\r
469\r
470**/\r
471EFI_STATUS\r
1f7eb561 472EFIAPI\r
216f7970 473Ip4DestroyChildEntryInHandleBuffer (\r
474 IN LIST_ENTRY *Entry,\r
475 IN VOID *Context\r
1f7eb561 476 )\r
216f7970 477{\r
478 IP4_PROTOCOL *IpInstance;\r
479 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
480 UINTN NumberOfChildren;\r
481 EFI_HANDLE *ChildHandleBuffer;\r
482\r
483 if (Entry == NULL || Context == NULL) {\r
484 return EFI_INVALID_PARAMETER;\r
485 }\r
486\r
487 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
488 ServiceBinding = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
489 NumberOfChildren = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
490 ChildHandleBuffer = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
491\r
492 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
493 return EFI_SUCCESS;\r
494 }\r
495\r
496 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
497}\r
772db4bb 498\r
499/**\r
5405e9a6 500 Start this driver on ControllerHandle. This service is called by the\r
501 EFI boot service ConnectController(). In order to make\r
502 drivers as small as possible, there are a few calling restrictions for\r
503 this service. ConnectController() must follow these\r
504 calling restrictions. If any other agent wishes to call Start() it\r
505 must also follow these calling restrictions.\r
506\r
3e8c18da 507 @param[in] This Protocol instance pointer.\r
508 @param[in] ControllerHandle Handle of device to bind driver to\r
509 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
510 device to start.\r
5405e9a6 511\r
512 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
513 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
514 @retval other This driver does not support this device\r
772db4bb 515\r
516**/\r
517EFI_STATUS\r
518EFIAPI\r
519Ip4DriverBindingStart (\r
1f6729ff 520 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
772db4bb 521 IN EFI_HANDLE ControllerHandle,\r
1f6729ff 522 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
772db4bb 523 )\r
1f6729ff 524{ \r
525 EFI_STATUS Status;\r
526 IP4_SERVICE *IpSb;\r
7648748e
JW
527 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;\r
528 UINTN Index;\r
529 IP4_CONFIG2_DATA_ITEM *DataItem;\r
530\r
531 IpSb = NULL;\r
532 Ip4Cfg2 = NULL;\r
533 DataItem = NULL;\r
772db4bb 534\r
535 //\r
536 // Test for the Ip4 service binding protocol\r
537 //\r
538 Status = gBS->OpenProtocol (\r
539 ControllerHandle,\r
540 &gEfiIp4ServiceBindingProtocolGuid,\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 return EFI_ALREADY_STARTED;\r
549 }\r
1f6729ff 550 \r
772db4bb 551 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
1f6729ff 552 \r
772db4bb 553 if (EFI_ERROR (Status)) {\r
554 return Status;\r
555 }\r
1f6729ff 556 \r
e2851998 557 ASSERT (IpSb != NULL);\r
772db4bb 558\r
7648748e
JW
559 Ip4Cfg2 = &IpSb->Ip4Config2Instance.Ip4Config2;\r
560\r
772db4bb 561 //\r
562 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
563 //\r
564 Status = gBS->InstallMultipleProtocolInterfaces (\r
565 &ControllerHandle,\r
566 &gEfiIp4ServiceBindingProtocolGuid,\r
567 &IpSb->ServiceBinding,\r
1f6729ff 568 &gEfiIp4Config2ProtocolGuid,\r
7648748e 569 Ip4Cfg2,\r
772db4bb 570 NULL\r
571 );\r
572\r
573 if (EFI_ERROR (Status)) {\r
574 goto FREE_SERVICE;\r
575 }\r
7648748e
JW
576\r
577 //\r
578 // Read the config data from NV variable again. \r
579 // The default data can be changed by other drivers.\r
580 //\r
581 Status = Ip4Config2ReadConfigData (IpSb->MacString, &IpSb->Ip4Config2Instance);\r
582 if (EFI_ERROR (Status)) {\r
583 goto UNINSTALL_PROTOCOL;\r
584 }\r
585 \r
586 //\r
587 // Consume the installed EFI_IP4_CONFIG2_PROTOCOL to set the default data items. \r
588 //\r
589 for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
590 DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
591 if (DataItem->Data.Ptr != NULL) {\r
592 Status = Ip4Cfg2->SetData (\r
593 Ip4Cfg2,\r
594 Index,\r
595 DataItem->DataSize,\r
596 DataItem->Data.Ptr\r
597 );\r
598 if (EFI_ERROR(Status)) {\r
599 goto UNINSTALL_PROTOCOL;\r
600 }\r
eab40164
JW
601 \r
602 if (Index == Ip4Config2DataTypePolicy && (*(DataItem->Data.Policy) == Ip4Config2PolicyDhcp)) {\r
603 break;\r
604 } \r
7648748e
JW
605 }\r
606 }\r
1f6729ff 607 \r
772db4bb 608 //\r
1f6729ff 609 // Ready to go: start the receiving and timer.\r
610 // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
611 // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
772db4bb 612 //\r
613 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
614\r
1f6729ff 615 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
772db4bb 616 goto UNINSTALL_PROTOCOL;\r
617 }\r
618\r
619 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
620\r
621 if (EFI_ERROR (Status)) {\r
622 goto UNINSTALL_PROTOCOL;\r
623 }\r
624\r
625 //\r
626 // Initialize the IP4 ID\r
627 //\r
628 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
629\r
772db4bb 630 return Status;\r
631\r
632UNINSTALL_PROTOCOL:\r
633 gBS->UninstallProtocolInterface (\r
634 ControllerHandle,\r
635 &gEfiIp4ServiceBindingProtocolGuid,\r
636 &IpSb->ServiceBinding\r
637 );\r
638\r
639FREE_SERVICE:\r
640 Ip4CleanService (IpSb);\r
766c7483 641 FreePool (IpSb);\r
772db4bb 642 return Status;\r
643}\r
644\r
645\r
646/**\r
5405e9a6 647 Stop this driver on ControllerHandle. This service is called by the\r
648 EFI boot service DisconnectController(). In order to\r
649 make drivers as small as possible, there are a few calling\r
650 restrictions for this service. DisconnectController()\r
651 must follow these calling restrictions. If any other agent wishes\r
652 to call Stop() it must also follow these calling restrictions.\r
e2851998 653\r
3e8c18da 654 @param[in] This Protocol instance pointer.\r
655 @param[in] ControllerHandle Handle of device to stop driver on\r
656 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
657 of children is zero stop the entire bus driver.\r
658 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
5405e9a6 659\r
3e8c18da 660 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
661 @retval other This driver was not removed from this device\r
772db4bb 662\r
663**/\r
664EFI_STATUS\r
665EFIAPI\r
666Ip4DriverBindingStop (\r
667 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
668 IN EFI_HANDLE ControllerHandle,\r
669 IN UINTN NumberOfChildren,\r
670 IN EFI_HANDLE *ChildHandleBuffer\r
671 )\r
672{\r
216f7970 673 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
674 IP4_SERVICE *IpSb; \r
675 EFI_HANDLE NicHandle;\r
676 EFI_STATUS Status; \r
677 INTN State;\r
678 LIST_ENTRY *List;\r
679 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
d0ccf55e 680 IP4_INTERFACE *IpIf;\r
681 IP4_ROUTE_TABLE *RouteTable;\r
772db4bb 682\r
1f6729ff 683 BOOLEAN IsDhcp4;\r
772db4bb 684\r
1f6729ff 685 IsDhcp4 = FALSE;\r
686 \r
772db4bb 687 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
772db4bb 688 if (NicHandle == NULL) {\r
689 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
216f7970 690 if (NicHandle == NULL) {\r
1f6729ff 691 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
692 if (NicHandle != NULL) {\r
693 IsDhcp4 = TRUE; \r
694 } else {\r
695 return EFI_SUCCESS;\r
696 }\r
216f7970 697 }\r
772db4bb 698 }\r
1f6729ff 699 \r
772db4bb 700 Status = gBS->OpenProtocol (\r
701 NicHandle,\r
702 &gEfiIp4ServiceBindingProtocolGuid,\r
703 (VOID **) &ServiceBinding,\r
704 This->DriverBindingHandle,\r
705 NicHandle,\r
706 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
707 );\r
772db4bb 708 if (EFI_ERROR (Status)) {\r
709 return EFI_DEVICE_ERROR;\r
710 }\r
1f6729ff 711 \r
712 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
772db4bb 713\r
1f6729ff 714 if (IsDhcp4) {\r
715 Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
716 gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
717 IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
718 } else if (NumberOfChildren != 0) {\r
216f7970 719 List = &IpSb->Children;\r
720 Context.ServiceBinding = ServiceBinding;\r
721 Context.NumberOfChildren = NumberOfChildren;\r
722 Context.ChildHandleBuffer = ChildHandleBuffer;\r
723 Status = NetDestroyLinkList (\r
724 List,\r
725 Ip4DestroyChildEntryInHandleBuffer,\r
726 &Context,\r
727 NULL\r
728 );\r
d0ccf55e 729 } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
1f6729ff 730 \r
d0ccf55e 731 //\r
732 // The ARP protocol for the default interface is being uninstalled and all\r
733 // its IP child handles should have been destroyed before. So, release the\r
734 // default interface and route table, create a new one and mark it as not started.\r
735 //\r
736 Ip4CancelReceive (IpSb->DefaultInterface);\r
737 Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
738 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
739 \r
740 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
741 if (IpIf == NULL) {\r
742 goto ON_ERROR;\r
743 }\r
744 RouteTable = Ip4CreateRouteTable ();\r
745 if (RouteTable == NULL) {\r
746 Ip4FreeInterface (IpIf, NULL);\r
747 goto ON_ERROR;;\r
748 }\r
749 \r
750 IpSb->DefaultInterface = IpIf;\r
751 InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
752 IpSb->DefaultRouteTable = RouteTable;\r
753 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
754\r
d0ccf55e 755 IpSb->State = IP4_SERVICE_UNSTARTED;\r
1f6729ff 756\r
216f7970 757 } else if (IsListEmpty (&IpSb->Children)) {\r
c4a62a12 758 State = IpSb->State;\r
c4a62a12 759 //\r
760 // OK, clean other resources then uninstall the service binding protocol.\r
761 //\r
762 Status = Ip4CleanService (IpSb);\r
c4a62a12 763 if (EFI_ERROR (Status)) {\r
764 IpSb->State = State;\r
765 goto ON_ERROR;\r
766 }\r
772db4bb 767\r
1f6729ff 768 gBS->UninstallMultipleProtocolInterfaces (\r
c4a62a12 769 NicHandle,\r
770 &gEfiIp4ServiceBindingProtocolGuid,\r
1f6729ff 771 ServiceBinding,\r
772 &gEfiIp4Config2ProtocolGuid,\r
773 &IpSb->Ip4Config2Instance.Ip4Config2,\r
774 NULL\r
c4a62a12 775 );\r
216f7970 776 \r
777 if (gIp4ControllerNameTable != NULL) {\r
778 FreeUnicodeStringTable (gIp4ControllerNameTable);\r
779 gIp4ControllerNameTable = NULL;\r
c4a62a12 780 }\r
766c7483 781 FreePool (IpSb);\r
c4a62a12 782 }\r
772db4bb 783\r
784ON_ERROR:\r
772db4bb 785 return Status;\r
786}\r
787\r
788\r
789/**\r
3e8c18da 790 Creates a child handle and installs a protocol.\r
e2851998 791\r
792 The CreateChild() function installs a protocol on ChildHandle.\r
793 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
3e8c18da 794 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
772db4bb 795\r
3e8c18da 796 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
797 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
e2851998 798 then a new handle is created. If it is a pointer to an existing UEFI handle,\r
3e8c18da 799 then the protocol is added to the existing UEFI handle.\r
772db4bb 800\r
3e8c18da 801 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
5405e9a6 802 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
2048c585 803 @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create\r
5405e9a6 804 the child\r
805 @retval other The child handle was not created\r
772db4bb 806\r
807**/\r
808EFI_STATUS\r
809EFIAPI\r
810Ip4ServiceBindingCreateChild (\r
811 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
5405e9a6 812 IN OUT EFI_HANDLE *ChildHandle\r
772db4bb 813 )\r
814{\r
815 IP4_SERVICE *IpSb;\r
816 IP4_PROTOCOL *IpInstance;\r
817 EFI_TPL OldTpl;\r
818 EFI_STATUS Status;\r
819 VOID *Mnp;\r
820\r
821 if ((This == NULL) || (ChildHandle == NULL)) {\r
822 return EFI_INVALID_PARAMETER;\r
823 }\r
824\r
825 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 826 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 827\r
828 if (IpInstance == NULL) {\r
829 return EFI_OUT_OF_RESOURCES;\r
830 }\r
831\r
832 Ip4InitProtocol (IpSb, IpInstance);\r
833\r
834 //\r
835 // Install Ip4 onto ChildHandle\r
836 //\r
837 Status = gBS->InstallMultipleProtocolInterfaces (\r
838 ChildHandle,\r
839 &gEfiIp4ProtocolGuid,\r
840 &IpInstance->Ip4Proto,\r
841 NULL\r
842 );\r
843\r
844 if (EFI_ERROR (Status)) {\r
845 goto ON_ERROR;\r
846 }\r
847\r
848 IpInstance->Handle = *ChildHandle;\r
849\r
850 //\r
851 // Open the Managed Network protocol BY_CHILD.\r
852 //\r
853 Status = gBS->OpenProtocol (\r
854 IpSb->MnpChildHandle,\r
855 &gEfiManagedNetworkProtocolGuid,\r
856 (VOID **) &Mnp,\r
857 gIp4DriverBinding.DriverBindingHandle,\r
858 IpInstance->Handle,\r
859 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
860 );\r
861 if (EFI_ERROR (Status)) {\r
862 gBS->UninstallMultipleProtocolInterfaces (\r
863 ChildHandle,\r
864 &gEfiIp4ProtocolGuid,\r
865 &IpInstance->Ip4Proto,\r
866 NULL\r
867 );\r
868\r
869 goto ON_ERROR;\r
870 }\r
871\r
872 //\r
873 // Insert it into the service binding instance.\r
874 //\r
e48e37fc 875 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 876\r
e48e37fc 877 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 878 IpSb->NumChildren++;\r
879\r
e48e37fc 880 gBS->RestoreTPL (OldTpl);\r
772db4bb 881\r
882ON_ERROR:\r
883\r
884 if (EFI_ERROR (Status)) {\r
885\r
886 Ip4CleanProtocol (IpInstance);\r
887\r
766c7483 888 FreePool (IpInstance);\r
772db4bb 889 }\r
890\r
891 return Status;\r
892}\r
893\r
894\r
895/**\r
3e8c18da 896 Destroys a child handle with a protocol installed on it.\r
e2851998 897\r
898 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
899 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
3e8c18da 900 last protocol on ChildHandle, then ChildHandle is destroyed.\r
772db4bb 901\r
3e8c18da 902 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
5405e9a6 903 @param ChildHandle Handle of the child to destroy\r
904\r
3e8c18da 905 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
906 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
284ee2e8 907 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
3e8c18da 908 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
909 because its services are being used.\r
5405e9a6 910 @retval other The child handle was not destroyed\r
772db4bb 911\r
912**/\r
913EFI_STATUS\r
914EFIAPI\r
915Ip4ServiceBindingDestroyChild (\r
916 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
917 IN EFI_HANDLE ChildHandle\r
918 )\r
919{\r
920 EFI_STATUS Status;\r
921 IP4_SERVICE *IpSb;\r
922 IP4_PROTOCOL *IpInstance;\r
923 EFI_IP4_PROTOCOL *Ip4;\r
924 EFI_TPL OldTpl;\r
925 INTN State;\r
926\r
927 if ((This == NULL) || (ChildHandle == NULL)) {\r
928 return EFI_INVALID_PARAMETER;\r
929 }\r
930\r
931 //\r
932 // Retrieve the private context data structures\r
933 //\r
934 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
935\r
936 Status = gBS->OpenProtocol (\r
937 ChildHandle,\r
938 &gEfiIp4ProtocolGuid,\r
939 (VOID **) &Ip4,\r
940 gIp4DriverBinding.DriverBindingHandle,\r
941 ChildHandle,\r
942 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
943 );\r
944\r
945 if (EFI_ERROR (Status)) {\r
946 return EFI_UNSUPPORTED;\r
947 }\r
948\r
949 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
950\r
951 if (IpInstance->Service != IpSb) {\r
952 return EFI_INVALID_PARAMETER;\r
953 }\r
954\r
e48e37fc 955 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 956\r
957 //\r
75dce340 958 // A child can be destroyed more than once. For example,\r
959 // Ip4DriverBindingStop will destroy all of its children.\r
960 // when UDP driver is being stopped, it will destroy all\r
772db4bb 961 // the IP child it opens.\r
962 //\r
75dce340 963 if (IpInstance->State == IP4_STATE_DESTROY) {\r
e48e37fc 964 gBS->RestoreTPL (OldTpl);\r
772db4bb 965 return EFI_SUCCESS;\r
966 }\r
967\r
968 State = IpInstance->State;\r
75dce340 969 IpInstance->State = IP4_STATE_DESTROY;\r
772db4bb 970\r
971 //\r
972 // Close the Managed Network protocol.\r
973 //\r
974 gBS->CloseProtocol (\r
975 IpSb->MnpChildHandle,\r
976 &gEfiManagedNetworkProtocolGuid,\r
977 gIp4DriverBinding.DriverBindingHandle,\r
978 ChildHandle\r
979 );\r
980\r
216f7970 981 if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {\r
982 gBS->CloseProtocol (\r
983 IpInstance->Interface->ArpHandle,\r
984 &gEfiArpProtocolGuid,\r
985 gIp4DriverBinding.DriverBindingHandle,\r
986 ChildHandle\r
987 );\r
988 }\r
989\r
772db4bb 990 //\r
991 // Uninstall the IP4 protocol first. Many thing happens during\r
992 // this:\r
993 // 1. The consumer of the IP4 protocol will be stopped if it\r
994 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
995 // stopped, IP driver's stop function will be called, and uninstall\r
996 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
997 // makes it possible to create the network stack bottom up, and\r
998 // stop it top down.\r
999 // 2. the upper layer will recycle the received packet. The recycle\r
1000 // event's TPL is higher than this function. The recycle events\r
1001 // will be called back before preceeding. If any packets not recycled,\r
1002 // that means there is a resource leak.\r
1003 //\r
216f7970 1004 gBS->RestoreTPL (OldTpl);\r
772db4bb 1005 Status = gBS->UninstallProtocolInterface (\r
1006 ChildHandle,\r
1007 &gEfiIp4ProtocolGuid,\r
1008 &IpInstance->Ip4Proto\r
1009 );\r
216f7970 1010 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1011 if (EFI_ERROR (Status)) {\r
1012 goto ON_ERROR;\r
1013 }\r
1014\r
1015 Status = Ip4CleanProtocol (IpInstance);\r
772db4bb 1016 if (EFI_ERROR (Status)) {\r
1017 gBS->InstallMultipleProtocolInterfaces (\r
1018 &ChildHandle,\r
1019 &gEfiIp4ProtocolGuid,\r
1020 Ip4,\r
1021 NULL\r
1022 );\r
1023\r
1024 goto ON_ERROR;\r
1025 }\r
1026\r
e48e37fc 1027 RemoveEntryList (&IpInstance->Link);\r
772db4bb 1028 IpSb->NumChildren--;\r
1029\r
e48e37fc 1030 gBS->RestoreTPL (OldTpl);\r
772db4bb 1031\r
766c7483 1032 FreePool (IpInstance);\r
772db4bb 1033 return EFI_SUCCESS;\r
1034\r
1035ON_ERROR:\r
1036 IpInstance->State = State;\r
e48e37fc 1037 gBS->RestoreTPL (OldTpl);\r
772db4bb 1038\r
1039 return Status;\r
1040}\r