]> git.proxmox.com Git - mirror_edk2.git/blame - MdeModulePkg/Universal/Network/Ip4Dxe/Ip4Driver.c
MdeModulePkg: Change the default IPv4 config policy
[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
396 if (IpSb->DefaultInterface != NULL) {\r
397 Status = Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
398\r
399 if (EFI_ERROR (Status)) {\r
400 return Status;\r
401 }\r
402\r
403 IpSb->DefaultInterface = NULL;\r
404 }\r
405\r
406 if (IpSb->DefaultRouteTable != NULL) {\r
407 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
408 IpSb->DefaultRouteTable = NULL;\r
409 }\r
410\r
411 Ip4CleanAssembleTable (&IpSb->Assemble);\r
412\r
413 if (IpSb->MnpChildHandle != NULL) {\r
5405e9a6 414 if (IpSb->Mnp != NULL) {\r
772db4bb 415 gBS->CloseProtocol (\r
5405e9a6 416 IpSb->MnpChildHandle,\r
417 &gEfiManagedNetworkProtocolGuid,\r
418 IpSb->Image,\r
419 IpSb->Controller\r
420 );\r
772db4bb 421\r
422 IpSb->Mnp = NULL;\r
423 }\r
424\r
425 NetLibDestroyServiceChild (\r
426 IpSb->Controller,\r
427 IpSb->Image,\r
428 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
429 IpSb->MnpChildHandle\r
430 );\r
431\r
432 IpSb->MnpChildHandle = NULL;\r
433 }\r
434\r
435 if (IpSb->Timer != NULL) {\r
436 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
437 gBS->CloseEvent (IpSb->Timer);\r
438\r
439 IpSb->Timer = NULL;\r
440 }\r
441\r
2c320007
JW
442 if (IpSb->ReconfigEvent != NULL) {\r
443 gBS->CloseEvent (IpSb->ReconfigEvent);\r
444\r
445 IpSb->ReconfigEvent = NULL;\r
446 }\r
447\r
e371cc14
JW
448 IpSb->Reconfig = FALSE;\r
449\r
1f6729ff 450 if (IpSb->MacString != NULL) {\r
451 FreePool (IpSb->MacString);\r
772db4bb 452 }\r
453\r
1f6729ff 454 Ip4Config2CleanInstance (&IpSb->Ip4Config2Instance);\r
455\r
772db4bb 456 return EFI_SUCCESS;\r
457}\r
458\r
216f7970 459/**\r
460 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
461 \r
462 @param[in] Entry The entry to be removed.\r
463 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
464\r
465 @retval EFI_SUCCESS The entry has been removed successfully.\r
466 @retval Others Fail to remove the entry.\r
467\r
468**/\r
469EFI_STATUS\r
1f7eb561 470EFIAPI\r
216f7970 471Ip4DestroyChildEntryInHandleBuffer (\r
472 IN LIST_ENTRY *Entry,\r
473 IN VOID *Context\r
1f7eb561 474 )\r
216f7970 475{\r
476 IP4_PROTOCOL *IpInstance;\r
477 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
478 UINTN NumberOfChildren;\r
479 EFI_HANDLE *ChildHandleBuffer;\r
480\r
481 if (Entry == NULL || Context == NULL) {\r
482 return EFI_INVALID_PARAMETER;\r
483 }\r
484\r
485 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP4_PROTOCOL, Link, IP4_PROTOCOL_SIGNATURE);\r
486 ServiceBinding = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
487 NumberOfChildren = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
488 ChildHandleBuffer = ((IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
489\r
490 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
491 return EFI_SUCCESS;\r
492 }\r
493\r
494 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
495}\r
772db4bb 496\r
497/**\r
5405e9a6 498 Start this driver on ControllerHandle. This service is called by the\r
499 EFI boot service ConnectController(). In order to make\r
500 drivers as small as possible, there are a few calling restrictions for\r
501 this service. ConnectController() must follow these\r
502 calling restrictions. If any other agent wishes to call Start() it\r
503 must also follow these calling restrictions.\r
504\r
3e8c18da 505 @param[in] This Protocol instance pointer.\r
506 @param[in] ControllerHandle Handle of device to bind driver to\r
507 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
508 device to start.\r
5405e9a6 509\r
510 @retval EFI_SUCCESS This driver is added to ControllerHandle\r
511 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle\r
512 @retval other This driver does not support this device\r
772db4bb 513\r
514**/\r
515EFI_STATUS\r
516EFIAPI\r
517Ip4DriverBindingStart (\r
1f6729ff 518 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
772db4bb 519 IN EFI_HANDLE ControllerHandle,\r
1f6729ff 520 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
772db4bb 521 )\r
1f6729ff 522{ \r
523 EFI_STATUS Status;\r
524 IP4_SERVICE *IpSb;\r
7648748e
JW
525 EFI_IP4_CONFIG2_PROTOCOL *Ip4Cfg2;\r
526 UINTN Index;\r
527 IP4_CONFIG2_DATA_ITEM *DataItem;\r
528\r
529 IpSb = NULL;\r
530 Ip4Cfg2 = NULL;\r
531 DataItem = NULL;\r
772db4bb 532\r
533 //\r
534 // Test for the Ip4 service binding protocol\r
535 //\r
536 Status = gBS->OpenProtocol (\r
537 ControllerHandle,\r
538 &gEfiIp4ServiceBindingProtocolGuid,\r
539 NULL,\r
540 This->DriverBindingHandle,\r
541 ControllerHandle,\r
542 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
543 );\r
544\r
545 if (Status == EFI_SUCCESS) {\r
546 return EFI_ALREADY_STARTED;\r
547 }\r
1f6729ff 548 \r
772db4bb 549 Status = Ip4CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
1f6729ff 550 \r
772db4bb 551 if (EFI_ERROR (Status)) {\r
552 return Status;\r
553 }\r
1f6729ff 554 \r
e2851998 555 ASSERT (IpSb != NULL);\r
772db4bb 556\r
7648748e
JW
557 Ip4Cfg2 = &IpSb->Ip4Config2Instance.Ip4Config2;\r
558\r
772db4bb 559 //\r
560 // Install the Ip4ServiceBinding Protocol onto ControlerHandle\r
561 //\r
562 Status = gBS->InstallMultipleProtocolInterfaces (\r
563 &ControllerHandle,\r
564 &gEfiIp4ServiceBindingProtocolGuid,\r
565 &IpSb->ServiceBinding,\r
1f6729ff 566 &gEfiIp4Config2ProtocolGuid,\r
7648748e 567 Ip4Cfg2,\r
772db4bb 568 NULL\r
569 );\r
570\r
571 if (EFI_ERROR (Status)) {\r
572 goto FREE_SERVICE;\r
573 }\r
7648748e
JW
574\r
575 //\r
576 // Read the config data from NV variable again. \r
577 // The default data can be changed by other drivers.\r
578 //\r
579 Status = Ip4Config2ReadConfigData (IpSb->MacString, &IpSb->Ip4Config2Instance);\r
580 if (EFI_ERROR (Status)) {\r
581 goto UNINSTALL_PROTOCOL;\r
582 }\r
583 \r
584 //\r
585 // Consume the installed EFI_IP4_CONFIG2_PROTOCOL to set the default data items. \r
586 //\r
587 for (Index = Ip4Config2DataTypePolicy; Index < Ip4Config2DataTypeMaximum; Index++) {\r
588 DataItem = &IpSb->Ip4Config2Instance.DataItem[Index];\r
589 if (DataItem->Data.Ptr != NULL) {\r
590 Status = Ip4Cfg2->SetData (\r
591 Ip4Cfg2,\r
592 Index,\r
593 DataItem->DataSize,\r
594 DataItem->Data.Ptr\r
595 );\r
596 if (EFI_ERROR(Status)) {\r
597 goto UNINSTALL_PROTOCOL;\r
598 }\r
599 }\r
600 }\r
1f6729ff 601 \r
772db4bb 602 //\r
1f6729ff 603 // Ready to go: start the receiving and timer.\r
604 // Ip4Config2SetPolicy maybe call Ip4ReceiveFrame() to set the default interface's RecvRequest first after\r
605 // Ip4Config2 instance is initialized. So, EFI_ALREADY_STARTED is the allowed return status.\r
772db4bb 606 //\r
607 Status = Ip4ReceiveFrame (IpSb->DefaultInterface, NULL, Ip4AccpetFrame, IpSb);\r
608\r
1f6729ff 609 if (EFI_ERROR (Status) && Status != EFI_ALREADY_STARTED) {\r
772db4bb 610 goto UNINSTALL_PROTOCOL;\r
611 }\r
612\r
613 Status = gBS->SetTimer (IpSb->Timer, TimerPeriodic, TICKS_PER_SECOND);\r
614\r
615 if (EFI_ERROR (Status)) {\r
616 goto UNINSTALL_PROTOCOL;\r
617 }\r
618\r
619 //\r
620 // Initialize the IP4 ID\r
621 //\r
622 mIp4Id = (UINT16)NET_RANDOM (NetRandomInitSeed ());\r
623\r
772db4bb 624 return Status;\r
625\r
626UNINSTALL_PROTOCOL:\r
627 gBS->UninstallProtocolInterface (\r
628 ControllerHandle,\r
629 &gEfiIp4ServiceBindingProtocolGuid,\r
630 &IpSb->ServiceBinding\r
631 );\r
632\r
633FREE_SERVICE:\r
634 Ip4CleanService (IpSb);\r
766c7483 635 FreePool (IpSb);\r
772db4bb 636 return Status;\r
637}\r
638\r
639\r
640/**\r
5405e9a6 641 Stop this driver on ControllerHandle. This service is called by the\r
642 EFI boot service DisconnectController(). In order to\r
643 make drivers as small as possible, there are a few calling\r
644 restrictions for this service. DisconnectController()\r
645 must follow these calling restrictions. If any other agent wishes\r
646 to call Stop() it must also follow these calling restrictions.\r
e2851998 647\r
3e8c18da 648 @param[in] This Protocol instance pointer.\r
649 @param[in] ControllerHandle Handle of device to stop driver on\r
650 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
651 of children is zero stop the entire bus driver.\r
652 @param[in] ChildHandleBuffer List of Child Handles to Stop.\r
5405e9a6 653\r
3e8c18da 654 @retval EFI_SUCCESS This driver is removed ControllerHandle\r
655 @retval other This driver was not removed from this device\r
772db4bb 656\r
657**/\r
658EFI_STATUS\r
659EFIAPI\r
660Ip4DriverBindingStop (\r
661 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
662 IN EFI_HANDLE ControllerHandle,\r
663 IN UINTN NumberOfChildren,\r
664 IN EFI_HANDLE *ChildHandleBuffer\r
665 )\r
666{\r
216f7970 667 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
668 IP4_SERVICE *IpSb; \r
669 EFI_HANDLE NicHandle;\r
670 EFI_STATUS Status; \r
671 INTN State;\r
672 LIST_ENTRY *List;\r
673 IP4_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
d0ccf55e 674 IP4_INTERFACE *IpIf;\r
675 IP4_ROUTE_TABLE *RouteTable;\r
772db4bb 676\r
1f6729ff 677 BOOLEAN IsDhcp4;\r
772db4bb 678\r
1f6729ff 679 IsDhcp4 = FALSE;\r
680 \r
772db4bb 681 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
772db4bb 682 if (NicHandle == NULL) {\r
683 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiArpProtocolGuid);\r
216f7970 684 if (NicHandle == NULL) {\r
1f6729ff 685 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp4ProtocolGuid);\r
686 if (NicHandle != NULL) {\r
687 IsDhcp4 = TRUE; \r
688 } else {\r
689 return EFI_SUCCESS;\r
690 }\r
216f7970 691 }\r
772db4bb 692 }\r
1f6729ff 693 \r
772db4bb 694 Status = gBS->OpenProtocol (\r
695 NicHandle,\r
696 &gEfiIp4ServiceBindingProtocolGuid,\r
697 (VOID **) &ServiceBinding,\r
698 This->DriverBindingHandle,\r
699 NicHandle,\r
700 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
701 );\r
772db4bb 702 if (EFI_ERROR (Status)) {\r
703 return EFI_DEVICE_ERROR;\r
704 }\r
1f6729ff 705 \r
706 IpSb = IP4_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
772db4bb 707\r
1f6729ff 708 if (IsDhcp4) {\r
709 Status = Ip4Config2DestroyDhcp4 (&IpSb->Ip4Config2Instance);\r
710 gBS->CloseEvent (IpSb->Ip4Config2Instance.Dhcp4Event);\r
711 IpSb->Ip4Config2Instance.Dhcp4Event = NULL;\r
712 } else if (NumberOfChildren != 0) {\r
216f7970 713 List = &IpSb->Children;\r
714 Context.ServiceBinding = ServiceBinding;\r
715 Context.NumberOfChildren = NumberOfChildren;\r
716 Context.ChildHandleBuffer = ChildHandleBuffer;\r
717 Status = NetDestroyLinkList (\r
718 List,\r
719 Ip4DestroyChildEntryInHandleBuffer,\r
720 &Context,\r
721 NULL\r
722 );\r
d0ccf55e 723 } else if (IpSb->DefaultInterface->ArpHandle == ControllerHandle) {\r
1f6729ff 724 \r
d0ccf55e 725 //\r
726 // The ARP protocol for the default interface is being uninstalled and all\r
727 // its IP child handles should have been destroyed before. So, release the\r
728 // default interface and route table, create a new one and mark it as not started.\r
729 //\r
730 Ip4CancelReceive (IpSb->DefaultInterface);\r
731 Ip4FreeInterface (IpSb->DefaultInterface, NULL);\r
732 Ip4FreeRouteTable (IpSb->DefaultRouteTable);\r
733 \r
734 IpIf = Ip4CreateInterface (IpSb->Mnp, IpSb->Controller, IpSb->Image);\r
735 if (IpIf == NULL) {\r
736 goto ON_ERROR;\r
737 }\r
738 RouteTable = Ip4CreateRouteTable ();\r
739 if (RouteTable == NULL) {\r
740 Ip4FreeInterface (IpIf, NULL);\r
741 goto ON_ERROR;;\r
742 }\r
743 \r
744 IpSb->DefaultInterface = IpIf;\r
745 InsertHeadList (&IpSb->Interfaces, &IpIf->Link);\r
746 IpSb->DefaultRouteTable = RouteTable;\r
747 Ip4ReceiveFrame (IpIf, NULL, Ip4AccpetFrame, IpSb);\r
748\r
d0ccf55e 749 IpSb->State = IP4_SERVICE_UNSTARTED;\r
1f6729ff 750\r
216f7970 751 } else if (IsListEmpty (&IpSb->Children)) {\r
c4a62a12 752 State = IpSb->State;\r
75dce340 753 IpSb->State = IP4_SERVICE_DESTROY;\r
772db4bb 754\r
c4a62a12 755 //\r
756 // OK, clean other resources then uninstall the service binding protocol.\r
757 //\r
758 Status = Ip4CleanService (IpSb);\r
c4a62a12 759 if (EFI_ERROR (Status)) {\r
760 IpSb->State = State;\r
761 goto ON_ERROR;\r
762 }\r
772db4bb 763\r
1f6729ff 764 gBS->UninstallMultipleProtocolInterfaces (\r
c4a62a12 765 NicHandle,\r
766 &gEfiIp4ServiceBindingProtocolGuid,\r
1f6729ff 767 ServiceBinding,\r
768 &gEfiIp4Config2ProtocolGuid,\r
769 &IpSb->Ip4Config2Instance.Ip4Config2,\r
770 NULL\r
c4a62a12 771 );\r
216f7970 772 \r
773 if (gIp4ControllerNameTable != NULL) {\r
774 FreeUnicodeStringTable (gIp4ControllerNameTable);\r
775 gIp4ControllerNameTable = NULL;\r
c4a62a12 776 }\r
766c7483 777 FreePool (IpSb);\r
c4a62a12 778 }\r
772db4bb 779\r
780ON_ERROR:\r
772db4bb 781 return Status;\r
782}\r
783\r
784\r
785/**\r
3e8c18da 786 Creates a child handle and installs a protocol.\r
e2851998 787\r
788 The CreateChild() function installs a protocol on ChildHandle.\r
789 If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.\r
3e8c18da 790 If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.\r
772db4bb 791\r
3e8c18da 792 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
793 @param ChildHandle Pointer to the handle of the child to create. If it is NULL,\r
e2851998 794 then a new handle is created. If it is a pointer to an existing UEFI handle,\r
3e8c18da 795 then the protocol is added to the existing UEFI handle.\r
772db4bb 796\r
3e8c18da 797 @retval EFI_SUCCES The protocol was added to ChildHandle.\r
5405e9a6 798 @retval EFI_INVALID_PARAMETER ChildHandle is NULL.\r
799 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
800 the child\r
801 @retval other The child handle was not created\r
772db4bb 802\r
803**/\r
804EFI_STATUS\r
805EFIAPI\r
806Ip4ServiceBindingCreateChild (\r
807 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
5405e9a6 808 IN OUT EFI_HANDLE *ChildHandle\r
772db4bb 809 )\r
810{\r
811 IP4_SERVICE *IpSb;\r
812 IP4_PROTOCOL *IpInstance;\r
813 EFI_TPL OldTpl;\r
814 EFI_STATUS Status;\r
815 VOID *Mnp;\r
816\r
817 if ((This == NULL) || (ChildHandle == NULL)) {\r
818 return EFI_INVALID_PARAMETER;\r
819 }\r
820\r
821 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
e48e37fc 822 IpInstance = AllocatePool (sizeof (IP4_PROTOCOL));\r
772db4bb 823\r
824 if (IpInstance == NULL) {\r
825 return EFI_OUT_OF_RESOURCES;\r
826 }\r
827\r
828 Ip4InitProtocol (IpSb, IpInstance);\r
829\r
830 //\r
831 // Install Ip4 onto ChildHandle\r
832 //\r
833 Status = gBS->InstallMultipleProtocolInterfaces (\r
834 ChildHandle,\r
835 &gEfiIp4ProtocolGuid,\r
836 &IpInstance->Ip4Proto,\r
837 NULL\r
838 );\r
839\r
840 if (EFI_ERROR (Status)) {\r
841 goto ON_ERROR;\r
842 }\r
843\r
844 IpInstance->Handle = *ChildHandle;\r
845\r
846 //\r
847 // Open the Managed Network protocol BY_CHILD.\r
848 //\r
849 Status = gBS->OpenProtocol (\r
850 IpSb->MnpChildHandle,\r
851 &gEfiManagedNetworkProtocolGuid,\r
852 (VOID **) &Mnp,\r
853 gIp4DriverBinding.DriverBindingHandle,\r
854 IpInstance->Handle,\r
855 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
856 );\r
857 if (EFI_ERROR (Status)) {\r
858 gBS->UninstallMultipleProtocolInterfaces (\r
859 ChildHandle,\r
860 &gEfiIp4ProtocolGuid,\r
861 &IpInstance->Ip4Proto,\r
862 NULL\r
863 );\r
864\r
865 goto ON_ERROR;\r
866 }\r
867\r
868 //\r
869 // Insert it into the service binding instance.\r
870 //\r
e48e37fc 871 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 872\r
e48e37fc 873 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
772db4bb 874 IpSb->NumChildren++;\r
875\r
e48e37fc 876 gBS->RestoreTPL (OldTpl);\r
772db4bb 877\r
878ON_ERROR:\r
879\r
880 if (EFI_ERROR (Status)) {\r
881\r
882 Ip4CleanProtocol (IpInstance);\r
883\r
766c7483 884 FreePool (IpInstance);\r
772db4bb 885 }\r
886\r
887 return Status;\r
888}\r
889\r
890\r
891/**\r
3e8c18da 892 Destroys a child handle with a protocol installed on it.\r
e2851998 893\r
894 The DestroyChild() function does the opposite of CreateChild(). It removes a protocol\r
895 that was installed by CreateChild() from ChildHandle. If the removed protocol is the\r
3e8c18da 896 last protocol on ChildHandle, then ChildHandle is destroyed.\r
772db4bb 897\r
3e8c18da 898 @param This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.\r
5405e9a6 899 @param ChildHandle Handle of the child to destroy\r
900\r
3e8c18da 901 @retval EFI_SUCCES The protocol was removed from ChildHandle.\r
902 @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.\r
284ee2e8 903 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
3e8c18da 904 @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle\r
905 because its services are being used.\r
5405e9a6 906 @retval other The child handle was not destroyed\r
772db4bb 907\r
908**/\r
909EFI_STATUS\r
910EFIAPI\r
911Ip4ServiceBindingDestroyChild (\r
912 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
913 IN EFI_HANDLE ChildHandle\r
914 )\r
915{\r
916 EFI_STATUS Status;\r
917 IP4_SERVICE *IpSb;\r
918 IP4_PROTOCOL *IpInstance;\r
919 EFI_IP4_PROTOCOL *Ip4;\r
920 EFI_TPL OldTpl;\r
921 INTN State;\r
922\r
923 if ((This == NULL) || (ChildHandle == NULL)) {\r
924 return EFI_INVALID_PARAMETER;\r
925 }\r
926\r
927 //\r
928 // Retrieve the private context data structures\r
929 //\r
930 IpSb = IP4_SERVICE_FROM_PROTOCOL (This);\r
931\r
932 Status = gBS->OpenProtocol (\r
933 ChildHandle,\r
934 &gEfiIp4ProtocolGuid,\r
935 (VOID **) &Ip4,\r
936 gIp4DriverBinding.DriverBindingHandle,\r
937 ChildHandle,\r
938 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
939 );\r
940\r
941 if (EFI_ERROR (Status)) {\r
942 return EFI_UNSUPPORTED;\r
943 }\r
944\r
945 IpInstance = IP4_INSTANCE_FROM_PROTOCOL (Ip4);\r
946\r
947 if (IpInstance->Service != IpSb) {\r
948 return EFI_INVALID_PARAMETER;\r
949 }\r
950\r
e48e37fc 951 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 952\r
953 //\r
75dce340 954 // A child can be destroyed more than once. For example,\r
955 // Ip4DriverBindingStop will destroy all of its children.\r
956 // when UDP driver is being stopped, it will destroy all\r
772db4bb 957 // the IP child it opens.\r
958 //\r
75dce340 959 if (IpInstance->State == IP4_STATE_DESTROY) {\r
e48e37fc 960 gBS->RestoreTPL (OldTpl);\r
772db4bb 961 return EFI_SUCCESS;\r
962 }\r
963\r
964 State = IpInstance->State;\r
75dce340 965 IpInstance->State = IP4_STATE_DESTROY;\r
772db4bb 966\r
967 //\r
968 // Close the Managed Network protocol.\r
969 //\r
970 gBS->CloseProtocol (\r
971 IpSb->MnpChildHandle,\r
972 &gEfiManagedNetworkProtocolGuid,\r
973 gIp4DriverBinding.DriverBindingHandle,\r
974 ChildHandle\r
975 );\r
976\r
216f7970 977 if (IpInstance->Interface != NULL && IpInstance->Interface->Arp != NULL) {\r
978 gBS->CloseProtocol (\r
979 IpInstance->Interface->ArpHandle,\r
980 &gEfiArpProtocolGuid,\r
981 gIp4DriverBinding.DriverBindingHandle,\r
982 ChildHandle\r
983 );\r
984 }\r
985\r
772db4bb 986 //\r
987 // Uninstall the IP4 protocol first. Many thing happens during\r
988 // this:\r
989 // 1. The consumer of the IP4 protocol will be stopped if it\r
990 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
991 // stopped, IP driver's stop function will be called, and uninstall\r
992 // EFI_IP4_PROTOCOL will trigger the UDP's stop function. This\r
993 // makes it possible to create the network stack bottom up, and\r
994 // stop it top down.\r
995 // 2. the upper layer will recycle the received packet. The recycle\r
996 // event's TPL is higher than this function. The recycle events\r
997 // will be called back before preceeding. If any packets not recycled,\r
998 // that means there is a resource leak.\r
999 //\r
216f7970 1000 gBS->RestoreTPL (OldTpl);\r
772db4bb 1001 Status = gBS->UninstallProtocolInterface (\r
1002 ChildHandle,\r
1003 &gEfiIp4ProtocolGuid,\r
1004 &IpInstance->Ip4Proto\r
1005 );\r
216f7970 1006 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
772db4bb 1007 if (EFI_ERROR (Status)) {\r
1008 goto ON_ERROR;\r
1009 }\r
1010\r
1011 Status = Ip4CleanProtocol (IpInstance);\r
772db4bb 1012 if (EFI_ERROR (Status)) {\r
1013 gBS->InstallMultipleProtocolInterfaces (\r
1014 &ChildHandle,\r
1015 &gEfiIp4ProtocolGuid,\r
1016 Ip4,\r
1017 NULL\r
1018 );\r
1019\r
1020 goto ON_ERROR;\r
1021 }\r
1022\r
e48e37fc 1023 RemoveEntryList (&IpInstance->Link);\r
772db4bb 1024 IpSb->NumChildren--;\r
1025\r
e48e37fc 1026 gBS->RestoreTPL (OldTpl);\r
772db4bb 1027\r
766c7483 1028 FreePool (IpInstance);\r
772db4bb 1029 return EFI_SUCCESS;\r
1030\r
1031ON_ERROR:\r
1032 IpInstance->State = State;\r
e48e37fc 1033 gBS->RestoreTPL (OldTpl);\r
772db4bb 1034\r
1035 return Status;\r
1036}\r