Home | History | Annotate | Download | only in I2cDxe
      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
     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
    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
    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
    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
    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
    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
    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
    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
    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
    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
   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
   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