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