Ip6Driver.c 30 KB

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