DnsDriver.c 50 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137113811391140114111421143114411451146114711481149115011511152115311541155115611571158115911601161116211631164116511661167116811691170117111721173117411751176117711781179118011811182118311841185118611871188118911901191119211931194119511961197119811991200120112021203120412051206120712081209121012111212121312141215121612171218121912201221122212231224122512261227122812291230123112321233123412351236123712381239124012411242124312441245124612471248124912501251125212531254125512561257125812591260126112621263126412651266126712681269127012711272127312741275127612771278127912801281128212831284128512861287128812891290129112921293129412951296129712981299130013011302130313041305130613071308130913101311131213131314131513161317131813191320132113221323132413251326132713281329133013311332133313341335133613371338133913401341134213431344134513461347134813491350135113521353135413551356135713581359136013611362136313641365136613671368136913701371137213731374137513761377137813791380138113821383138413851386138713881389139013911392139313941395139613971398139914001401140214031404140514061407140814091410141114121413141414151416141714181419142014211422142314241425142614271428142914301431143214331434143514361437143814391440144114421443144414451446144714481449145014511452145314541455145614571458145914601461146214631464146514661467146814691470147114721473147414751476147714781479148014811482148314841485148614871488148914901491149214931494149514961497149814991500150115021503150415051506150715081509151015111512151315141515151615171518151915201521152215231524152515261527152815291530153115321533153415351536
  1. /** @file
  2. The driver binding and service binding protocol for DnsDxe driver.
  3. Copyright (c) 2015 - 2019, Intel Corporation. All rights reserved.<BR>
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. **/
  6. #include "DnsImpl.h"
  7. EFI_DRIVER_BINDING_PROTOCOL gDns4DriverBinding = {
  8. Dns4DriverBindingSupported,
  9. Dns4DriverBindingStart,
  10. Dns4DriverBindingStop,
  11. DNS_VERSION,
  12. NULL,
  13. NULL
  14. };
  15. EFI_DRIVER_BINDING_PROTOCOL gDns6DriverBinding = {
  16. Dns6DriverBindingSupported,
  17. Dns6DriverBindingStart,
  18. Dns6DriverBindingStop,
  19. DNS_VERSION,
  20. NULL,
  21. NULL
  22. };
  23. EFI_SERVICE_BINDING_PROTOCOL mDns4ServiceBinding = {
  24. Dns4ServiceBindingCreateChild,
  25. Dns4ServiceBindingDestroyChild
  26. };
  27. EFI_SERVICE_BINDING_PROTOCOL mDns6ServiceBinding = {
  28. Dns6ServiceBindingCreateChild,
  29. Dns6ServiceBindingDestroyChild
  30. };
  31. DNS_DRIVER_DATA *mDriverData = NULL;
  32. /**
  33. Destroy the DNS instance and recycle the resources.
  34. @param[in] Instance The pointer to the DNS instance.
  35. **/
  36. VOID
  37. DnsDestroyInstance (
  38. IN DNS_INSTANCE *Instance
  39. )
  40. {
  41. ZeroMem (&Instance->Dns4CfgData, sizeof (EFI_DNS4_CONFIG_DATA));
  42. ZeroMem (&Instance->Dns6CfgData, sizeof (EFI_DNS6_CONFIG_DATA));
  43. if (!NetMapIsEmpty (&Instance->Dns4TxTokens)) {
  44. Dns4InstanceCancelToken (Instance, NULL);
  45. }
  46. if (!NetMapIsEmpty (&Instance->Dns6TxTokens)) {
  47. Dns6InstanceCancelToken (Instance, NULL);
  48. }
  49. if (Instance->UdpIo != NULL) {
  50. UdpIoFreeIo (Instance->UdpIo);
  51. }
  52. FreePool (Instance);
  53. }
  54. /**
  55. Create the DNS instance and initialize it.
  56. @param[in] Service The pointer to the DNS service.
  57. @param[out] Instance The pointer to the DNS instance.
  58. @retval EFI_OUT_OF_RESOURCES Failed to allocate resources.
  59. @retval EFI_SUCCESS The DNS instance is created.
  60. **/
  61. EFI_STATUS
  62. DnsCreateInstance (
  63. IN DNS_SERVICE *Service,
  64. OUT DNS_INSTANCE **Instance
  65. )
  66. {
  67. DNS_INSTANCE *DnsIns;
  68. *Instance = NULL;
  69. DnsIns = AllocateZeroPool (sizeof (DNS_INSTANCE));
  70. if (DnsIns == NULL) {
  71. return EFI_OUT_OF_RESOURCES;
  72. }
  73. DnsIns->Signature = DNS_INSTANCE_SIGNATURE;
  74. InitializeListHead (&DnsIns->Link);
  75. DnsIns->State = DNS_STATE_UNCONFIGED;
  76. DnsIns->InDestroy = FALSE;
  77. DnsIns->Service = Service;
  78. if (Service->IpVersion == IP_VERSION_4) {
  79. CopyMem (&DnsIns->Dns4, &mDns4Protocol, sizeof (DnsIns->Dns4));
  80. NetMapInit (&DnsIns->Dns4TxTokens);
  81. } else {
  82. CopyMem (&DnsIns->Dns6, &mDns6Protocol, sizeof (DnsIns->Dns6));
  83. NetMapInit (&DnsIns->Dns6TxTokens);
  84. }
  85. DnsIns->UdpIo = UdpIoCreateIo (
  86. Service->ControllerHandle, /// NicHandle
  87. Service->ImageHandle,
  88. DnsConfigNullUdp,
  89. Service->IpVersion,
  90. DnsIns
  91. );
  92. if (DnsIns->UdpIo == NULL) {
  93. FreePool (DnsIns);
  94. return EFI_OUT_OF_RESOURCES;
  95. }
  96. *Instance = DnsIns;
  97. return EFI_SUCCESS;
  98. }
  99. /**
  100. Callback function which provided by user to remove one node in NetDestroyLinkList process.
  101. @param[in] Entry The entry to be removed.
  102. @param[in] Context Pointer to the callback context corresponds to the Context in NetDestroyLinkList.
  103. @retval EFI_SUCCESS The entry has been removed successfully.
  104. @retval Others Fail to remove the entry.
  105. **/
  106. EFI_STATUS
  107. EFIAPI
  108. DnsDestroyChildEntryInHandleBuffer (
  109. IN LIST_ENTRY *Entry,
  110. IN VOID *Context
  111. )
  112. {
  113. DNS_INSTANCE *Instance;
  114. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  115. UINTN NumberOfChildren;
  116. EFI_HANDLE *ChildHandleBuffer;
  117. if ((Entry == NULL) || (Context == NULL)) {
  118. return EFI_INVALID_PARAMETER;
  119. }
  120. Instance = NET_LIST_USER_STRUCT_S (Entry, DNS_INSTANCE, Link, DNS_INSTANCE_SIGNATURE);
  121. ServiceBinding = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ServiceBinding;
  122. NumberOfChildren = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->NumberOfChildren;
  123. ChildHandleBuffer = ((DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT *)Context)->ChildHandleBuffer;
  124. if (!NetIsInHandleBuffer (Instance->ChildHandle, NumberOfChildren, ChildHandleBuffer)) {
  125. return EFI_SUCCESS;
  126. }
  127. return ServiceBinding->DestroyChild (ServiceBinding, Instance->ChildHandle);
  128. }
  129. /**
  130. Config a NULL UDP that is used to keep the connection between UDP and DNS.
  131. Just leave the Udp child unconfigured. When UDP is unloaded,
  132. DNS will be informed with DriverBinding Stop.
  133. @param UdpIo The UDP_IO to configure
  134. @param Context The opaque parameter to the callback
  135. @retval EFI_SUCCESS It always return EFI_SUCCESS directly.
  136. **/
  137. EFI_STATUS
  138. EFIAPI
  139. DnsConfigNullUdp (
  140. IN UDP_IO *UdpIo,
  141. IN VOID *Context
  142. )
  143. {
  144. return EFI_SUCCESS;
  145. }
  146. /**
  147. Release all the resource used the DNS service binding instance.
  148. @param DnsSb The Dns service binding instance.
  149. **/
  150. VOID
  151. DnsDestroyService (
  152. IN DNS_SERVICE *DnsSb
  153. )
  154. {
  155. UdpIoFreeIo (DnsSb->ConnectUdp);
  156. if (DnsSb->TimerToGetMap != NULL) {
  157. gBS->CloseEvent (DnsSb->TimerToGetMap);
  158. }
  159. if (DnsSb->Timer != NULL) {
  160. gBS->CloseEvent (DnsSb->Timer);
  161. }
  162. FreePool (DnsSb);
  163. }
  164. /**
  165. Create then initialize a Dns service binding instance.
  166. @param Controller The controller to install the DNS service
  167. binding on
  168. @param Image The driver binding image of the DNS driver
  169. @param IpVersion IpVersion for this service
  170. @param Service The variable to receive the created service
  171. binding instance.
  172. @retval EFI_OUT_OF_RESOURCES Failed to allocate resource to create the instance.
  173. @retval EFI_DEVICE_ERROR Failed to create a NULL UDP port to keep
  174. connection with UDP.
  175. @retval EFI_SUCCESS The service instance is created for the
  176. controller.
  177. **/
  178. EFI_STATUS
  179. DnsCreateService (
  180. IN EFI_HANDLE Controller,
  181. IN EFI_HANDLE Image,
  182. IN UINT8 IpVersion,
  183. OUT DNS_SERVICE **Service
  184. )
  185. {
  186. EFI_STATUS Status;
  187. DNS_SERVICE *DnsSb;
  188. Status = EFI_SUCCESS;
  189. DnsSb = NULL;
  190. *Service = NULL;
  191. DnsSb = AllocateZeroPool (sizeof (DNS_SERVICE));
  192. if (DnsSb == NULL) {
  193. return EFI_OUT_OF_RESOURCES;
  194. }
  195. DnsSb->Signature = DNS_SERVICE_SIGNATURE;
  196. if (IpVersion == IP_VERSION_4) {
  197. DnsSb->ServiceBinding = mDns4ServiceBinding;
  198. } else {
  199. DnsSb->ServiceBinding = mDns6ServiceBinding;
  200. }
  201. DnsSb->Dns4ChildrenNum = 0;
  202. InitializeListHead (&DnsSb->Dns4ChildrenList);
  203. DnsSb->Dns6ChildrenNum = 0;
  204. InitializeListHead (&DnsSb->Dns6ChildrenList);
  205. DnsSb->ControllerHandle = Controller;
  206. DnsSb->ImageHandle = Image;
  207. DnsSb->TimerToGetMap = NULL;
  208. DnsSb->Timer = NULL;
  209. DnsSb->IpVersion = IpVersion;
  210. //
  211. // Create the timer used to time out the procedure which is used to
  212. // get the default IP address.
  213. //
  214. Status = gBS->CreateEvent (
  215. EVT_TIMER,
  216. TPL_CALLBACK,
  217. NULL,
  218. NULL,
  219. &DnsSb->TimerToGetMap
  220. );
  221. if (EFI_ERROR (Status)) {
  222. FreePool (DnsSb);
  223. return Status;
  224. }
  225. //
  226. // Create the timer to retransmit packets.
  227. //
  228. Status = gBS->CreateEvent (
  229. EVT_NOTIFY_SIGNAL | EVT_TIMER,
  230. TPL_CALLBACK,
  231. DnsOnTimerRetransmit,
  232. DnsSb,
  233. &DnsSb->Timer
  234. );
  235. if (EFI_ERROR (Status)) {
  236. if (DnsSb->TimerToGetMap != NULL) {
  237. gBS->CloseEvent (DnsSb->TimerToGetMap);
  238. }
  239. FreePool (DnsSb);
  240. return Status;
  241. }
  242. DnsSb->ConnectUdp = NULL;
  243. DnsSb->ConnectUdp = UdpIoCreateIo (
  244. Controller,
  245. Image,
  246. DnsConfigNullUdp,
  247. DnsSb->IpVersion,
  248. NULL
  249. );
  250. if (DnsSb->ConnectUdp == NULL) {
  251. if (DnsSb->TimerToGetMap != NULL) {
  252. gBS->CloseEvent (DnsSb->TimerToGetMap);
  253. }
  254. gBS->CloseEvent (DnsSb->Timer);
  255. FreePool (DnsSb);
  256. return EFI_DEVICE_ERROR;
  257. }
  258. *Service = DnsSb;
  259. return Status;
  260. }
  261. /**
  262. Unloads an image.
  263. @param ImageHandle Handle that identifies the image to be unloaded.
  264. @retval EFI_SUCCESS The image has been unloaded.
  265. @retval EFI_INVALID_PARAMETER ImageHandle is not a valid image handle.
  266. **/
  267. EFI_STATUS
  268. EFIAPI
  269. DnsUnload (
  270. IN EFI_HANDLE ImageHandle
  271. )
  272. {
  273. EFI_STATUS Status;
  274. LIST_ENTRY *Entry;
  275. DNS4_CACHE *ItemCache4;
  276. DNS4_SERVER_IP *ItemServerIp4;
  277. DNS6_CACHE *ItemCache6;
  278. DNS6_SERVER_IP *ItemServerIp6;
  279. ItemCache4 = NULL;
  280. ItemServerIp4 = NULL;
  281. ItemCache6 = NULL;
  282. ItemServerIp6 = NULL;
  283. //
  284. // Disconnect the driver specified by ImageHandle
  285. //
  286. Status = NetLibDefaultUnload (ImageHandle);
  287. if (EFI_ERROR (Status)) {
  288. return Status;
  289. }
  290. //
  291. // Free mDriverData.
  292. //
  293. if (mDriverData != NULL) {
  294. if (mDriverData->Timer != NULL) {
  295. gBS->CloseEvent (mDriverData->Timer);
  296. }
  297. while (!IsListEmpty (&mDriverData->Dns4CacheList)) {
  298. Entry = NetListRemoveHead (&mDriverData->Dns4CacheList);
  299. ASSERT (Entry != NULL);
  300. ItemCache4 = NET_LIST_USER_STRUCT (Entry, DNS4_CACHE, AllCacheLink);
  301. FreePool (ItemCache4->DnsCache.HostName);
  302. FreePool (ItemCache4->DnsCache.IpAddress);
  303. FreePool (ItemCache4);
  304. }
  305. while (!IsListEmpty (&mDriverData->Dns4ServerList)) {
  306. Entry = NetListRemoveHead (&mDriverData->Dns4ServerList);
  307. ASSERT (Entry != NULL);
  308. ItemServerIp4 = NET_LIST_USER_STRUCT (Entry, DNS4_SERVER_IP, AllServerLink);
  309. FreePool (ItemServerIp4);
  310. }
  311. while (!IsListEmpty (&mDriverData->Dns6CacheList)) {
  312. Entry = NetListRemoveHead (&mDriverData->Dns6CacheList);
  313. ASSERT (Entry != NULL);
  314. ItemCache6 = NET_LIST_USER_STRUCT (Entry, DNS6_CACHE, AllCacheLink);
  315. FreePool (ItemCache6->DnsCache.HostName);
  316. FreePool (ItemCache6->DnsCache.IpAddress);
  317. FreePool (ItemCache6);
  318. }
  319. while (!IsListEmpty (&mDriverData->Dns6ServerList)) {
  320. Entry = NetListRemoveHead (&mDriverData->Dns6ServerList);
  321. ASSERT (Entry != NULL);
  322. ItemServerIp6 = NET_LIST_USER_STRUCT (Entry, DNS6_SERVER_IP, AllServerLink);
  323. FreePool (ItemServerIp6);
  324. }
  325. FreePool (mDriverData);
  326. }
  327. return Status;
  328. }
  329. /**
  330. This is the declaration of an EFI image entry point. This entry point is
  331. the same for UEFI Applications, UEFI OS Loaders, and UEFI Drivers including
  332. both device drivers and bus drivers.
  333. @param ImageHandle The firmware allocated handle for the UEFI image.
  334. @param SystemTable A pointer to the EFI System Table.
  335. @retval EFI_SUCCESS The operation completed successfully.
  336. @retval Others An unexpected error occurred.
  337. **/
  338. EFI_STATUS
  339. EFIAPI
  340. DnsDriverEntryPoint (
  341. IN EFI_HANDLE ImageHandle,
  342. IN EFI_SYSTEM_TABLE *SystemTable
  343. )
  344. {
  345. EFI_STATUS Status;
  346. Status = EFI_SUCCESS;
  347. //
  348. // Install the Dns4 Driver Binding Protocol.
  349. //
  350. Status = EfiLibInstallDriverBindingComponentName2 (
  351. ImageHandle,
  352. SystemTable,
  353. &gDns4DriverBinding,
  354. ImageHandle,
  355. &gDnsComponentName,
  356. &gDnsComponentName2
  357. );
  358. if (EFI_ERROR (Status)) {
  359. return Status;
  360. }
  361. //
  362. // Install the Dns6 Driver Binding Protocol.
  363. //
  364. Status = EfiLibInstallDriverBindingComponentName2 (
  365. ImageHandle,
  366. SystemTable,
  367. &gDns6DriverBinding,
  368. NULL,
  369. &gDnsComponentName,
  370. &gDnsComponentName2
  371. );
  372. if (EFI_ERROR (Status)) {
  373. goto Error1;
  374. }
  375. //
  376. // Create the driver data structures.
  377. //
  378. mDriverData = AllocateZeroPool (sizeof (DNS_DRIVER_DATA));
  379. if (mDriverData == NULL) {
  380. Status = EFI_OUT_OF_RESOURCES;
  381. goto Error2;
  382. }
  383. //
  384. // Create the timer event to update DNS cache list.
  385. //
  386. Status = gBS->CreateEvent (
  387. EVT_NOTIFY_SIGNAL | EVT_TIMER,
  388. TPL_CALLBACK,
  389. DnsOnTimerUpdate,
  390. NULL,
  391. &mDriverData->Timer
  392. );
  393. if (EFI_ERROR (Status)) {
  394. goto Error3;
  395. }
  396. Status = gBS->SetTimer (mDriverData->Timer, TimerPeriodic, TICKS_PER_SECOND);
  397. if (EFI_ERROR (Status)) {
  398. goto Error4;
  399. }
  400. InitializeListHead (&mDriverData->Dns4CacheList);
  401. InitializeListHead (&mDriverData->Dns4ServerList);
  402. InitializeListHead (&mDriverData->Dns6CacheList);
  403. InitializeListHead (&mDriverData->Dns6ServerList);
  404. return Status;
  405. Error4:
  406. gBS->CloseEvent (mDriverData->Timer);
  407. Error3:
  408. FreePool (mDriverData);
  409. Error2:
  410. EfiLibUninstallDriverBindingComponentName2 (
  411. &gDns6DriverBinding,
  412. &gDnsComponentName,
  413. &gDnsComponentName2
  414. );
  415. Error1:
  416. EfiLibUninstallDriverBindingComponentName2 (
  417. &gDns4DriverBinding,
  418. &gDnsComponentName,
  419. &gDnsComponentName2
  420. );
  421. return Status;
  422. }
  423. /**
  424. Tests to see if this driver supports a given controller. If a child device is provided,
  425. it further tests to see if this driver supports creating a handle for the specified child device.
  426. This function checks to see if the driver specified by This supports the device specified by
  427. ControllerHandle. Drivers will typically use the device path attached to
  428. ControllerHandle and/or the services from the bus I/O abstraction attached to
  429. ControllerHandle to determine if the driver supports ControllerHandle. This function
  430. may be called many times during platform initialization. In order to reduce boot times, the tests
  431. performed by this function must be very small, and take as little time as possible to execute. This
  432. function must not change the state of any hardware devices, and this function must be aware that the
  433. device specified by ControllerHandle may already be managed by the same driver or a
  434. different driver. This function must match its calls to AllocatePages() with FreePages(),
  435. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  436. Because ControllerHandle may have been previously started by the same driver, if a protocol is
  437. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  438. to guarantee the state of ControllerHandle is not modified by this function.
  439. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  440. @param[in] ControllerHandle The handle of the controller to test. This handle
  441. must support a protocol interface that supplies
  442. an I/O abstraction to the driver.
  443. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  444. parameter is ignored by device drivers, and is optional for bus
  445. drivers. For bus drivers, if this parameter is not NULL, then
  446. the bus driver must determine if the bus controller specified
  447. by ControllerHandle and the child controller specified
  448. by RemainingDevicePath are both supported by this
  449. bus driver.
  450. @retval EFI_SUCCESS The device specified by ControllerHandle and
  451. RemainingDevicePath is supported by the driver specified by This.
  452. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  453. RemainingDevicePath is already being managed by the driver
  454. specified by This.
  455. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  456. RemainingDevicePath is already being managed by a different
  457. driver or an application that requires exclusive access.
  458. Currently not implemented.
  459. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  460. RemainingDevicePath is not supported by the driver specified by This.
  461. **/
  462. EFI_STATUS
  463. EFIAPI
  464. Dns4DriverBindingSupported (
  465. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  466. IN EFI_HANDLE ControllerHandle,
  467. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  468. )
  469. {
  470. EFI_STATUS Status;
  471. //
  472. // Test for the Dns4ServiceBinding Protocol.
  473. //
  474. Status = gBS->OpenProtocol (
  475. ControllerHandle,
  476. &gEfiDns4ServiceBindingProtocolGuid,
  477. NULL,
  478. This->DriverBindingHandle,
  479. ControllerHandle,
  480. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  481. );
  482. if (!EFI_ERROR (Status)) {
  483. return EFI_ALREADY_STARTED;
  484. }
  485. //
  486. // Test for the Udp4ServiceBinding Protocol.
  487. //
  488. Status = gBS->OpenProtocol (
  489. ControllerHandle,
  490. &gEfiUdp4ServiceBindingProtocolGuid,
  491. NULL,
  492. This->DriverBindingHandle,
  493. ControllerHandle,
  494. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  495. );
  496. return Status;
  497. }
  498. /**
  499. Starts a device controller or a bus controller.
  500. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  501. As a result, much of the error checking on the parameters to Start() has been moved into this
  502. common boot service. It is legal to call Start() from other locations,
  503. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  504. 1. ControllerHandle must be a valid EFI_HANDLE.
  505. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  506. EFI_DEVICE_PATH_PROTOCOL.
  507. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  508. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  509. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  510. @param[in] ControllerHandle The handle of the controller to start. This handle
  511. must support a protocol interface that supplies
  512. an I/O abstraction to the driver.
  513. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  514. parameter is ignored by device drivers, and is optional for bus
  515. drivers. For a bus driver, if this parameter is NULL, then handles
  516. for all the children of Controller are created by this driver.
  517. If this parameter is not NULL and the first Device Path Node is
  518. not the End of Device Path Node, then only the handle for the
  519. child device specified by the first Device Path Node of
  520. RemainingDevicePath is created by this driver.
  521. If the first Device Path Node of RemainingDevicePath is
  522. the End of Device Path Node, no child handle is created by this
  523. driver.
  524. @retval EFI_SUCCESS The device was started.
  525. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
  526. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  527. @retval Others The driver failed to start the device.
  528. **/
  529. EFI_STATUS
  530. EFIAPI
  531. Dns4DriverBindingStart (
  532. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  533. IN EFI_HANDLE ControllerHandle,
  534. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  535. )
  536. {
  537. DNS_SERVICE *DnsSb;
  538. EFI_STATUS Status;
  539. Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_4, &DnsSb);
  540. if (EFI_ERROR (Status)) {
  541. return Status;
  542. }
  543. ASSERT (DnsSb != NULL);
  544. Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
  545. if (EFI_ERROR (Status)) {
  546. goto ON_ERROR;
  547. }
  548. //
  549. // Install the Dns4ServiceBinding Protocol onto ControllerHandle.
  550. //
  551. Status = gBS->InstallMultipleProtocolInterfaces (
  552. &ControllerHandle,
  553. &gEfiDns4ServiceBindingProtocolGuid,
  554. &DnsSb->ServiceBinding,
  555. NULL
  556. );
  557. if (EFI_ERROR (Status)) {
  558. goto ON_ERROR;
  559. }
  560. return EFI_SUCCESS;
  561. ON_ERROR:
  562. DnsDestroyService (DnsSb);
  563. return Status;
  564. }
  565. /**
  566. Stops a device controller or a bus controller.
  567. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  568. As a result, much of the error checking on the parameters to Stop() has been moved
  569. into this common boot service. It is legal to call Stop() from other locations,
  570. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  571. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  572. same driver's Start() function.
  573. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  574. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  575. Start() function, and the Start() function must have called OpenProtocol() on
  576. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  577. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  578. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  579. support a bus specific I/O protocol for the driver
  580. to use to stop the device.
  581. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  582. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  583. if NumberOfChildren is 0.
  584. @retval EFI_SUCCESS The device was stopped.
  585. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  586. **/
  587. EFI_STATUS
  588. EFIAPI
  589. Dns4DriverBindingStop (
  590. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  591. IN EFI_HANDLE ControllerHandle,
  592. IN UINTN NumberOfChildren,
  593. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  594. )
  595. {
  596. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  597. DNS_SERVICE *DnsSb;
  598. EFI_HANDLE NicHandle;
  599. EFI_STATUS Status;
  600. LIST_ENTRY *List;
  601. DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
  602. //
  603. // DNS driver opens UDP child, So, Controller is a UDP
  604. // child handle. Locate the Nic handle first. Then get the
  605. // DNS private data back.
  606. //
  607. NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp4ProtocolGuid);
  608. if (NicHandle == NULL) {
  609. return EFI_SUCCESS;
  610. }
  611. Status = gBS->OpenProtocol (
  612. NicHandle,
  613. &gEfiDns4ServiceBindingProtocolGuid,
  614. (VOID **)&ServiceBinding,
  615. This->DriverBindingHandle,
  616. NicHandle,
  617. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  618. );
  619. if (EFI_ERROR (Status)) {
  620. return EFI_DEVICE_ERROR;
  621. }
  622. DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
  623. if (!IsListEmpty (&DnsSb->Dns4ChildrenList)) {
  624. //
  625. // Destroy the Dns child instance in ChildHandleBuffer.
  626. //
  627. List = &DnsSb->Dns4ChildrenList;
  628. Context.ServiceBinding = ServiceBinding;
  629. Context.NumberOfChildren = NumberOfChildren;
  630. Context.ChildHandleBuffer = ChildHandleBuffer;
  631. Status = NetDestroyLinkList (
  632. List,
  633. DnsDestroyChildEntryInHandleBuffer,
  634. &Context,
  635. NULL
  636. );
  637. }
  638. if ((NumberOfChildren == 0) && IsListEmpty (&DnsSb->Dns4ChildrenList)) {
  639. gBS->UninstallProtocolInterface (
  640. NicHandle,
  641. &gEfiDns4ServiceBindingProtocolGuid,
  642. ServiceBinding
  643. );
  644. DnsDestroyService (DnsSb);
  645. if (gDnsControllerNameTable != NULL) {
  646. FreeUnicodeStringTable (gDnsControllerNameTable);
  647. gDnsControllerNameTable = NULL;
  648. }
  649. Status = EFI_SUCCESS;
  650. }
  651. return Status;
  652. }
  653. /**
  654. Tests to see if this driver supports a given controller. If a child device is provided,
  655. it further tests to see if this driver supports creating a handle for the specified child device.
  656. This function checks to see if the driver specified by This supports the device specified by
  657. ControllerHandle. Drivers will typically use the device path attached to
  658. ControllerHandle and/or the services from the bus I/O abstraction attached to
  659. ControllerHandle to determine if the driver supports ControllerHandle. This function
  660. may be called many times during platform initialization. In order to reduce boot times, the tests
  661. performed by this function must be very small, and take as little time as possible to execute. This
  662. function must not change the state of any hardware devices, and this function must be aware that the
  663. device specified by ControllerHandle may already be managed by the same driver or a
  664. different driver. This function must match its calls to AllocatePages() with FreePages(),
  665. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  666. Because ControllerHandle may have been previously started by the same driver, if a protocol is
  667. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  668. to guarantee the state of ControllerHandle is not modified by this function.
  669. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  670. @param[in] ControllerHandle The handle of the controller to test. This handle
  671. must support a protocol interface that supplies
  672. an I/O abstraction to the driver.
  673. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  674. parameter is ignored by device drivers, and is optional for bus
  675. drivers. For bus drivers, if this parameter is not NULL, then
  676. the bus driver must determine if the bus controller specified
  677. by ControllerHandle and the child controller specified
  678. by RemainingDevicePath are both supported by this
  679. bus driver.
  680. @retval EFI_SUCCESS The device specified by ControllerHandle and
  681. RemainingDevicePath is supported by the driver specified by This.
  682. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  683. RemainingDevicePath is already being managed by the driver
  684. specified by This.
  685. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  686. RemainingDevicePath is already being managed by a different
  687. driver or an application that requires exclusive access.
  688. Currently not implemented.
  689. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  690. RemainingDevicePath is not supported by the driver specified by This.
  691. **/
  692. EFI_STATUS
  693. EFIAPI
  694. Dns6DriverBindingSupported (
  695. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  696. IN EFI_HANDLE ControllerHandle,
  697. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  698. )
  699. {
  700. EFI_STATUS Status;
  701. //
  702. // Test for the Dns6ServiceBinding Protocol
  703. //
  704. Status = gBS->OpenProtocol (
  705. ControllerHandle,
  706. &gEfiDns6ServiceBindingProtocolGuid,
  707. NULL,
  708. This->DriverBindingHandle,
  709. ControllerHandle,
  710. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  711. );
  712. if (!EFI_ERROR (Status)) {
  713. return EFI_ALREADY_STARTED;
  714. }
  715. //
  716. // Test for the Udp6ServiceBinding Protocol
  717. //
  718. Status = gBS->OpenProtocol (
  719. ControllerHandle,
  720. &gEfiUdp6ServiceBindingProtocolGuid,
  721. NULL,
  722. This->DriverBindingHandle,
  723. ControllerHandle,
  724. EFI_OPEN_PROTOCOL_TEST_PROTOCOL
  725. );
  726. return Status;
  727. }
  728. /**
  729. Starts a device controller or a bus controller.
  730. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  731. As a result, much of the error checking on the parameters to Start() has been moved into this
  732. common boot service. It is legal to call Start() from other locations,
  733. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  734. 1. ControllerHandle must be a valid EFI_HANDLE.
  735. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  736. EFI_DEVICE_PATH_PROTOCOL.
  737. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  738. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  739. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  740. @param[in] ControllerHandle The handle of the controller to start. This handle
  741. must support a protocol interface that supplies
  742. an I/O abstraction to the driver.
  743. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  744. parameter is ignored by device drivers, and is optional for bus
  745. drivers. For a bus driver, if this parameter is NULL, then handles
  746. for all the children of Controller are created by this driver.
  747. If this parameter is not NULL and the first Device Path Node is
  748. not the End of Device Path Node, then only the handle for the
  749. child device specified by the first Device Path Node of
  750. RemainingDevicePath is created by this driver.
  751. If the first Device Path Node of RemainingDevicePath is
  752. the End of Device Path Node, no child handle is created by this
  753. driver.
  754. @retval EFI_SUCCESS The device was started.
  755. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
  756. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  757. @retval Others The driver failed to start the device.
  758. **/
  759. EFI_STATUS
  760. EFIAPI
  761. Dns6DriverBindingStart (
  762. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  763. IN EFI_HANDLE ControllerHandle,
  764. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath OPTIONAL
  765. )
  766. {
  767. DNS_SERVICE *DnsSb;
  768. EFI_STATUS Status;
  769. Status = DnsCreateService (ControllerHandle, This->DriverBindingHandle, IP_VERSION_6, &DnsSb);
  770. if (EFI_ERROR (Status)) {
  771. return Status;
  772. }
  773. ASSERT (DnsSb != NULL);
  774. Status = gBS->SetTimer (DnsSb->Timer, TimerPeriodic, TICKS_PER_SECOND);
  775. if (EFI_ERROR (Status)) {
  776. goto ON_ERROR;
  777. }
  778. //
  779. // Install the Dns6ServiceBinding Protocol onto ControllerHandle
  780. //
  781. Status = gBS->InstallMultipleProtocolInterfaces (
  782. &ControllerHandle,
  783. &gEfiDns6ServiceBindingProtocolGuid,
  784. &DnsSb->ServiceBinding,
  785. NULL
  786. );
  787. if (EFI_ERROR (Status)) {
  788. goto ON_ERROR;
  789. }
  790. return EFI_SUCCESS;
  791. ON_ERROR:
  792. DnsDestroyService (DnsSb);
  793. return Status;
  794. }
  795. /**
  796. Stops a device controller or a bus controller.
  797. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  798. As a result, much of the error checking on the parameters to Stop() has been moved
  799. into this common boot service. It is legal to call Stop() from other locations,
  800. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  801. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  802. same driver's Start() function.
  803. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  804. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  805. Start() function, and the Start() function must have called OpenProtocol() on
  806. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  807. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  808. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  809. support a bus specific I/O protocol for the driver
  810. to use to stop the device.
  811. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  812. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  813. if NumberOfChildren is 0.
  814. @retval EFI_SUCCESS The device was stopped.
  815. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  816. **/
  817. EFI_STATUS
  818. EFIAPI
  819. Dns6DriverBindingStop (
  820. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  821. IN EFI_HANDLE ControllerHandle,
  822. IN UINTN NumberOfChildren,
  823. IN EFI_HANDLE *ChildHandleBuffer OPTIONAL
  824. )
  825. {
  826. EFI_SERVICE_BINDING_PROTOCOL *ServiceBinding;
  827. DNS_SERVICE *DnsSb;
  828. EFI_HANDLE NicHandle;
  829. EFI_STATUS Status;
  830. LIST_ENTRY *List;
  831. DNS_DESTROY_CHILD_IN_HANDLE_BUF_CONTEXT Context;
  832. //
  833. // DNS driver opens UDP child, So, Controller is a UDP
  834. // child handle. Locate the Nic handle first. Then get the
  835. // DNS private data back.
  836. //
  837. NicHandle = NetLibGetNicHandle (ControllerHandle, &gEfiUdp6ProtocolGuid);
  838. if (NicHandle == NULL) {
  839. return EFI_SUCCESS;
  840. }
  841. Status = gBS->OpenProtocol (
  842. NicHandle,
  843. &gEfiDns6ServiceBindingProtocolGuid,
  844. (VOID **)&ServiceBinding,
  845. This->DriverBindingHandle,
  846. NicHandle,
  847. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  848. );
  849. if (EFI_ERROR (Status)) {
  850. return EFI_DEVICE_ERROR;
  851. }
  852. DnsSb = DNS_SERVICE_FROM_THIS (ServiceBinding);
  853. if (!IsListEmpty (&DnsSb->Dns6ChildrenList)) {
  854. //
  855. // Destroy the Dns child instance in ChildHandleBuffer.
  856. //
  857. List = &DnsSb->Dns6ChildrenList;
  858. Context.ServiceBinding = ServiceBinding;
  859. Context.NumberOfChildren = NumberOfChildren;
  860. Context.ChildHandleBuffer = ChildHandleBuffer;
  861. Status = NetDestroyLinkList (
  862. List,
  863. DnsDestroyChildEntryInHandleBuffer,
  864. &Context,
  865. NULL
  866. );
  867. }
  868. if ((NumberOfChildren == 0) && IsListEmpty (&DnsSb->Dns6ChildrenList)) {
  869. gBS->UninstallProtocolInterface (
  870. NicHandle,
  871. &gEfiDns6ServiceBindingProtocolGuid,
  872. ServiceBinding
  873. );
  874. DnsDestroyService (DnsSb);
  875. if (gDnsControllerNameTable != NULL) {
  876. FreeUnicodeStringTable (gDnsControllerNameTable);
  877. gDnsControllerNameTable = NULL;
  878. }
  879. Status = EFI_SUCCESS;
  880. }
  881. return Status;
  882. }
  883. /**
  884. Creates a child handle and installs a protocol.
  885. The CreateChild() function installs a protocol on ChildHandle.
  886. If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
  887. If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
  888. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  889. @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
  890. then a new handle is created. If it is a pointer to an existing UEFI handle,
  891. then the protocol is added to the existing UEFI handle.
  892. @retval EFI_SUCCESS The protocol was added to ChildHandle.
  893. @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
  894. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
  895. the child
  896. @retval other The child handle was not created
  897. **/
  898. EFI_STATUS
  899. EFIAPI
  900. Dns4ServiceBindingCreateChild (
  901. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  902. IN EFI_HANDLE *ChildHandle
  903. )
  904. {
  905. DNS_SERVICE *DnsSb;
  906. DNS_INSTANCE *Instance;
  907. EFI_STATUS Status;
  908. EFI_TPL OldTpl;
  909. VOID *Udp4;
  910. if ((This == NULL) || (ChildHandle == NULL)) {
  911. return EFI_INVALID_PARAMETER;
  912. }
  913. DnsSb = DNS_SERVICE_FROM_THIS (This);
  914. Status = DnsCreateInstance (DnsSb, &Instance);
  915. if (EFI_ERROR (Status)) {
  916. return Status;
  917. }
  918. ASSERT (Instance != NULL);
  919. //
  920. // Install the DNS protocol onto ChildHandle
  921. //
  922. Status = gBS->InstallMultipleProtocolInterfaces (
  923. ChildHandle,
  924. &gEfiDns4ProtocolGuid,
  925. &Instance->Dns4,
  926. NULL
  927. );
  928. if (EFI_ERROR (Status)) {
  929. goto ON_ERROR;
  930. }
  931. Instance->ChildHandle = *ChildHandle;
  932. //
  933. // Open the Udp4 protocol BY_CHILD.
  934. //
  935. Status = gBS->OpenProtocol (
  936. DnsSb->ConnectUdp->UdpHandle,
  937. &gEfiUdp4ProtocolGuid,
  938. (VOID **)&Udp4,
  939. gDns4DriverBinding.DriverBindingHandle,
  940. Instance->ChildHandle,
  941. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  942. );
  943. if (EFI_ERROR (Status)) {
  944. gBS->UninstallMultipleProtocolInterfaces (
  945. Instance->ChildHandle,
  946. &gEfiDns4ProtocolGuid,
  947. &Instance->Dns4,
  948. NULL
  949. );
  950. goto ON_ERROR;
  951. }
  952. //
  953. // Open the Udp4 protocol by child.
  954. //
  955. Status = gBS->OpenProtocol (
  956. Instance->UdpIo->UdpHandle,
  957. &gEfiUdp4ProtocolGuid,
  958. (VOID **)&Udp4,
  959. gDns4DriverBinding.DriverBindingHandle,
  960. Instance->ChildHandle,
  961. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  962. );
  963. if (EFI_ERROR (Status)) {
  964. //
  965. // Close the Udp4 protocol.
  966. //
  967. gBS->CloseProtocol (
  968. DnsSb->ConnectUdp->UdpHandle,
  969. &gEfiUdp4ProtocolGuid,
  970. gDns4DriverBinding.DriverBindingHandle,
  971. *ChildHandle
  972. );
  973. gBS->UninstallMultipleProtocolInterfaces (
  974. Instance->ChildHandle,
  975. &gEfiDns4ProtocolGuid,
  976. &Instance->Dns4,
  977. NULL
  978. );
  979. goto ON_ERROR;
  980. }
  981. //
  982. // Add it to the parent's child list.
  983. //
  984. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  985. InsertTailList (&DnsSb->Dns4ChildrenList, &Instance->Link);
  986. DnsSb->Dns4ChildrenNum++;
  987. gBS->RestoreTPL (OldTpl);
  988. return EFI_SUCCESS;
  989. ON_ERROR:
  990. DnsDestroyInstance (Instance);
  991. return Status;
  992. }
  993. /**
  994. Destroys a child handle with a protocol installed on it.
  995. The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
  996. that was installed by CreateChild() from ChildHandle. If the removed protocol is the
  997. last protocol on ChildHandle, then ChildHandle is destroyed.
  998. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  999. @param[in] ChildHandle Handle of the child to destroy
  1000. @retval EFI_SUCCESS The protocol was removed from ChildHandle.
  1001. @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
  1002. @retval EFI_INVALID_PARAMETER Child handle is NULL.
  1003. @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
  1004. because its services are being used.
  1005. @retval other The child handle was not destroyed
  1006. **/
  1007. EFI_STATUS
  1008. EFIAPI
  1009. Dns4ServiceBindingDestroyChild (
  1010. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  1011. IN EFI_HANDLE ChildHandle
  1012. )
  1013. {
  1014. DNS_SERVICE *DnsSb;
  1015. DNS_INSTANCE *Instance;
  1016. EFI_DNS4_PROTOCOL *Dns4;
  1017. EFI_STATUS Status;
  1018. EFI_TPL OldTpl;
  1019. if ((This == NULL) || (ChildHandle == NULL)) {
  1020. return EFI_INVALID_PARAMETER;
  1021. }
  1022. //
  1023. // Retrieve the private context data structures
  1024. //
  1025. Status = gBS->OpenProtocol (
  1026. ChildHandle,
  1027. &gEfiDns4ProtocolGuid,
  1028. (VOID **)&Dns4,
  1029. gDns4DriverBinding.DriverBindingHandle,
  1030. ChildHandle,
  1031. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  1032. );
  1033. if (EFI_ERROR (Status)) {
  1034. return EFI_UNSUPPORTED;
  1035. }
  1036. Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL4 (Dns4);
  1037. DnsSb = DNS_SERVICE_FROM_THIS (This);
  1038. if (Instance->Service != DnsSb) {
  1039. return EFI_INVALID_PARAMETER;
  1040. }
  1041. if (Instance->InDestroy) {
  1042. return EFI_SUCCESS;
  1043. }
  1044. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1045. Instance->InDestroy = TRUE;
  1046. //
  1047. // Close the Udp4 protocol.
  1048. //
  1049. gBS->CloseProtocol (
  1050. DnsSb->ConnectUdp->UdpHandle,
  1051. &gEfiUdp4ProtocolGuid,
  1052. gDns4DriverBinding.DriverBindingHandle,
  1053. ChildHandle
  1054. );
  1055. gBS->CloseProtocol (
  1056. Instance->UdpIo->UdpHandle,
  1057. &gEfiUdp4ProtocolGuid,
  1058. gDns4DriverBinding.DriverBindingHandle,
  1059. ChildHandle
  1060. );
  1061. gBS->RestoreTPL (OldTpl);
  1062. //
  1063. // Uninstall the DNS protocol first to enable a top down destruction.
  1064. //
  1065. Status = gBS->UninstallProtocolInterface (
  1066. ChildHandle,
  1067. &gEfiDns4ProtocolGuid,
  1068. Dns4
  1069. );
  1070. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1071. if (EFI_ERROR (Status)) {
  1072. Instance->InDestroy = FALSE;
  1073. gBS->RestoreTPL (OldTpl);
  1074. return Status;
  1075. }
  1076. RemoveEntryList (&Instance->Link);
  1077. DnsSb->Dns4ChildrenNum--;
  1078. gBS->RestoreTPL (OldTpl);
  1079. DnsDestroyInstance (Instance);
  1080. return EFI_SUCCESS;
  1081. }
  1082. /**
  1083. Creates a child handle and installs a protocol.
  1084. The CreateChild() function installs a protocol on ChildHandle.
  1085. If ChildHandle is a pointer to NULL, then a new handle is created and returned in ChildHandle.
  1086. If ChildHandle is not a pointer to NULL, then the protocol installs on the existing ChildHandle.
  1087. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  1088. @param[in] ChildHandle Pointer to the handle of the child to create. If it is NULL,
  1089. then a new handle is created. If it is a pointer to an existing UEFI handle,
  1090. then the protocol is added to the existing UEFI handle.
  1091. @retval EFI_SUCCESS The protocol was added to ChildHandle.
  1092. @retval EFI_INVALID_PARAMETER ChildHandle is NULL.
  1093. @retval EFI_OUT_OF_RESOURCES There are not enough resources available to create
  1094. the child
  1095. @retval other The child handle was not created
  1096. **/
  1097. EFI_STATUS
  1098. EFIAPI
  1099. Dns6ServiceBindingCreateChild (
  1100. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  1101. IN EFI_HANDLE *ChildHandle
  1102. )
  1103. {
  1104. DNS_SERVICE *DnsSb;
  1105. DNS_INSTANCE *Instance;
  1106. EFI_STATUS Status;
  1107. EFI_TPL OldTpl;
  1108. VOID *Udp6;
  1109. if ((This == NULL) || (ChildHandle == NULL)) {
  1110. return EFI_INVALID_PARAMETER;
  1111. }
  1112. DnsSb = DNS_SERVICE_FROM_THIS (This);
  1113. Status = DnsCreateInstance (DnsSb, &Instance);
  1114. if (EFI_ERROR (Status)) {
  1115. return Status;
  1116. }
  1117. ASSERT (Instance != NULL);
  1118. //
  1119. // Install the DNS protocol onto ChildHandle
  1120. //
  1121. Status = gBS->InstallMultipleProtocolInterfaces (
  1122. ChildHandle,
  1123. &gEfiDns6ProtocolGuid,
  1124. &Instance->Dns6,
  1125. NULL
  1126. );
  1127. if (EFI_ERROR (Status)) {
  1128. goto ON_ERROR;
  1129. }
  1130. Instance->ChildHandle = *ChildHandle;
  1131. //
  1132. // Open the Udp6 protocol BY_CHILD.
  1133. //
  1134. Status = gBS->OpenProtocol (
  1135. DnsSb->ConnectUdp->UdpHandle,
  1136. &gEfiUdp6ProtocolGuid,
  1137. (VOID **)&Udp6,
  1138. gDns6DriverBinding.DriverBindingHandle,
  1139. Instance->ChildHandle,
  1140. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  1141. );
  1142. if (EFI_ERROR (Status)) {
  1143. gBS->UninstallMultipleProtocolInterfaces (
  1144. Instance->ChildHandle,
  1145. &gEfiDns6ProtocolGuid,
  1146. &Instance->Dns6,
  1147. NULL
  1148. );
  1149. goto ON_ERROR;
  1150. }
  1151. //
  1152. // Open the Udp6 protocol by child.
  1153. //
  1154. Status = gBS->OpenProtocol (
  1155. Instance->UdpIo->UdpHandle,
  1156. &gEfiUdp6ProtocolGuid,
  1157. (VOID **)&Udp6,
  1158. gDns6DriverBinding.DriverBindingHandle,
  1159. Instance->ChildHandle,
  1160. EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
  1161. );
  1162. if (EFI_ERROR (Status)) {
  1163. //
  1164. // Close the Udp6 protocol.
  1165. //
  1166. gBS->CloseProtocol (
  1167. DnsSb->ConnectUdp->UdpHandle,
  1168. &gEfiUdp6ProtocolGuid,
  1169. gDns6DriverBinding.DriverBindingHandle,
  1170. *ChildHandle
  1171. );
  1172. gBS->UninstallMultipleProtocolInterfaces (
  1173. Instance->ChildHandle,
  1174. &gEfiDns6ProtocolGuid,
  1175. &Instance->Dns6,
  1176. NULL
  1177. );
  1178. goto ON_ERROR;
  1179. }
  1180. //
  1181. // Add it to the parent's child list.
  1182. //
  1183. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1184. InsertTailList (&DnsSb->Dns6ChildrenList, &Instance->Link);
  1185. DnsSb->Dns6ChildrenNum++;
  1186. gBS->RestoreTPL (OldTpl);
  1187. return EFI_SUCCESS;
  1188. ON_ERROR:
  1189. DnsDestroyInstance (Instance);
  1190. return Status;
  1191. }
  1192. /**
  1193. Destroys a child handle with a protocol installed on it.
  1194. The DestroyChild() function does the opposite of CreateChild(). It removes a protocol
  1195. that was installed by CreateChild() from ChildHandle. If the removed protocol is the
  1196. last protocol on ChildHandle, then ChildHandle is destroyed.
  1197. @param[in] This Pointer to the EFI_SERVICE_BINDING_PROTOCOL instance.
  1198. @param[in] ChildHandle Handle of the child to destroy
  1199. @retval EFI_SUCCESS The protocol was removed from ChildHandle.
  1200. @retval EFI_UNSUPPORTED ChildHandle does not support the protocol that is being removed.
  1201. @retval EFI_INVALID_PARAMETER Child handle is NULL.
  1202. @retval EFI_ACCESS_DENIED The protocol could not be removed from the ChildHandle
  1203. because its services are being used.
  1204. @retval other The child handle was not destroyed
  1205. **/
  1206. EFI_STATUS
  1207. EFIAPI
  1208. Dns6ServiceBindingDestroyChild (
  1209. IN EFI_SERVICE_BINDING_PROTOCOL *This,
  1210. IN EFI_HANDLE ChildHandle
  1211. )
  1212. {
  1213. DNS_SERVICE *DnsSb;
  1214. DNS_INSTANCE *Instance;
  1215. EFI_DNS6_PROTOCOL *Dns6;
  1216. EFI_STATUS Status;
  1217. EFI_TPL OldTpl;
  1218. if ((This == NULL) || (ChildHandle == NULL)) {
  1219. return EFI_INVALID_PARAMETER;
  1220. }
  1221. //
  1222. // Retrieve the private context data structures
  1223. //
  1224. Status = gBS->OpenProtocol (
  1225. ChildHandle,
  1226. &gEfiDns6ProtocolGuid,
  1227. (VOID **)&Dns6,
  1228. gDns6DriverBinding.DriverBindingHandle,
  1229. ChildHandle,
  1230. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  1231. );
  1232. if (EFI_ERROR (Status)) {
  1233. return EFI_UNSUPPORTED;
  1234. }
  1235. Instance = DNS_INSTANCE_FROM_THIS_PROTOCOL6 (Dns6);
  1236. DnsSb = DNS_SERVICE_FROM_THIS (This);
  1237. if (Instance->Service != DnsSb) {
  1238. return EFI_INVALID_PARAMETER;
  1239. }
  1240. if (Instance->InDestroy) {
  1241. return EFI_SUCCESS;
  1242. }
  1243. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1244. Instance->InDestroy = TRUE;
  1245. //
  1246. // Close the Udp6 protocol.
  1247. //
  1248. gBS->CloseProtocol (
  1249. DnsSb->ConnectUdp->UdpHandle,
  1250. &gEfiUdp6ProtocolGuid,
  1251. gDns6DriverBinding.DriverBindingHandle,
  1252. ChildHandle
  1253. );
  1254. gBS->CloseProtocol (
  1255. Instance->UdpIo->UdpHandle,
  1256. &gEfiUdp6ProtocolGuid,
  1257. gDns6DriverBinding.DriverBindingHandle,
  1258. ChildHandle
  1259. );
  1260. gBS->RestoreTPL (OldTpl);
  1261. //
  1262. // Uninstall the DNS protocol first to enable a top down destruction.
  1263. //
  1264. Status = gBS->UninstallProtocolInterface (
  1265. ChildHandle,
  1266. &gEfiDns6ProtocolGuid,
  1267. Dns6
  1268. );
  1269. OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
  1270. if (EFI_ERROR (Status)) {
  1271. Instance->InDestroy = FALSE;
  1272. gBS->RestoreTPL (OldTpl);
  1273. return Status;
  1274. }
  1275. RemoveEntryList (&Instance->Link);
  1276. DnsSb->Dns6ChildrenNum--;
  1277. gBS->RestoreTPL (OldTpl);
  1278. DnsDestroyInstance (Instance);
  1279. return EFI_SUCCESS;
  1280. }