I2cHost.c 44 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180118111821183118411851186118711881189119011911192119311941195119611971198119912001201120212031204120512061207120812091210121112121213121412151216121712181219122012211222
  1. /** @file
  2. This file implements I2C Host Protocol which provides callers with the ability to
  3. do I/O transactions to all of the devices on the I2C bus.
  4. Copyright (c) 2014, Hewlett-Packard Development Company, L.P.<BR>
  5. Copyright (c) 2013 - 2018, Intel Corporation. All rights reserved.<BR>
  6. SPDX-License-Identifier: BSD-2-Clause-Patent
  7. **/
  8. #include "I2cDxe.h"
  9. EFI_DRIVER_BINDING_PROTOCOL gI2cHostDriverBinding = {
  10. I2cHostDriverSupported,
  11. I2cHostDriverStart,
  12. I2cHostDriverStop,
  13. 0x10,
  14. NULL,
  15. NULL
  16. };
  17. //
  18. // Driver name table
  19. //
  20. GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cHostDriverNameTable[] = {
  21. { "eng;en", L"I2c Host Driver" },
  22. { NULL , NULL }
  23. };
  24. //
  25. // EFI Component Name Protocol
  26. //
  27. GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gI2cHostComponentName = {
  28. (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cHostComponentNameGetDriverName,
  29. (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cHostComponentNameGetControllerName,
  30. "eng"
  31. };
  32. //
  33. // EFI Component Name 2 Protocol
  34. //
  35. GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cHostComponentName2 = {
  36. I2cHostComponentNameGetDriverName,
  37. I2cHostComponentNameGetControllerName,
  38. "en"
  39. };
  40. /**
  41. Retrieves a Unicode string that is the user readable name of the driver.
  42. This function retrieves the user readable name of a driver in the form of a
  43. Unicode string. If the driver specified by This has a user readable name in
  44. the language specified by Language, then a pointer to the driver name is
  45. returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
  46. by This does not support the language specified by Language,
  47. then EFI_UNSUPPORTED is returned.
  48. @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
  49. EFI_COMPONENT_NAME_PROTOCOL instance.
  50. @param Language[in] A pointer to a Null-terminated ASCII string
  51. array indicating the language. This is the
  52. language of the driver name that the caller is
  53. requesting, and it must match one of the
  54. languages specified in SupportedLanguages. The
  55. number of languages supported by a driver is up
  56. to the driver writer. Language is specified
  57. in RFC 4646 or ISO 639-2 language code format.
  58. @param DriverName[out] A pointer to the Unicode string to return.
  59. This Unicode string is the name of the
  60. driver specified by This in the language
  61. specified by Language.
  62. @retval EFI_SUCCESS The Unicode string for the Driver specified by
  63. This and the language specified by Language was
  64. returned in DriverName.
  65. @retval EFI_INVALID_PARAMETER Language is NULL.
  66. @retval EFI_INVALID_PARAMETER DriverName is NULL.
  67. @retval EFI_UNSUPPORTED The driver specified by This does not support
  68. the language specified by Language.
  69. **/
  70. EFI_STATUS
  71. EFIAPI
  72. I2cHostComponentNameGetDriverName (
  73. IN EFI_COMPONENT_NAME2_PROTOCOL *This,
  74. IN CHAR8 *Language,
  75. OUT CHAR16 **DriverName
  76. )
  77. {
  78. return LookupUnicodeString2 (
  79. Language,
  80. This->SupportedLanguages,
  81. mI2cHostDriverNameTable,
  82. DriverName,
  83. (BOOLEAN)(This != &gI2cHostComponentName2)
  84. );
  85. }
  86. /**
  87. Retrieves a Unicode string that is the user readable name of the controller
  88. that is being managed by a driver.
  89. This function retrieves the user readable name of the controller specified by
  90. ControllerHandle and ChildHandle in the form of a Unicode string. If the
  91. driver specified by This has a user readable name in the language specified by
  92. Language, then a pointer to the controller name is returned in ControllerName,
  93. and EFI_SUCCESS is returned. If the driver specified by This is not currently
  94. managing the controller specified by ControllerHandle and ChildHandle,
  95. then EFI_UNSUPPORTED is returned. If the driver specified by This does not
  96. support the language specified by Language, then EFI_UNSUPPORTED is returned.
  97. @param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
  98. EFI_COMPONENT_NAME_PROTOCOL instance.
  99. @param ControllerHandle[in] The handle of a controller that the driver
  100. specified by This is managing. This handle
  101. specifies the controller whose name is to be
  102. returned.
  103. @param ChildHandle[in] The handle of the child controller to retrieve
  104. the name of. This is an optional parameter that
  105. may be NULL. It will be NULL for device
  106. drivers. It will also be NULL for a bus drivers
  107. that wish to retrieve the name of the bus
  108. controller. It will not be NULL for a bus
  109. driver that wishes to retrieve the name of a
  110. child controller.
  111. @param Language[in] A pointer to a Null-terminated ASCII string
  112. array indicating the language. This is the
  113. language of the driver name that the caller is
  114. requesting, and it must match one of the
  115. languages specified in SupportedLanguages. The
  116. number of languages supported by a driver is up
  117. to the driver writer. Language is specified in
  118. RFC 4646 or ISO 639-2 language code format.
  119. @param ControllerName[out] A pointer to the Unicode string to return.
  120. This Unicode string is the name of the
  121. controller specified by ControllerHandle and
  122. ChildHandle in the language specified by
  123. Language from the point of view of the driver
  124. specified by This.
  125. @retval EFI_SUCCESS The Unicode string for the user readable name in
  126. the language specified by Language for the
  127. driver specified by This was returned in
  128. DriverName.
  129. @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
  130. @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
  131. EFI_HANDLE.
  132. @retval EFI_INVALID_PARAMETER Language is NULL.
  133. @retval EFI_INVALID_PARAMETER ControllerName is NULL.
  134. @retval EFI_UNSUPPORTED The driver specified by This is not currently
  135. managing the controller specified by
  136. ControllerHandle and ChildHandle.
  137. @retval EFI_UNSUPPORTED The driver specified by This does not support
  138. the language specified by Language.
  139. **/
  140. EFI_STATUS
  141. EFIAPI
  142. I2cHostComponentNameGetControllerName (
  143. IN EFI_COMPONENT_NAME2_PROTOCOL *This,
  144. IN EFI_HANDLE ControllerHandle,
  145. IN EFI_HANDLE ChildHandle OPTIONAL,
  146. IN CHAR8 *Language,
  147. OUT CHAR16 **ControllerName
  148. )
  149. {
  150. return EFI_UNSUPPORTED;
  151. }
  152. /**
  153. Tests to see if this driver supports a given controller. If a child device is provided,
  154. it further tests to see if this driver supports creating a handle for the specified child device.
  155. This function checks to see if the driver specified by This supports the device specified by
  156. ControllerHandle. Drivers will typically use the device path attached to
  157. ControllerHandle and/or the services from the bus I/O abstraction attached to
  158. ControllerHandle to determine if the driver supports ControllerHandle. This function
  159. may be called many times during platform initialization. In order to reduce boot times, the tests
  160. performed by this function must be very small, and take as little time as possible to execute. This
  161. function must not change the state of any hardware devices, and this function must be aware that the
  162. device specified by ControllerHandle may already be managed by the same driver or a
  163. different driver. This function must match its calls to AllocatePages() with FreePages(),
  164. AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
  165. Since ControllerHandle may have been previously started by the same driver, if a protocol is
  166. already in the opened state, then it must not be closed with CloseProtocol(). This is required
  167. to guarantee the state of ControllerHandle is not modified by this function.
  168. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  169. @param[in] ControllerHandle The handle of the controller to test. This handle
  170. must support a protocol interface that supplies
  171. an I/O abstraction to the driver.
  172. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  173. parameter is ignored by device drivers, and is optional for bus
  174. drivers. For bus drivers, if this parameter is not NULL, then
  175. the bus driver must determine if the bus controller specified
  176. by ControllerHandle and the child controller specified
  177. by RemainingDevicePath are both supported by this
  178. bus driver.
  179. @retval EFI_SUCCESS The device specified by ControllerHandle and
  180. RemainingDevicePath is supported by the driver specified by This.
  181. @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
  182. RemainingDevicePath is already being managed by the driver
  183. specified by This.
  184. @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
  185. RemainingDevicePath is already being managed by a different
  186. driver or an application that requires exclusive access.
  187. Currently not implemented.
  188. @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
  189. RemainingDevicePath is not supported by the driver specified by This.
  190. **/
  191. EFI_STATUS
  192. EFIAPI
  193. I2cHostDriverSupported (
  194. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  195. IN EFI_HANDLE Controller,
  196. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  197. )
  198. {
  199. EFI_I2C_MASTER_PROTOCOL *I2cMaster;
  200. EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
  201. EFI_STATUS Status;
  202. //
  203. // Locate I2C Bus Configuration Management Protocol
  204. //
  205. Status = gBS->OpenProtocol (
  206. Controller,
  207. &gEfiI2cBusConfigurationManagementProtocolGuid,
  208. (VOID **)&I2cBusConfigurationManagement,
  209. This->DriverBindingHandle,
  210. Controller,
  211. EFI_OPEN_PROTOCOL_BY_DRIVER
  212. );
  213. if (EFI_ERROR (Status)) {
  214. return Status;
  215. }
  216. //
  217. // Close the protocol because we don't use it here
  218. //
  219. gBS->CloseProtocol (
  220. Controller,
  221. &gEfiI2cBusConfigurationManagementProtocolGuid,
  222. This->DriverBindingHandle,
  223. Controller
  224. );
  225. //
  226. // Locate I2C Master Protocol
  227. //
  228. Status = gBS->OpenProtocol (
  229. Controller,
  230. &gEfiI2cMasterProtocolGuid,
  231. (VOID **)&I2cMaster,
  232. This->DriverBindingHandle,
  233. Controller,
  234. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  235. );
  236. if (EFI_ERROR (Status)) {
  237. return Status;
  238. }
  239. return EFI_SUCCESS;
  240. }
  241. /**
  242. Starts a device controller or a bus controller.
  243. The Start() function is designed to be invoked from the EFI boot service ConnectController().
  244. As a result, much of the error checking on the parameters to Start() has been moved into this
  245. common boot service. It is legal to call Start() from other locations,
  246. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  247. 1. ControllerHandle must be a valid EFI_HANDLE.
  248. 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
  249. EFI_DEVICE_PATH_PROTOCOL.
  250. 3. Prior to calling Start(), the Supported() function for the driver specified by This must
  251. have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
  252. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  253. @param[in] ControllerHandle The handle of the controller to start. This handle
  254. must support a protocol interface that supplies
  255. an I/O abstraction to the driver.
  256. @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
  257. parameter is ignored by device drivers, and is optional for bus
  258. drivers. For a bus driver, if this parameter is NULL, then handles
  259. for all the children of Controller are created by this driver.
  260. If this parameter is not NULL and the first Device Path Node is
  261. not the End of Device Path Node, then only the handle for the
  262. child device specified by the first Device Path Node of
  263. RemainingDevicePath is created by this driver.
  264. If the first Device Path Node of RemainingDevicePath is
  265. the End of Device Path Node, no child handle is created by this
  266. driver.
  267. @retval EFI_SUCCESS The device was started.
  268. @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
  269. @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
  270. @retval Others The driver failded to start the device.
  271. **/
  272. EFI_STATUS
  273. EFIAPI
  274. I2cHostDriverStart (
  275. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  276. IN EFI_HANDLE Controller,
  277. IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
  278. )
  279. {
  280. EFI_STATUS Status;
  281. EFI_I2C_MASTER_PROTOCOL *I2cMaster;
  282. EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
  283. I2C_HOST_CONTEXT *I2cHostContext;
  284. I2cMaster = NULL;
  285. I2cHostContext = NULL;
  286. I2cBusConfigurationManagement = NULL;
  287. //
  288. // Locate I2C Bus Configuration Management Protocol
  289. //
  290. Status = gBS->OpenProtocol (
  291. Controller,
  292. &gEfiI2cBusConfigurationManagementProtocolGuid,
  293. (VOID **)&I2cBusConfigurationManagement,
  294. This->DriverBindingHandle,
  295. Controller,
  296. EFI_OPEN_PROTOCOL_BY_DRIVER
  297. );
  298. if (EFI_ERROR (Status)) {
  299. DEBUG ((EFI_D_ERROR, "I2cHost: Open I2C bus configuration error, Status = %r\n", Status));
  300. return Status;
  301. }
  302. //
  303. // Locate I2C Master Protocol
  304. //
  305. Status = gBS->OpenProtocol (
  306. Controller,
  307. &gEfiI2cMasterProtocolGuid,
  308. (VOID **)&I2cMaster,
  309. This->DriverBindingHandle,
  310. Controller,
  311. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  312. );
  313. if (EFI_ERROR (Status)) {
  314. DEBUG ((EFI_D_ERROR, "I2cHost: Open I2C master error, Status = %r\n", Status));
  315. goto Exit;
  316. }
  317. //
  318. // Allocate the I2C Host Context structure
  319. //
  320. I2cHostContext = AllocateZeroPool (sizeof (I2C_HOST_CONTEXT));
  321. if (I2cHostContext == NULL) {
  322. DEBUG ((EFI_D_ERROR, "I2cHost: there is no enough memory to allocate.\n"));
  323. Status = EFI_OUT_OF_RESOURCES;
  324. goto Exit;
  325. }
  326. //
  327. // Initialize the context structure for the current I2C Controller
  328. //
  329. I2cHostContext->Signature = I2C_HOST_SIGNATURE;
  330. I2cHostContext->I2cMaster = I2cMaster;
  331. I2cHostContext->I2cBusConfigurationManagement = I2cBusConfigurationManagement;
  332. I2cHostContext->I2cBusConfiguration = (UINTN) -1;
  333. InitializeListHead(&I2cHostContext->RequestList);
  334. //
  335. // Reset the controller
  336. //
  337. Status = I2cMaster->Reset (I2cMaster);
  338. if (EFI_ERROR (Status)) {
  339. DEBUG ((EFI_D_ERROR, "I2cHost: I2C controller reset failed!\n"));
  340. goto Exit;
  341. }
  342. //
  343. // Create the I2C transaction complete event
  344. //
  345. Status = gBS->CreateEvent (
  346. EVT_NOTIFY_SIGNAL,
  347. TPL_I2C_SYNC,
  348. I2cHostRequestCompleteEvent,
  349. I2cHostContext,
  350. &I2cHostContext->I2cEvent
  351. );
  352. if (EFI_ERROR (Status)) {
  353. DEBUG ((EFI_D_ERROR, "I2cHost: create complete event error, Status = %r\n", Status));
  354. goto Exit;
  355. }
  356. //
  357. // Get the bus management event
  358. //
  359. Status = gBS->CreateEvent (
  360. EVT_NOTIFY_SIGNAL,
  361. TPL_I2C_SYNC,
  362. I2cHostI2cBusConfigurationAvailable,
  363. I2cHostContext,
  364. &I2cHostContext->I2cBusConfigurationEvent
  365. );
  366. if (EFI_ERROR (Status)) {
  367. DEBUG ((EFI_D_ERROR, "I2cHost: create bus available event error, Status = %r\n", Status));
  368. goto Exit;
  369. }
  370. //
  371. // Build the I2C host protocol for the current I2C controller
  372. //
  373. I2cHostContext->I2cHost.QueueRequest = I2cHostQueueRequest;
  374. I2cHostContext->I2cHost.I2cControllerCapabilities = I2cMaster->I2cControllerCapabilities;
  375. //
  376. // Install the driver protocol
  377. //
  378. Status = gBS->InstallMultipleProtocolInterfaces (
  379. &Controller,
  380. &gEfiI2cHostProtocolGuid,
  381. &I2cHostContext->I2cHost,
  382. NULL
  383. );
  384. Exit:
  385. if (EFI_ERROR (Status)) {
  386. DEBUG ((EFI_D_ERROR, "I2cHost: Start() function failed, Status = %r\n", Status));
  387. if (I2cBusConfigurationManagement != NULL) {
  388. gBS->CloseProtocol (
  389. Controller,
  390. &gEfiI2cBusConfigurationManagementProtocolGuid,
  391. This->DriverBindingHandle,
  392. Controller
  393. );
  394. }
  395. if ((I2cHostContext != NULL) && (I2cHostContext->I2cEvent != NULL)) {
  396. gBS->CloseEvent (I2cHostContext->I2cEvent);
  397. I2cHostContext->I2cEvent = NULL;
  398. }
  399. if ((I2cHostContext != NULL) && (I2cHostContext->I2cBusConfigurationEvent != NULL)) {
  400. gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
  401. I2cHostContext->I2cBusConfigurationEvent = NULL;
  402. }
  403. //
  404. // Release the context structure upon failure
  405. //
  406. if (I2cHostContext != NULL) {
  407. FreePool (I2cHostContext);
  408. }
  409. }
  410. //
  411. // Return the operation status.
  412. //
  413. return Status;
  414. }
  415. /**
  416. Stops a device controller or a bus controller.
  417. The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
  418. As a result, much of the error checking on the parameters to Stop() has been moved
  419. into this common boot service. It is legal to call Stop() from other locations,
  420. but the following calling restrictions must be followed, or the system behavior will not be deterministic.
  421. 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
  422. same driver's Start() function.
  423. 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
  424. EFI_HANDLE. In addition, all of these handles must have been created in this driver's
  425. Start() function, and the Start() function must have called OpenProtocol() on
  426. ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
  427. @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
  428. @param[in] ControllerHandle A handle to the device being stopped. The handle must
  429. support a bus specific I/O protocol for the driver
  430. to use to stop the device.
  431. @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
  432. @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
  433. if NumberOfChildren is 0.
  434. @retval EFI_SUCCESS The device was stopped.
  435. @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
  436. **/
  437. EFI_STATUS
  438. EFIAPI
  439. I2cHostDriverStop (
  440. IN EFI_DRIVER_BINDING_PROTOCOL *This,
  441. IN EFI_HANDLE Controller,
  442. IN UINTN NumberOfChildren,
  443. IN EFI_HANDLE *ChildHandleBuffer
  444. )
  445. {
  446. EFI_STATUS Status;
  447. I2C_HOST_CONTEXT *I2cHostContext;
  448. EFI_I2C_HOST_PROTOCOL *I2cHost;
  449. EFI_TPL TplPrevious;
  450. TplPrevious = EfiGetCurrentTpl ();
  451. if (TplPrevious > TPL_I2C_SYNC) {
  452. DEBUG ((EFI_D_ERROR, "I2cHost: TPL %d is too high in Stop.\n", TplPrevious));
  453. return EFI_DEVICE_ERROR;
  454. }
  455. Status = gBS->OpenProtocol (
  456. Controller,
  457. &gEfiI2cHostProtocolGuid,
  458. (VOID **) &I2cHost,
  459. This->DriverBindingHandle,
  460. Controller,
  461. EFI_OPEN_PROTOCOL_GET_PROTOCOL
  462. );
  463. if (EFI_ERROR (Status)) {
  464. return EFI_DEVICE_ERROR;
  465. }
  466. I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (I2cHost);
  467. //
  468. // Raise TPL for critical section
  469. //
  470. TplPrevious = gBS->RaiseTPL (TPL_I2C_SYNC);
  471. //
  472. // If there is pending request or pending bus configuration, do not stop
  473. //
  474. Status = EFI_DEVICE_ERROR;
  475. if (( !I2cHostContext->I2cBusConfigurationManagementPending )
  476. && IsListEmpty (&I2cHostContext->RequestList)) {
  477. //
  478. // Remove the I2C host protocol
  479. //
  480. Status = gBS->UninstallMultipleProtocolInterfaces (
  481. Controller,
  482. &gEfiI2cHostProtocolGuid,
  483. I2cHost,
  484. NULL
  485. );
  486. }
  487. //
  488. // Leave critical section
  489. //
  490. gBS->RestoreTPL (TplPrevious);
  491. if (!EFI_ERROR (Status)) {
  492. gBS->CloseProtocol (
  493. Controller,
  494. &gEfiI2cBusConfigurationManagementProtocolGuid,
  495. This->DriverBindingHandle,
  496. Controller
  497. );
  498. //
  499. // Release I2c Host resources
  500. //
  501. if (I2cHostContext->I2cBusConfigurationEvent != NULL) {
  502. gBS->CloseEvent (I2cHostContext->I2cBusConfigurationEvent);
  503. I2cHostContext->I2cBusConfigurationEvent = NULL;
  504. }
  505. if (I2cHostContext->I2cEvent != NULL) {
  506. gBS->CloseEvent (I2cHostContext->I2cEvent);
  507. I2cHostContext->I2cEvent = NULL;
  508. }
  509. FreePool (I2cHostContext);
  510. }
  511. //
  512. // Return the stop status
  513. //
  514. return Status;
  515. }
  516. /**
  517. Handle the I2C bus configuration available event
  518. This routine is called at TPL_I2C_SYNC.
  519. @param[in] Event Address of an EFI_EVENT handle
  520. @param[in] Context Address of an I2C_HOST_CONTEXT structure
  521. **/
  522. VOID
  523. EFIAPI
  524. I2cHostI2cBusConfigurationAvailable (
  525. IN EFI_EVENT Event,
  526. IN VOID *Context
  527. )
  528. {
  529. I2C_HOST_CONTEXT *I2cHostContext;
  530. EFI_I2C_MASTER_PROTOCOL *I2cMaster;
  531. I2C_REQUEST *I2cRequest;
  532. LIST_ENTRY *EntryHeader;
  533. LIST_ENTRY *Entry;
  534. EFI_STATUS Status;
  535. //
  536. // Mark this I2C bus configuration management operation as complete
  537. //
  538. I2cHostContext = (I2C_HOST_CONTEXT *)Context;
  539. I2cMaster = I2cHostContext->I2cMaster;
  540. ASSERT (I2cMaster != NULL);
  541. //
  542. // Clear flag to indicate I2C bus configuration is finished
  543. //
  544. I2cHostContext->I2cBusConfigurationManagementPending = FALSE;
  545. //
  546. // Validate the completion status
  547. //
  548. if (EFI_ERROR (I2cHostContext->Status)) {
  549. //
  550. // Setting I2C bus configuration failed before
  551. //
  552. I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
  553. //
  554. // Unknown I2C bus configuration
  555. // Force next operation to enable the I2C bus configuration
  556. //
  557. I2cHostContext->I2cBusConfiguration = (UINTN) -1;
  558. //
  559. // Do not continue current I2C request
  560. //
  561. return;
  562. }
  563. //
  564. // Get the first request in the link with FIFO order
  565. //
  566. EntryHeader = &I2cHostContext->RequestList;
  567. Entry = GetFirstNode (EntryHeader);
  568. I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
  569. //
  570. // Update the I2C bus configuration of the current I2C request
  571. //
  572. I2cHostContext->I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
  573. //
  574. // Start an I2C operation on the host, the status is returned by I2cHostContext->Status
  575. //
  576. Status = I2cMaster->StartRequest (
  577. I2cMaster,
  578. I2cRequest->SlaveAddress,
  579. I2cRequest->RequestPacket,
  580. I2cHostContext->I2cEvent,
  581. &I2cHostContext->Status
  582. );
  583. if (EFI_ERROR (Status)) {
  584. DEBUG((DEBUG_ERROR, "I2cHostI2cBusConfigurationAvailable: Error starting I2C operation, %r\n", Status));
  585. }
  586. }
  587. /**
  588. Complete the current request
  589. This routine is called at TPL_I2C_SYNC.
  590. @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure.
  591. @param[in] Status Status of the I2C operation.
  592. @return This routine returns the input status value.
  593. **/
  594. EFI_STATUS
  595. I2cHostRequestComplete (
  596. I2C_HOST_CONTEXT *I2cHostContext,
  597. EFI_STATUS Status
  598. )
  599. {
  600. I2C_REQUEST *I2cRequest;
  601. LIST_ENTRY *EntryHeader;
  602. LIST_ENTRY *Entry;
  603. //
  604. // Remove the current I2C request from the list
  605. //
  606. EntryHeader = &I2cHostContext->RequestList;
  607. Entry = GetFirstNode (EntryHeader);
  608. I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
  609. //
  610. // Save the status for QueueRequest
  611. //
  612. if ( NULL != I2cRequest->Status ) {
  613. *I2cRequest->Status = Status;
  614. }
  615. //
  616. // Notify the user of the I2C request completion
  617. //
  618. if ( NULL != I2cRequest->Event ) {
  619. gBS->SignalEvent (I2cRequest->Event);
  620. }
  621. //
  622. // Done with this request, remove the current request from list
  623. //
  624. RemoveEntryList (&I2cRequest->Link);
  625. FreePool (I2cRequest->RequestPacket);
  626. FreePool (I2cRequest);
  627. //
  628. // If there is more I2C request, start next one
  629. //
  630. if(!IsListEmpty (EntryHeader)) {
  631. I2cHostRequestEnable (I2cHostContext);
  632. }
  633. return Status;
  634. }
  635. /**
  636. Handle the bus available event
  637. This routine is called at TPL_I2C_SYNC.
  638. @param[in] Event Address of an EFI_EVENT handle
  639. @param[in] Context Address of an I2C_HOST_CONTEXT structure
  640. **/
  641. VOID
  642. EFIAPI
  643. I2cHostRequestCompleteEvent (
  644. IN EFI_EVENT Event,
  645. IN VOID *Context
  646. )
  647. {
  648. I2C_HOST_CONTEXT *I2cHostContext;
  649. //
  650. // Handle the completion event
  651. //
  652. I2cHostContext = (I2C_HOST_CONTEXT *)Context;
  653. I2cHostRequestComplete (I2cHostContext, I2cHostContext->Status);
  654. }
  655. /**
  656. Enable access to the I2C bus configuration
  657. @param[in] I2cHostContext Address of an I2C_HOST_CONTEXT structure
  658. @retval EFI_SUCCESS The operation completed successfully.
  659. @retval EFI_ABORTED The request did not complete because the driver
  660. was shutdown.
  661. @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
  662. @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
  663. This could indicate the slave device is not present.
  664. @retval EFI_INVALID_PARAMETER RequestPacket is NULL
  665. @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
  666. @retval EFI_NO_RESPONSE The I2C device is not responding to the
  667. slave address. EFI_DEVICE_ERROR may also be
  668. returned if the controller can not distinguish
  669. when the NACK occurred.
  670. @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
  671. @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
  672. the event and then read status.
  673. @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
  674. @retval EFI_TIMEOUT The transaction did not complete within an internally
  675. specified timeout period.
  676. **/
  677. EFI_STATUS
  678. I2cHostRequestEnable (
  679. I2C_HOST_CONTEXT *I2cHostContext
  680. )
  681. {
  682. UINTN I2cBusConfiguration;
  683. CONST EFI_I2C_BUS_CONFIGURATION_MANAGEMENT_PROTOCOL *I2cBusConfigurationManagement;
  684. I2C_REQUEST *I2cRequest;
  685. EFI_STATUS Status;
  686. EFI_TPL TplPrevious;
  687. LIST_ENTRY *EntryHeader;
  688. LIST_ENTRY *Entry;
  689. //
  690. // Assume pending request
  691. //
  692. Status = EFI_NOT_READY;
  693. I2cBusConfigurationManagement = I2cHostContext->I2cBusConfigurationManagement;
  694. //
  695. // Validate the I2c bus configuration
  696. //
  697. EntryHeader = &I2cHostContext->RequestList;
  698. Entry = GetFirstNode (EntryHeader);
  699. I2cRequest = I2C_REQUEST_FROM_ENTRY (Entry);
  700. I2cBusConfiguration = I2cRequest->I2cBusConfiguration;
  701. if (I2cHostContext->I2cBusConfiguration != I2cBusConfiguration ) {
  702. //
  703. // Set flag to indicate I2C bus configuration is in progress
  704. //
  705. I2cHostContext->I2cBusConfigurationManagementPending = TRUE;
  706. //
  707. // Update bus configuration for this device's requesting bus configuration
  708. //
  709. Status = I2cBusConfigurationManagement->EnableI2cBusConfiguration (
  710. I2cBusConfigurationManagement,
  711. I2cBusConfiguration,
  712. I2cHostContext->I2cBusConfigurationEvent,
  713. &I2cHostContext->Status
  714. );
  715. } else {
  716. //
  717. // I2C bus configuration is same, no need change configuration and start I2c transaction directly
  718. //
  719. TplPrevious = gBS->RaiseTPL ( TPL_I2C_SYNC );
  720. //
  721. // Same I2C bus configuration
  722. //
  723. I2cHostContext->Status = EFI_SUCCESS;
  724. I2cHostI2cBusConfigurationAvailable (I2cHostContext->I2cBusConfigurationEvent, I2cHostContext);
  725. //
  726. // Release the thread synchronization
  727. //
  728. gBS->RestoreTPL ( TplPrevious );
  729. }
  730. return Status;
  731. }
  732. /**
  733. Queue an I2C operation for execution on the I2C controller.
  734. This routine must be called at or below TPL_NOTIFY. For synchronous
  735. requests this routine must be called at or below TPL_CALLBACK.
  736. N.B. The typical consumers of this API are the I2C bus driver and
  737. on rare occasions the I2C test application. Extreme care must be
  738. taken by other consumers of this API to prevent confusing the
  739. third party I2C drivers due to a state change at the I2C device
  740. which the third party I2C drivers did not initiate. I2C platform
  741. drivers may use this API within these guidelines.
  742. This layer uses the concept of I2C bus configurations to describe
  743. the I2C bus. An I2C bus configuration is defined as a unique
  744. setting of the multiplexers and switches in the I2C bus which
  745. enable access to one or more I2C devices. When using a switch
  746. to divide a bus, due to speed differences, the I2C platform layer
  747. would define an I2C bus configuration for the I2C devices on each
  748. side of the switch. When using a multiplexer, the I2C platform
  749. layer defines an I2C bus configuration for each of the selector
  750. values required to control the multiplexer. See Figure 1 in the
  751. <a href="http://www.nxp.com/documents/user_manual/UM10204.pdf">I<sup>2</sup>C
  752. Specification</a> for a complex I2C bus configuration.
  753. The I2C host driver processes all operations in FIFO order. Prior to
  754. performing the operation, the I2C host driver calls the I2C platform
  755. driver to reconfigure the switches and multiplexers in the I2C bus
  756. enabling access to the specified I2C device. The I2C platform driver
  757. also selects the maximum bus speed for the device. After the I2C bus
  758. is configured, the I2C host driver calls the I2C port driver to
  759. initialize the I2C controller and start the I2C operation.
  760. @param[in] This Address of an EFI_I2C_HOST_PROTOCOL instance.
  761. @param[in] I2cBusConfiguration I2C bus configuration to access the I2C
  762. device.
  763. @param[in] SlaveAddress Address of the device on the I2C bus.
  764. @param[in] Event Event to set for asynchronous operations,
  765. NULL for synchronous operations
  766. @param[in] RequestPacket Address of an EFI_I2C_REQUEST_PACKET
  767. structure describing the I2C operation
  768. @param[out] I2cStatus Optional buffer to receive the I2C operation
  769. completion status
  770. @retval EFI_SUCCESS The operation completed successfully.
  771. @retval EFI_BAD_BUFFER_SIZE The WriteBytes or ReadBytes buffer size is too large.
  772. @retval EFI_DEVICE_ERROR There was an I2C error (NACK) during the operation.
  773. This could indicate the slave device is not present.
  774. @retval EFI_INVALID_PARAMETER RequestPacket is NULL
  775. @retval EFI_INVALID_PARAMETER TPL is too high
  776. @retval EFI_NO_MAPPING Invalid I2cBusConfiguration value
  777. @retval EFI_NO_RESPONSE The I2C device is not responding to the
  778. slave address. EFI_DEVICE_ERROR may also be
  779. returned if the controller can not distinguish
  780. when the NACK occurred.
  781. @retval EFI_NOT_FOUND I2C slave address exceeds maximum address
  782. @retval EFI_NOT_READY I2C bus is busy or operation pending, wait for
  783. the event and then read status pointed to by
  784. the request packet.
  785. @retval EFI_OUT_OF_RESOURCES Insufficient memory for I2C operation
  786. @retval EFI_TIMEOUT The transaction did not complete within an internally
  787. specified timeout period.
  788. **/
  789. EFI_STATUS
  790. EFIAPI
  791. I2cHostQueueRequest (
  792. IN CONST EFI_I2C_HOST_PROTOCOL *This,
  793. IN UINTN I2cBusConfiguration,
  794. IN UINTN SlaveAddress,
  795. IN EFI_EVENT Event OPTIONAL,
  796. IN EFI_I2C_REQUEST_PACKET *RequestPacket,
  797. OUT EFI_STATUS *I2cStatus OPTIONAL
  798. )
  799. {
  800. EFI_STATUS Status;
  801. EFI_EVENT SyncEvent;
  802. EFI_TPL TplPrevious;
  803. I2C_REQUEST *I2cRequest;
  804. I2C_HOST_CONTEXT *I2cHostContext;
  805. BOOLEAN FirstRequest;
  806. UINTN RequestPacketSize;
  807. UINTN StartBit;
  808. SyncEvent = NULL;
  809. FirstRequest = FALSE;
  810. Status = EFI_SUCCESS;
  811. if (RequestPacket == NULL) {
  812. return EFI_INVALID_PARAMETER;
  813. }
  814. if ((SlaveAddress & I2C_ADDRESSING_10_BIT) != 0) {
  815. //
  816. // 10-bit address, bits 0-9 are used for 10-bit I2C slave addresses,
  817. // bits 10-30 are reserved bits and must be zero
  818. //
  819. StartBit = 10;
  820. } else {
  821. //
  822. // 7-bit address, Bits 0-6 are used for 7-bit I2C slave addresses,
  823. // bits 7-30 are reserved bits and must be zero
  824. //
  825. StartBit = 7;
  826. }
  827. if (BitFieldRead32 ((UINT32)SlaveAddress, StartBit, 30) != 0) {
  828. //
  829. // Reserved bit set in the SlaveAddress parameter
  830. //
  831. return EFI_NOT_FOUND;
  832. }
  833. I2cHostContext = I2C_HOST_CONTEXT_FROM_PROTOCOL (This);
  834. if (Event == NULL) {
  835. //
  836. // For synchronous transaction, register an event used to wait for finishing synchronous transaction
  837. //
  838. Status = gBS->CreateEvent (
  839. 0,
  840. TPL_I2C_SYNC,
  841. NULL,
  842. NULL,
  843. &SyncEvent
  844. );
  845. if (EFI_ERROR (Status)) {
  846. return Status;
  847. }
  848. }
  849. //
  850. // TPL should be at or below TPL_NOTIFY.
  851. // For synchronous requests this routine must be called at or below TPL_CALLBACK.
  852. //
  853. TplPrevious = EfiGetCurrentTpl ();
  854. if ((TplPrevious > TPL_I2C_SYNC) || ((Event == NULL) && (TplPrevious > TPL_CALLBACK))) {
  855. DEBUG ((EFI_D_ERROR, "ERROR - TPL %d is too high!\n", TplPrevious));
  856. return EFI_INVALID_PARAMETER;
  857. }
  858. //
  859. // Allocate the request structure
  860. //
  861. I2cRequest = AllocateZeroPool (sizeof (I2C_REQUEST));
  862. if (I2cRequest == NULL) {
  863. DEBUG ((EFI_D_ERROR, "WARNING - Failed to allocate I2C_REQUEST!\n"));
  864. return EFI_OUT_OF_RESOURCES;
  865. }
  866. //
  867. // Initialize the request
  868. //
  869. I2cRequest->Signature = I2C_REQUEST_SIGNATURE;
  870. I2cRequest->I2cBusConfiguration = I2cBusConfiguration;
  871. I2cRequest->SlaveAddress = SlaveAddress;
  872. I2cRequest->Event = (Event == NULL) ? SyncEvent : Event;
  873. I2cRequest->Status = I2cStatus;
  874. //
  875. // Copy request packet into private buffer, as RequestPacket may be freed during asynchronous transaction
  876. //
  877. RequestPacketSize = sizeof (UINTN) + RequestPacket->OperationCount * sizeof (EFI_I2C_OPERATION);
  878. I2cRequest->RequestPacket = AllocateZeroPool (RequestPacketSize);
  879. ASSERT (I2cRequest->RequestPacket != NULL);
  880. CopyMem (I2cRequest->RequestPacket, RequestPacket, RequestPacketSize);
  881. //
  882. // Synchronize with the other threads
  883. //
  884. gBS->RaiseTPL ( TPL_I2C_SYNC );
  885. FirstRequest = IsListEmpty (&I2cHostContext->RequestList);
  886. //
  887. // Insert new I2C request in the list
  888. //
  889. InsertTailList (&I2cHostContext->RequestList, &I2cRequest->Link);
  890. //
  891. // Release the thread synchronization
  892. //
  893. gBS->RestoreTPL (TplPrevious);
  894. if (FirstRequest) {
  895. //
  896. // Start the first I2C request, then the subsequent of I2C request will continue
  897. //
  898. Status = I2cHostRequestEnable (I2cHostContext);
  899. }
  900. if (Event != NULL) {
  901. //
  902. // For asynchronous, return EFI_SUCCESS indicating that the asynchronously I2C transaction was queued.
  903. // No real I2C operation status in I2cStatus
  904. //
  905. return EFI_SUCCESS;
  906. }
  907. //
  908. // For synchronous transaction, wait for the operation completion
  909. //
  910. do {
  911. Status = gBS->CheckEvent (SyncEvent);
  912. } while (Status == EFI_NOT_READY);
  913. //
  914. // Get the I2C operation status
  915. //
  916. Status = I2cHostContext->Status;
  917. //
  918. // Return the I2C operation status
  919. //
  920. if (I2cStatus != NULL) {
  921. *I2cStatus = Status;
  922. }
  923. //
  924. // Close the event if necessary
  925. //
  926. if (SyncEvent != NULL) {
  927. gBS->CloseEvent (SyncEvent);
  928. }
  929. return Status;
  930. }
  931. /**
  932. The user Entry Point for I2C host module. The user code starts with this function.
  933. @param[in] ImageHandle The firmware allocated handle for the EFI image.
  934. @param[in] SystemTable A pointer to the EFI System Table.
  935. @retval EFI_SUCCESS The entry point is executed successfully.
  936. @retval other Some error occurs when executing this entry point.
  937. **/
  938. EFI_STATUS
  939. EFIAPI
  940. InitializeI2cHost(
  941. IN EFI_HANDLE ImageHandle,
  942. IN EFI_SYSTEM_TABLE *SystemTable
  943. )
  944. {
  945. EFI_STATUS Status;
  946. //
  947. // Install driver model protocol(s).
  948. //
  949. Status = EfiLibInstallDriverBindingComponentName2 (
  950. ImageHandle,
  951. SystemTable,
  952. &gI2cHostDriverBinding,
  953. ImageHandle,
  954. &gI2cHostComponentName,
  955. &gI2cHostComponentName2
  956. );
  957. ASSERT_EFI_ERROR (Status);
  958. return Status;
  959. }
  960. /**
  961. This is the unload handle for I2C host module.
  962. Disconnect the driver specified by ImageHandle from all the devices in the handle database.
  963. Uninstall all the protocols installed in the driver entry point.
  964. @param[in] ImageHandle The drivers' driver image.
  965. @retval EFI_SUCCESS The image is unloaded.
  966. @retval Others Failed to unload the image.
  967. **/
  968. EFI_STATUS
  969. EFIAPI
  970. I2cHostUnload (
  971. IN EFI_HANDLE ImageHandle
  972. )
  973. {
  974. EFI_STATUS Status;
  975. EFI_HANDLE *DeviceHandleBuffer;
  976. UINTN DeviceHandleCount;
  977. UINTN Index;
  978. EFI_COMPONENT_NAME_PROTOCOL *ComponentName;
  979. EFI_COMPONENT_NAME2_PROTOCOL *ComponentName2;
  980. //
  981. // Get the list of all I2C Controller handles in the handle database.
  982. // If there is an error getting the list, then the unload
  983. // operation fails.
  984. //
  985. Status = gBS->LocateHandleBuffer (
  986. ByProtocol,
  987. &gEfiI2cHostProtocolGuid,
  988. NULL,
  989. &DeviceHandleCount,
  990. &DeviceHandleBuffer
  991. );
  992. if (!EFI_ERROR (Status)) {
  993. //
  994. // Disconnect the driver specified by ImageHandle from all
  995. // the devices in the handle database.
  996. //
  997. for (Index = 0; Index < DeviceHandleCount; Index++) {
  998. Status = gBS->DisconnectController (
  999. DeviceHandleBuffer[Index],
  1000. ImageHandle,
  1001. NULL
  1002. );
  1003. if (EFI_ERROR (Status)) {
  1004. goto Done;
  1005. }
  1006. }
  1007. }
  1008. //
  1009. // Uninstall all the protocols installed in the driver entry point
  1010. //
  1011. Status = gBS->UninstallMultipleProtocolInterfaces (
  1012. gI2cHostDriverBinding.DriverBindingHandle,
  1013. &gEfiDriverBindingProtocolGuid,
  1014. &gI2cHostDriverBinding,
  1015. NULL
  1016. );
  1017. ASSERT_EFI_ERROR (Status);
  1018. //
  1019. // Note we have to one by one uninstall the following protocols.
  1020. // It's because some of them are optionally installed based on
  1021. // the following PCD settings.
  1022. // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
  1023. // gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
  1024. // gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
  1025. // gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
  1026. //
  1027. Status = gBS->HandleProtocol (
  1028. gI2cHostDriverBinding.DriverBindingHandle,
  1029. &gEfiComponentNameProtocolGuid,
  1030. (VOID **) &ComponentName
  1031. );
  1032. if (!EFI_ERROR (Status)) {
  1033. gBS->UninstallProtocolInterface (
  1034. gI2cHostDriverBinding.DriverBindingHandle,
  1035. &gEfiComponentNameProtocolGuid,
  1036. ComponentName
  1037. );
  1038. }
  1039. Status = gBS->HandleProtocol (
  1040. gI2cHostDriverBinding.DriverBindingHandle,
  1041. &gEfiComponentName2ProtocolGuid,
  1042. (VOID **) &ComponentName2
  1043. );
  1044. if (!EFI_ERROR (Status)) {
  1045. gBS->UninstallProtocolInterface (
  1046. gI2cHostDriverBinding.DriverBindingHandle,
  1047. &gEfiComponentName2ProtocolGuid,
  1048. ComponentName2
  1049. );
  1050. }
  1051. Status = EFI_SUCCESS;
  1052. Done:
  1053. //
  1054. // Free the buffer containing the list of handles from the handle database
  1055. //
  1056. if (DeviceHandleBuffer != NULL) {
  1057. gBS->FreePool (DeviceHandleBuffer);
  1058. }
  1059. return Status;
  1060. }