]> git.proxmox.com Git - mirror_edk2.git/blame - NetworkPkg/Ip6Dxe/Ip6Driver.c
NetworkPkg: Add URI configuration form to HTTP boot driver.
[mirror_edk2.git] / NetworkPkg / Ip6Dxe / Ip6Driver.c
CommitLineData
a3bcde70
HT
1/** @file\r
2 The driver binding and service binding protocol for IP6 driver.\r
3\r
4720106b 4 Copyright (c) 2009 - 2016, Intel Corporation. All rights reserved.<BR>\r
c79de074 5 (C) Copyright 2015 Hewlett-Packard Development Company, L.P.<BR>\r
a3bcde70
HT
6\r
7 This program and the accompanying materials\r
8 are licensed and made available under the terms and conditions of the BSD License\r
9 which accompanies this distribution. The full text of the license may be found at\r
10 http://opensource.org/licenses/bsd-license.php.\r
11\r
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,\r
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.\r
14\r
15**/\r
16\r
17#include "Ip6Impl.h"\r
18\r
19EFI_DRIVER_BINDING_PROTOCOL gIp6DriverBinding = {\r
20 Ip6DriverBindingSupported,\r
21 Ip6DriverBindingStart,\r
22 Ip6DriverBindingStop,\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
c79de074
SEHM
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 return;\r
52}\r
53\r
a3bcde70
HT
54/**\r
55 This is the declaration of an EFI image entry point. This entry point is\r
56 the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including\r
57 both device drivers and bus drivers.\r
58\r
59 The entry point for IP6 driver which installs the driver\r
60 binding and component name protocol on its image.\r
61\r
62 @param[in] ImageHandle The firmware allocated handle for the UEFI image.\r
63 @param[in] SystemTable A pointer to the EFI System Table.\r
64\r
65 @retval EFI_SUCCESS The operation completed successfully.\r
66 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
67\r
68**/\r
69EFI_STATUS\r
70EFIAPI\r
71Ip6DriverEntryPoint (\r
72 IN EFI_HANDLE ImageHandle,\r
73 IN EFI_SYSTEM_TABLE *SystemTable\r
74 )\r
75{\r
c79de074
SEHM
76 VOID *Registration;\r
77\r
78 EfiCreateProtocolNotifyEvent (\r
79 &gEfiIpSec2ProtocolGuid,\r
80 TPL_CALLBACK,\r
81 IpSec2InstalledCallback,\r
82 NULL,\r
83 &Registration\r
84 );\r
85\r
a3bcde70
HT
86 return EfiLibInstallDriverBindingComponentName2 (\r
87 ImageHandle,\r
88 SystemTable,\r
89 &gIp6DriverBinding,\r
90 ImageHandle,\r
91 &gIp6ComponentName,\r
92 &gIp6ComponentName2\r
93 );\r
94}\r
95\r
96/**\r
97 Test to see if this driver supports ControllerHandle.\r
98\r
99 @param[in] This Protocol instance pointer.\r
100 @param[in] ControllerHandle Handle of device to test.\r
101 @param[in] RemainingDevicePath Optional parameter use to pick a specific child\r
102 device to start.\r
103\r
104 @retval EFI_SUCCESS This driver supports this device.\r
105 @retval EFI_ALREADY_STARTED This driver is already running on this device.\r
106 @retval other This driver does not support this device.\r
107\r
108**/\r
109EFI_STATUS\r
110EFIAPI\r
111Ip6DriverBindingSupported (\r
112 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
113 IN EFI_HANDLE ControllerHandle,\r
114 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
115 )\r
116{\r
117 //\r
118 // Test for the MNP service binding Protocol\r
119 //\r
120 return gBS->OpenProtocol (\r
121 ControllerHandle,\r
122 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
123 NULL,\r
124 This->DriverBindingHandle,\r
125 ControllerHandle,\r
126 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
127 );\r
128}\r
129\r
130/**\r
131 Clean up an IP6 service binding instance. It releases all\r
132 the resource allocated by the instance. The instance may be\r
133 partly initialized, or partly destroyed. If a resource is\r
75dce340 134 destroyed, it is marked as that in case the destroy failed and\r
a3bcde70
HT
135 being called again later.\r
136\r
137 @param[in] IpSb The IP6 service binding instance to clean up.\r
138\r
139 @retval EFI_SUCCESS The resource used by the instance are cleaned up.\r
140 @retval Others Failed to clean up some of the resources.\r
141\r
142**/\r
143EFI_STATUS\r
144Ip6CleanService (\r
145 IN IP6_SERVICE *IpSb\r
146 )\r
147{\r
148 EFI_STATUS Status;\r
149 EFI_IPv6_ADDRESS AllNodes;\r
150 IP6_NEIGHBOR_ENTRY *NeighborCache;\r
151\r
152 Ip6ConfigCleanInstance (&IpSb->Ip6ConfigInstance);\r
153\r
216f7970 154 if (!IpSb->LinkLocalDadFail) {\r
155 //\r
156 // Leave link-scope all-nodes multicast address (FF02::1)\r
157 //\r
158 Ip6SetToAllNodeMulticast (FALSE, IP6_LINK_LOCAL_SCOPE, &AllNodes);\r
a3bcde70 159\r
216f7970 160 Status = Ip6LeaveGroup (IpSb, &AllNodes);\r
161 if (EFI_ERROR (Status)) {\r
162 return Status;\r
163 } \r
a3bcde70
HT
164 }\r
165\r
166 if (IpSb->DefaultInterface != NULL) {\r
167 Ip6CleanInterface (IpSb->DefaultInterface, NULL);\r
168 IpSb->DefaultInterface = NULL;\r
169 }\r
170\r
171 Ip6CleanDefaultRouterList (IpSb);\r
172\r
173 Ip6CleanPrefixListTable (IpSb, &IpSb->OnlinkPrefix);\r
174 Ip6CleanPrefixListTable (IpSb, &IpSb->AutonomousPrefix);\r
175\r
176 if (IpSb->RouteTable != NULL) {\r
177 Ip6CleanRouteTable (IpSb->RouteTable);\r
178 IpSb->RouteTable = NULL;\r
179 }\r
180\r
181 if (IpSb->InterfaceId != NULL) {\r
182 FreePool (IpSb->InterfaceId);\r
183 }\r
184\r
185 IpSb->InterfaceId = NULL;\r
186\r
187 Ip6CleanAssembleTable (&IpSb->Assemble);\r
188\r
189 if (IpSb->MnpChildHandle != NULL) {\r
190 if (IpSb->Mnp != NULL) {\r
191 IpSb->Mnp->Cancel (IpSb->Mnp, NULL);\r
192 IpSb->Mnp->Configure (IpSb->Mnp, NULL);\r
193 gBS->CloseProtocol (\r
194 IpSb->MnpChildHandle,\r
195 &gEfiManagedNetworkProtocolGuid,\r
196 IpSb->Image,\r
197 IpSb->Controller\r
198 );\r
199\r
200 IpSb->Mnp = NULL;\r
201 }\r
202\r
203 NetLibDestroyServiceChild (\r
204 IpSb->Controller,\r
205 IpSb->Image,\r
206 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
207 IpSb->MnpChildHandle\r
208 );\r
209\r
210 IpSb->MnpChildHandle = NULL;\r
211 }\r
212\r
213 if (IpSb->RecvRequest.MnpToken.Event != NULL) {\r
214 gBS->CloseEvent (IpSb->RecvRequest.MnpToken.Event);\r
215 }\r
216\r
217 if (IpSb->Timer != NULL) {\r
218 gBS->SetTimer (IpSb->Timer, TimerCancel, 0);\r
219 gBS->CloseEvent (IpSb->Timer);\r
220\r
221 IpSb->Timer = NULL;\r
222 }\r
223\r
224 if (IpSb->FasterTimer != NULL) {\r
225 gBS->SetTimer (IpSb->FasterTimer, TimerCancel, 0);\r
226 gBS->CloseEvent (IpSb->FasterTimer);\r
227\r
228 IpSb->FasterTimer = NULL;\r
229 }\r
230 //\r
231 // Free the Neighbor Discovery resources\r
232 //\r
233 while (!IsListEmpty (&IpSb->NeighborTable)) {\r
234 NeighborCache = NET_LIST_HEAD (&IpSb->NeighborTable, IP6_NEIGHBOR_ENTRY, Link);\r
235 Ip6FreeNeighborEntry (IpSb, NeighborCache, FALSE, TRUE, EFI_SUCCESS, NULL, NULL);\r
236 }\r
237\r
238 return EFI_SUCCESS;\r
239}\r
240\r
241/**\r
242 Create a new IP6 driver service binding protocol.\r
243\r
244 @param[in] Controller The controller that has MNP service binding\r
245 installed.\r
246 @param[in] ImageHandle The IP6 driver's image handle.\r
247 @param[out] Service The variable to receive the newly created IP6\r
248 service.\r
249\r
250 @retval EFI_OUT_OF_RESOURCES Failed to allocate some resources.\r
251 @retval EFI_SUCCESS A new IP6 service binding private is created.\r
252\r
253**/\r
254EFI_STATUS\r
255Ip6CreateService (\r
256 IN EFI_HANDLE Controller,\r
257 IN EFI_HANDLE ImageHandle,\r
258 OUT IP6_SERVICE **Service\r
259 )\r
260{\r
261 IP6_SERVICE *IpSb;\r
262 EFI_STATUS Status;\r
263 EFI_MANAGED_NETWORK_COMPLETION_TOKEN *MnpToken;\r
264 EFI_MANAGED_NETWORK_CONFIG_DATA *Config;\r
a3bcde70
HT
265\r
266 ASSERT (Service != NULL);\r
267\r
268 *Service = NULL;\r
269\r
270 //\r
271 // allocate a service private data then initialize all the filed to\r
272 // empty resources, so if any thing goes wrong when allocating\r
273 // resources, Ip6CleanService can be called to clean it up.\r
274 //\r
275 IpSb = AllocateZeroPool (sizeof (IP6_SERVICE));\r
276\r
277 if (IpSb == NULL) {\r
278 return EFI_OUT_OF_RESOURCES;\r
279 }\r
280\r
281 IpSb->Signature = IP6_SERVICE_SIGNATURE;\r
282 IpSb->ServiceBinding.CreateChild = Ip6ServiceBindingCreateChild;\r
283 IpSb->ServiceBinding.DestroyChild = Ip6ServiceBindingDestroyChild;\r
284 IpSb->State = IP6_SERVICE_UNSTARTED;\r
a3bcde70
HT
285\r
286 IpSb->NumChildren = 0;\r
287 InitializeListHead (&IpSb->Children);\r
288\r
289 InitializeListHead (&IpSb->Interfaces);\r
290 IpSb->DefaultInterface = NULL;\r
291 IpSb->RouteTable = NULL;\r
292\r
293 IpSb->RecvRequest.Signature = IP6_LINK_RX_SIGNATURE;\r
294 IpSb->RecvRequest.CallBack = NULL;\r
295 IpSb->RecvRequest.Context = NULL;\r
296 MnpToken = &IpSb->RecvRequest.MnpToken;\r
297 MnpToken->Event = NULL;\r
298 MnpToken->Status = EFI_NOT_READY;\r
299 MnpToken->Packet.RxData = NULL;\r
300\r
301 Ip6CreateAssembleTable (&IpSb->Assemble);\r
302\r
303 IpSb->MldCtrl.Mldv1QuerySeen = 0;\r
304 InitializeListHead (&IpSb->MldCtrl.Groups);\r
305\r
306 ZeroMem (&IpSb->LinkLocalAddr, sizeof (EFI_IPv6_ADDRESS));\r
307 IpSb->LinkLocalOk = FALSE;\r
308 IpSb->LinkLocalDadFail = FALSE;\r
309 IpSb->Dhcp6NeedStart = FALSE;\r
310 IpSb->Dhcp6NeedInfoRequest = FALSE;\r
311\r
312 IpSb->CurHopLimit = IP6_HOP_LIMIT;\r
313 IpSb->LinkMTU = IP6_MIN_LINK_MTU;\r
314 IpSb->BaseReachableTime = IP6_REACHABLE_TIME;\r
315 Ip6UpdateReachableTime (IpSb);\r
316 //\r
317 // RFC4861 RETRANS_TIMER: 1,000 milliseconds\r
318 //\r
319 IpSb->RetransTimer = IP6_RETRANS_TIMER;\r
320\r
321 IpSb->RoundRobin = 0;\r
322\r
323 InitializeListHead (&IpSb->NeighborTable);\r
324 InitializeListHead (&IpSb->DefaultRouterList);\r
325 InitializeListHead (&IpSb->OnlinkPrefix);\r
326 InitializeListHead (&IpSb->AutonomousPrefix);\r
327\r
328 IpSb->InterfaceIdLen = IP6_IF_ID_LEN;\r
329 IpSb->InterfaceId = NULL;\r
330\r
331 IpSb->RouterAdvertiseReceived = FALSE;\r
332 IpSb->SolicitTimer = IP6_MAX_RTR_SOLICITATIONS;\r
333 IpSb->Ticks = 0;\r
334\r
335 IpSb->Image = ImageHandle;\r
336 IpSb->Controller = Controller;\r
337\r
338 IpSb->MnpChildHandle = NULL;\r
339 IpSb->Mnp = NULL;\r
340\r
341 Config = &IpSb->MnpConfigData;\r
342 Config->ReceivedQueueTimeoutValue = 0;\r
343 Config->TransmitQueueTimeoutValue = 0;\r
344 Config->ProtocolTypeFilter = IP6_ETHER_PROTO;\r
345 Config->EnableUnicastReceive = TRUE;\r
346 Config->EnableMulticastReceive = TRUE;\r
347 Config->EnableBroadcastReceive = TRUE;\r
348 Config->EnablePromiscuousReceive = FALSE;\r
349 Config->FlushQueuesOnReset = TRUE;\r
350 Config->EnableReceiveTimestamps = FALSE;\r
351 Config->DisableBackgroundPolling = FALSE;\r
352\r
353 ZeroMem (&IpSb->SnpMode, sizeof (EFI_SIMPLE_NETWORK_MODE));\r
354\r
355 IpSb->Timer = NULL;\r
356 IpSb->FasterTimer = NULL;\r
357\r
358 ZeroMem (&IpSb->Ip6ConfigInstance, sizeof (IP6_CONFIG_INSTANCE));\r
359\r
360 IpSb->MacString = NULL;\r
361\r
362 //\r
363 // Create various resources. First create the route table, timer\r
364 // event, MNP token event and MNP child.\r
365 //\r
366\r
367 IpSb->RouteTable = Ip6CreateRouteTable ();\r
368 if (IpSb->RouteTable == NULL) {\r
369 Status = EFI_OUT_OF_RESOURCES;\r
370 goto ON_ERROR;\r
371 }\r
372\r
373 Status = gBS->CreateEvent (\r
374 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
375 TPL_CALLBACK,\r
376 Ip6TimerTicking,\r
377 IpSb,\r
378 &IpSb->Timer\r
379 );\r
380 if (EFI_ERROR (Status)) {\r
381 goto ON_ERROR;\r
382 }\r
383\r
384 Status = gBS->CreateEvent (\r
385 EVT_NOTIFY_SIGNAL | EVT_TIMER,\r
386 TPL_CALLBACK,\r
387 Ip6NdFasterTimerTicking,\r
388 IpSb,\r
389 &IpSb->FasterTimer\r
390 );\r
391 if (EFI_ERROR (Status)) {\r
392 goto ON_ERROR;\r
393 }\r
394\r
395 Status = NetLibCreateServiceChild (\r
396 Controller,\r
397 ImageHandle,\r
398 &gEfiManagedNetworkServiceBindingProtocolGuid,\r
399 &IpSb->MnpChildHandle\r
400 );\r
401 if (EFI_ERROR (Status)) {\r
402 goto ON_ERROR;\r
403 }\r
404\r
405 Status = gBS->OpenProtocol (\r
406 IpSb->MnpChildHandle,\r
407 &gEfiManagedNetworkProtocolGuid,\r
408 (VOID **) (&IpSb->Mnp),\r
409 ImageHandle,\r
410 Controller,\r
411 EFI_OPEN_PROTOCOL_BY_DRIVER\r
412 );\r
413 if (EFI_ERROR (Status)) {\r
414 goto ON_ERROR;\r
415 }\r
416\r
417 Status = Ip6ServiceConfigMnp (IpSb, TRUE);\r
418 if (EFI_ERROR (Status)) {\r
419 goto ON_ERROR;\r
420 }\r
421\r
422 Status = IpSb->Mnp->GetModeData (IpSb->Mnp, NULL, &IpSb->SnpMode);\r
423 if (EFI_ERROR (Status)) {\r
424 goto ON_ERROR;\r
425 }\r
426\r
427 IpSb->MaxPacketSize = IP6_MIN_LINK_MTU - sizeof (EFI_IP6_HEADER);\r
428 if (NetLibGetVlanId (IpSb->Controller) != 0) {\r
429 //\r
430 // This is a VLAN device, reduce MTU by VLAN tag length\r
431 //\r
432 IpSb->MaxPacketSize -= NET_VLAN_TAG_LEN;\r
433 }\r
434 IpSb->OldMaxPacketSize = IpSb->MaxPacketSize;\r
435\r
436 //\r
437 // Currently only ETHERNET is supported in IPv6 stack, since\r
438 // link local address requires an IEEE 802 48-bit MACs for\r
439 // EUI-64 format interface identifier mapping.\r
440 //\r
441 if (IpSb->SnpMode.IfType != NET_IFTYPE_ETHERNET) {\r
442 Status = EFI_UNSUPPORTED;\r
443 goto ON_ERROR;\r
444 }\r
445\r
446 Status = Ip6InitMld (IpSb);\r
447 if (EFI_ERROR (Status)) {\r
448 goto ON_ERROR;\r
449 }\r
450\r
8fedfc04 451 Status = NetLibGetMacString (IpSb->Controller, IpSb->Image, &IpSb->MacString);\r
a3bcde70
HT
452 if (EFI_ERROR (Status)) {\r
453 goto ON_ERROR;\r
454 }\r
455\r
8fedfc04 456 Status = Ip6ConfigInitInstance (&IpSb->Ip6ConfigInstance);\r
a3bcde70
HT
457 if (EFI_ERROR (Status)) {\r
458 goto ON_ERROR;\r
459 }\r
460\r
8fedfc04
YT
461 IpSb->DefaultInterface = Ip6CreateInterface (IpSb, TRUE);\r
462 if (IpSb->DefaultInterface == NULL) {\r
463 Status = EFI_DEVICE_ERROR;\r
464 goto ON_ERROR;\r
465 }\r
a3bcde70
HT
466\r
467 Status = gBS->CreateEvent (\r
468 EVT_NOTIFY_SIGNAL,\r
469 TPL_NOTIFY,\r
470 Ip6OnFrameReceived,\r
471 &IpSb->RecvRequest,\r
472 &MnpToken->Event\r
473 );\r
474 if (EFI_ERROR (Status)) {\r
475 goto ON_ERROR;\r
476 }\r
477\r
a3bcde70
HT
478 InsertHeadList (&IpSb->Interfaces, &IpSb->DefaultInterface->Link);\r
479\r
480 *Service = IpSb;\r
481 return EFI_SUCCESS;\r
482\r
483ON_ERROR:\r
484 Ip6CleanService (IpSb);\r
485 FreePool (IpSb);\r
486 return Status;\r
487}\r
488\r
489\r
490/**\r
491 Start this driver on ControllerHandle.\r
492\r
493 @param[in] This Protocol instance pointer.\r
494 @param[in] ControllerHandle Handle of device to bind driver to.\r
495 @param[in] RemainingDevicePath Optional parameter used to pick a specific child\r
496 device to start.\r
497\r
498 @retval EFI_SUCCES This driver is added to ControllerHandle.\r
499 @retval EFI_ALREADY_STARTED This driver is already running on ControllerHandle.\r
500 @retval other This driver does not support this device.\r
501\r
502**/\r
503EFI_STATUS\r
504EFIAPI\r
505Ip6DriverBindingStart (\r
506 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
507 IN EFI_HANDLE ControllerHandle,\r
508 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL\r
509 )\r
510{\r
511 IP6_SERVICE *IpSb;\r
512 EFI_STATUS Status;\r
4720106b
JW
513 EFI_IP6_CONFIG_PROTOCOL *Ip6Cfg;\r
514 IP6_CONFIG_DATA_ITEM *DataItem;\r
515\r
516 IpSb = NULL;\r
517 Ip6Cfg = NULL;\r
518 DataItem = NULL;\r
a3bcde70
HT
519\r
520 //\r
521 // Test for the Ip6 service binding protocol\r
522 //\r
523 Status = gBS->OpenProtocol (\r
524 ControllerHandle,\r
525 &gEfiIp6ServiceBindingProtocolGuid,\r
526 NULL,\r
527 This->DriverBindingHandle,\r
528 ControllerHandle,\r
529 EFI_OPEN_PROTOCOL_TEST_PROTOCOL\r
530 );\r
531\r
532 if (Status == EFI_SUCCESS) {\r
533 return EFI_ALREADY_STARTED;\r
534 }\r
535\r
536 Status = Ip6CreateService (ControllerHandle, This->DriverBindingHandle, &IpSb);\r
537\r
538 if (EFI_ERROR (Status)) {\r
539 return Status;\r
540 }\r
541\r
542 ASSERT (IpSb != NULL);\r
543\r
4720106b
JW
544 Ip6Cfg = &IpSb->Ip6ConfigInstance.Ip6Config;\r
545\r
a3bcde70
HT
546 //\r
547 // Install the Ip6ServiceBinding Protocol onto ControlerHandle\r
548 //\r
549 Status = gBS->InstallMultipleProtocolInterfaces (\r
550 &ControllerHandle,\r
551 &gEfiIp6ServiceBindingProtocolGuid,\r
552 &IpSb->ServiceBinding,\r
553 &gEfiIp6ConfigProtocolGuid,\r
4720106b 554 Ip6Cfg,\r
a3bcde70
HT
555 NULL\r
556 );\r
4720106b
JW
557 if (EFI_ERROR (Status)) {\r
558 goto ON_ERROR;\r
559 }\r
560\r
561 //\r
562 // Read the config data from NV variable again. \r
563 // The default data can be changed by other drivers.\r
564 //\r
565 Status = Ip6ConfigReadConfigData (IpSb->MacString, &IpSb->Ip6ConfigInstance);\r
566 if (EFI_ERROR (Status)) {\r
567 goto ON_ERROR;\r
568 }\r
569 \r
570 //\r
571 // If there is any default manual address, set it.\r
572 //\r
573 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeManualAddress];\r
574 if (DataItem->Data.Ptr != NULL) {\r
575 Status = Ip6Cfg->SetData (\r
576 Ip6Cfg,\r
577 Ip6ConfigDataTypeManualAddress,\r
578 DataItem->DataSize,\r
579 DataItem->Data.Ptr\r
580 );\r
581 if (EFI_ERROR(Status)) {\r
582 goto ON_ERROR;\r
583 }\r
584 }\r
585\r
586 //\r
587 // If there is any default gateway address, set it.\r
588 //\r
589 DataItem = &IpSb->Ip6ConfigInstance.DataItem[Ip6ConfigDataTypeGateway];\r
590 if (DataItem->Data.Ptr != NULL) {\r
591 Status = Ip6Cfg->SetData (\r
592 Ip6Cfg,\r
593 Ip6ConfigDataTypeGateway,\r
594 DataItem->DataSize,\r
595 DataItem->Data.Ptr\r
596 );\r
597 if (EFI_ERROR(Status)) {\r
598 goto ON_ERROR;\r
599 }\r
600 }\r
a3bcde70 601\r
8fedfc04
YT
602 if (!EFI_ERROR (Status)) {\r
603 //\r
604 // ready to go: start the receiving and timer\r
605 //\r
606 Status = Ip6ReceiveFrame (Ip6AcceptFrame, IpSb);\r
607 if (EFI_ERROR (Status)) {\r
608 goto ON_ERROR;\r
609 }\r
610\r
611 //\r
612 // The timer expires every 100 (IP6_TIMER_INTERVAL_IN_MS) milliseconds.\r
613 //\r
614 Status = gBS->SetTimer (\r
615 IpSb->FasterTimer,\r
616 TimerPeriodic,\r
617 TICKS_PER_MS * IP6_TIMER_INTERVAL_IN_MS\r
618 );\r
619 if (EFI_ERROR (Status)) {\r
620 goto ON_ERROR;\r
621 }\r
622\r
623 //\r
624 // The timer expires every 1000 (IP6_ONE_SECOND_IN_MS) milliseconds.\r
625 //\r
626 Status = gBS->SetTimer (\r
627 IpSb->Timer,\r
628 TimerPeriodic,\r
629 TICKS_PER_MS * IP6_ONE_SECOND_IN_MS\r
630 );\r
631 if (EFI_ERROR (Status)) {\r
632 goto ON_ERROR;\r
633 } \r
a3bcde70 634\r
a3bcde70
HT
635 //\r
636 // Initialize the IP6 ID\r
637 //\r
638 mIp6Id = NET_RANDOM (NetRandomInitSeed ());\r
639\r
8fedfc04 640 return EFI_SUCCESS;\r
a3bcde70
HT
641 }\r
642\r
8fedfc04
YT
643ON_ERROR:\r
644 Ip6CleanService (IpSb);\r
645 FreePool (IpSb);\r
a3bcde70
HT
646 return Status;\r
647}\r
648\r
216f7970 649/**\r
650 Callback function which provided by user to remove one node in NetDestroyLinkList process.\r
651 \r
652 @param[in] Entry The entry to be removed.\r
653 @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.\r
654\r
655 @retval EFI_SUCCESS The entry has been removed successfully.\r
656 @retval Others Fail to remove the entry.\r
657\r
658**/\r
659EFI_STATUS\r
1f7eb561 660EFIAPI\r
216f7970 661Ip6DestroyChildEntryInHandleBuffer (\r
662 IN LIST_ENTRY *Entry,\r
663 IN VOID *Context\r
1f7eb561 664 )\r
216f7970 665{\r
666 IP6_PROTOCOL *IpInstance;\r
667 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
668 UINTN NumberOfChildren;\r
669 EFI_HANDLE *ChildHandleBuffer;\r
670\r
671 if (Entry == NULL || Context == NULL) {\r
672 return EFI_INVALID_PARAMETER;\r
673 }\r
674\r
675 IpInstance = NET_LIST_USER_STRUCT_S (Entry, IP6_PROTOCOL, Link, IP6_PROTOCOL_SIGNATURE);\r
676 ServiceBinding = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ServiceBinding;\r
677 NumberOfChildren = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->NumberOfChildren;\r
678 ChildHandleBuffer = ((IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *) Context)->ChildHandleBuffer;\r
679\r
680 if (!NetIsInHandleBuffer (IpInstance->Handle, NumberOfChildren, ChildHandleBuffer)) {\r
681 return EFI_SUCCESS;\r
682 }\r
683\r
684 return ServiceBinding->DestroyChild (ServiceBinding, IpInstance->Handle);\r
685}\r
686\r
a3bcde70
HT
687/**\r
688 Stop this driver on ControllerHandle.\r
689\r
690 @param[in] This Protocol instance pointer.\r
691 @param[in] ControllerHandle Handle of device to stop driver on.\r
692 @param[in] NumberOfChildren Number of Handles in ChildHandleBuffer. If number\r
693 of children is zero, stop the entire bus driver.\r
694 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
695 if NumberOfChildren is 0.\r
696\r
697 @retval EFI_SUCCESS The device was stopped.\r
698 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
699\r
700**/\r
701EFI_STATUS\r
702EFIAPI\r
703Ip6DriverBindingStop (\r
704 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
705 IN EFI_HANDLE ControllerHandle,\r
706 IN UINTN NumberOfChildren,\r
707 IN EFI_HANDLE *ChildHandleBuffer OPTIONAL\r
708 )\r
709{\r
216f7970 710 EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;\r
711 IP6_SERVICE *IpSb;\r
712 EFI_HANDLE NicHandle;\r
713 EFI_STATUS Status;\r
714 LIST_ENTRY *List;\r
715 INTN State;\r
716 BOOLEAN IsDhcp6;\r
717 IP6_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;\r
a3bcde70
HT
718\r
719 IsDhcp6 = FALSE;\r
216f7970 720 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiManagedNetworkProtocolGuid);\r
721 if (NicHandle == NULL) {\r
722 NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiDhcp6ProtocolGuid);\r
723 if (NicHandle != NULL) {\r
724 IsDhcp6 = TRUE;\r
725 } else {\r
726 return EFI_SUCCESS;\r
a3bcde70
HT
727 }\r
728 }\r
729\r
730 Status = gBS->OpenProtocol (\r
731 NicHandle,\r
732 &gEfiIp6ServiceBindingProtocolGuid,\r
733 (VOID **) &ServiceBinding,\r
734 This->DriverBindingHandle,\r
735 NicHandle,\r
736 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
737 );\r
738 if (EFI_ERROR (Status)) {\r
739 return EFI_DEVICE_ERROR;\r
740 }\r
741\r
742 IpSb = IP6_SERVICE_FROM_PROTOCOL (ServiceBinding);\r
743\r
a3bcde70 744 if (IsDhcp6) {\r
a3bcde70
HT
745 Status = Ip6ConfigDestroyDhcp6 (&IpSb->Ip6ConfigInstance);\r
746 gBS->CloseEvent (IpSb->Ip6ConfigInstance.Dhcp6Event);\r
747 IpSb->Ip6ConfigInstance.Dhcp6Event = NULL;\r
216f7970 748 } else if (NumberOfChildren != 0) {\r
749 //\r
750 // NumberOfChildren is not zero, destroy the IP6 children instances in ChildHandleBuffer.\r
751 //\r
752 List = &IpSb->Children;\r
753 Context.ServiceBinding = ServiceBinding;\r
754 Context.NumberOfChildren = NumberOfChildren;\r
755 Context.ChildHandleBuffer = ChildHandleBuffer;\r
756 Status = NetDestroyLinkList (\r
757 List,\r
758 Ip6DestroyChildEntryInHandleBuffer,\r
759 &Context,\r
760 NULL\r
761 );\r
762 } else if (IsListEmpty (&IpSb->Children)) {\r
a3bcde70
HT
763 State = IpSb->State;\r
764 IpSb->State = IP6_SERVICE_DESTROY;\r
765\r
a3bcde70
HT
766 Status = Ip6CleanService (IpSb);\r
767 if (EFI_ERROR (Status)) {\r
768 IpSb->State = State;\r
769 goto Exit;\r
770 }\r
771\r
772 Status = gBS->UninstallMultipleProtocolInterfaces (\r
773 NicHandle,\r
774 &gEfiIp6ServiceBindingProtocolGuid,\r
775 ServiceBinding,\r
776 &gEfiIp6ConfigProtocolGuid,\r
777 &IpSb->Ip6ConfigInstance.Ip6Config,\r
778 NULL\r
779 );\r
780 ASSERT_EFI_ERROR (Status);\r
781 FreePool (IpSb);\r
216f7970 782 Status = EFI_SUCCESS;\r
a3bcde70 783 }\r
216f7970 784 \r
a3bcde70 785Exit:\r
a3bcde70
HT
786 return Status;\r
787}\r
788\r
789\r
790/**\r
791 Creates a child handle with a set of I/O services.\r
792\r
793 @param[in] This Protocol instance pointer.\r
794 @param[in] ChildHandle Pointer to the handle of the child to create. If\r
795 it is NULL, then a new handle is created. If it\r
796 is not NULL, then the I/O services are added to\r
797 the existing child handle.\r
798\r
799 @retval EFI_SUCCES The child handle was created with the I/O services.\r
800 @retval EFI_OUT_OF_RESOURCES There are not enough resources availabe to create\r
801 the child.\r
802 @retval other The child handle was not created.\r
803\r
804**/\r
805EFI_STATUS\r
806EFIAPI\r
807Ip6ServiceBindingCreateChild (\r
808 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
809 IN EFI_HANDLE *ChildHandle\r
810 )\r
811{\r
812 IP6_SERVICE *IpSb;\r
813 IP6_PROTOCOL *IpInstance;\r
814 EFI_TPL OldTpl;\r
815 EFI_STATUS Status;\r
816 VOID *Mnp;\r
817\r
818 if ((This == NULL) || (ChildHandle == NULL)) {\r
819 return EFI_INVALID_PARAMETER;\r
820 }\r
821\r
822 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);\r
823\r
824 if (IpSb->LinkLocalDadFail) {\r
825 return EFI_DEVICE_ERROR;\r
826 }\r
827\r
828 IpInstance = AllocatePool (sizeof (IP6_PROTOCOL));\r
829\r
830 if (IpInstance == NULL) {\r
831 return EFI_OUT_OF_RESOURCES;\r
832 }\r
833\r
834 Ip6InitProtocol (IpSb, IpInstance);\r
835\r
836 //\r
837 // Install Ip6 onto ChildHandle\r
838 //\r
839 Status = gBS->InstallMultipleProtocolInterfaces (\r
840 ChildHandle,\r
841 &gEfiIp6ProtocolGuid,\r
842 &IpInstance->Ip6Proto,\r
843 NULL\r
844 );\r
845 if (EFI_ERROR (Status)) {\r
846 goto ON_ERROR;\r
847 }\r
848\r
849 IpInstance->Handle = *ChildHandle;\r
850\r
851 //\r
852 // Open the Managed Network protocol BY_CHILD.\r
853 //\r
854 Status = gBS->OpenProtocol (\r
855 IpSb->MnpChildHandle,\r
856 &gEfiManagedNetworkProtocolGuid,\r
857 (VOID **) &Mnp,\r
858 gIp6DriverBinding.DriverBindingHandle,\r
859 IpInstance->Handle,\r
860 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER\r
861 );\r
862 if (EFI_ERROR (Status)) {\r
863 gBS->UninstallMultipleProtocolInterfaces (\r
864 ChildHandle,\r
865 &gEfiIp6ProtocolGuid,\r
866 &IpInstance->Ip6Proto,\r
867 NULL\r
868 );\r
869\r
870 goto ON_ERROR;\r
871 }\r
872\r
873 //\r
874 // Insert it into the service binding instance.\r
875 //\r
876 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
877\r
878 InsertTailList (&IpSb->Children, &IpInstance->Link);\r
879 IpSb->NumChildren++;\r
880\r
881 gBS->RestoreTPL (OldTpl);\r
882\r
883ON_ERROR:\r
884\r
885 if (EFI_ERROR (Status)) {\r
886\r
887 Ip6CleanProtocol (IpInstance);\r
888\r
889 FreePool (IpInstance);\r
890 }\r
891\r
892 return Status;\r
893}\r
894\r
895/**\r
896 Destroys a child handle with a set of I/O services.\r
897\r
898 @param[in] This Protocol instance pointer.\r
899 @param[in] ChildHandle Handle of the child to destroy.\r
900\r
901 @retval EFI_SUCCES The I/O services were removed from the child\r
902 handle.\r
903 @retval EFI_UNSUPPORTED The child handle does not support the I/O services\r
904 that are being removed.\r
15ee13fc 905 @retval EFI_INVALID_PARAMETER Child handle is NULL.\r
a3bcde70
HT
906 @retval EFI_ACCESS_DENIED The child handle could not be destroyed because\r
907 its I/O services are being used.\r
908 @retval other The child handle was not destroyed.\r
909\r
910**/\r
911EFI_STATUS\r
912EFIAPI\r
913Ip6ServiceBindingDestroyChild (\r
914 IN EFI_SERVICE_BINDING_PROTOCOL *This,\r
915 IN EFI_HANDLE ChildHandle\r
916 )\r
917{\r
918 EFI_STATUS Status;\r
919 IP6_SERVICE *IpSb;\r
920 IP6_PROTOCOL *IpInstance;\r
921 EFI_IP6_PROTOCOL *Ip6;\r
922 EFI_TPL OldTpl;\r
a3bcde70
HT
923\r
924 if ((This == NULL) || (ChildHandle == NULL)) {\r
925 return EFI_INVALID_PARAMETER;\r
926 }\r
927\r
928 //\r
929 // Retrieve the private context data structures\r
930 //\r
931 IpSb = IP6_SERVICE_FROM_PROTOCOL (This);\r
932\r
933 Status = gBS->OpenProtocol (\r
934 ChildHandle,\r
935 &gEfiIp6ProtocolGuid,\r
936 (VOID **) &Ip6,\r
937 gIp6DriverBinding.DriverBindingHandle,\r
938 ChildHandle,\r
939 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
940 );\r
941\r
942 if (EFI_ERROR (Status)) {\r
943 return EFI_UNSUPPORTED;\r
944 }\r
945\r
946 IpInstance = IP6_INSTANCE_FROM_PROTOCOL (Ip6);\r
947\r
948 if (IpInstance->Service != IpSb) {\r
949 return EFI_INVALID_PARAMETER;\r
950 }\r
951\r
952 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
953\r
954 //\r
955 // A child can be destroyed more than once. For example,\r
75dce340 956 // Ip6DriverBindingStop will destroy all of its children.\r
957 // when UDP driver is being stopped, it will destroy all\r
a3bcde70
HT
958 // the IP child it opens.\r
959 //\r
216f7970 960 if (IpInstance->InDestroy) {\r
a3bcde70
HT
961 gBS->RestoreTPL (OldTpl);\r
962 return EFI_SUCCESS;\r
963 }\r
964\r
216f7970 965 IpInstance->InDestroy = TRUE;\r
a3bcde70
HT
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 gIp6DriverBinding.DriverBindingHandle,\r
974 ChildHandle\r
975 );\r
976\r
977 //\r
978 // Uninstall the IP6 protocol first. Many thing happens during\r
979 // this:\r
980 // 1. The consumer of the IP6 protocol will be stopped if it\r
981 // opens the protocol BY_DRIVER. For eaxmple, if MNP driver is\r
982 // stopped, IP driver's stop function will be called, and uninstall\r
983 // EFI_IP6_PROTOCOL will trigger the UDP's stop function. This\r
984 // makes it possible to create the network stack bottom up, and\r
985 // stop it top down.\r
986 // 2. the upper layer will recycle the received packet. The recycle\r
987 // event's TPL is higher than this function. The recycle events\r
988 // will be called back before preceeding. If any packets not recycled,\r
989 // that means there is a resource leak.\r
990 //\r
216f7970 991 gBS->RestoreTPL (OldTpl);\r
a3bcde70
HT
992 Status = gBS->UninstallProtocolInterface (\r
993 ChildHandle,\r
994 &gEfiIp6ProtocolGuid,\r
995 &IpInstance->Ip6Proto\r
996 );\r
216f7970 997 OldTpl = gBS->RaiseTPL (TPL_CALLBACK);\r
a3bcde70
HT
998 if (EFI_ERROR (Status)) {\r
999 goto ON_ERROR;\r
1000 }\r
1001\r
1002 Status = Ip6CleanProtocol (IpInstance);\r
a3bcde70
HT
1003 if (EFI_ERROR (Status)) {\r
1004 gBS->InstallMultipleProtocolInterfaces (\r
1005 &ChildHandle,\r
1006 &gEfiIp6ProtocolGuid,\r
1007 Ip6,\r
1008 NULL\r
1009 );\r
1010\r
1011 goto ON_ERROR;\r
1012 }\r
1013\r
1014 RemoveEntryList (&IpInstance->Link);\r
1015 ASSERT (IpSb->NumChildren > 0);\r
1016 IpSb->NumChildren--;\r
1017\r
1018 gBS->RestoreTPL (OldTpl);\r
1019\r
1020 FreePool (IpInstance);\r
1021 return EFI_SUCCESS;\r
1022\r
1023ON_ERROR:\r
a3bcde70
HT
1024 gBS->RestoreTPL (OldTpl);\r
1025\r
1026 return Status;\r
1027}\r