Home | History | Annotate | Download | only in I2cDxe
      1 /** @file
      2   This file implements I2C IO Protocol which enables the user to manipulate a single
      3   I2C device independent of the host controller and I2C design.
      4 
      5   Copyright (c) 2013 - 2015, Intel Corporation. All rights reserved.<BR>
      6   This program and the accompanying materials
      7   are licensed and made available under the terms and conditions of the BSD License
      8   which accompanies this distribution.  The full text of the license may be found at
      9   http://opensource.org/licenses/bsd-license.php
     10 
     11   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
     12   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
     13 
     14 **/
     15 
     16 #include "I2cDxe.h"
     17 
     18 //
     19 //  EFI_DRIVER_BINDING_PROTOCOL instance
     20 //
     21 EFI_DRIVER_BINDING_PROTOCOL gI2cBusDriverBinding = {
     22   I2cBusDriverSupported,
     23   I2cBusDriverStart,
     24   I2cBusDriverStop,
     25   0x10,
     26   NULL,
     27   NULL
     28 };
     29 
     30 //
     31 // Template for I2C Bus Child Device.
     32 //
     33 I2C_DEVICE_CONTEXT gI2cDeviceContextTemplate = {
     34   I2C_DEVICE_SIGNATURE,
     35   NULL,
     36   {                     // I2cIo Protocol
     37     I2cBusQueueRequest, // QueueRequest
     38     NULL,               // DeviceGuid
     39     0,                  // DeviceIndex
     40     0,                  // HardwareRevision
     41     NULL                // I2cControllerCapabilities
     42   },
     43   NULL,                 // DevicePath
     44   NULL,                 // I2cDevice
     45   NULL,                 // I2cBusContext
     46 };
     47 
     48 //
     49 // Template for controller device path node.
     50 //
     51 CONTROLLER_DEVICE_PATH gControllerDevicePathTemplate = {
     52   {
     53     HARDWARE_DEVICE_PATH,
     54     HW_CONTROLLER_DP,
     55     {
     56       (UINT8) (sizeof (CONTROLLER_DEVICE_PATH)),
     57       (UINT8) ((sizeof (CONTROLLER_DEVICE_PATH)) >> 8)
     58     }
     59   },
     60   0
     61 };
     62 
     63 //
     64 // Template for vendor device path node.
     65 //
     66 VENDOR_DEVICE_PATH gVendorDevicePathTemplate = {
     67   {
     68     HARDWARE_DEVICE_PATH,
     69     HW_VENDOR_DP,
     70     {
     71       (UINT8) (sizeof (VENDOR_DEVICE_PATH)),
     72       (UINT8) ((sizeof (VENDOR_DEVICE_PATH)) >> 8)
     73     }
     74   },
     75   { 0x0, 0x0, 0x0, { 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0, 0x0 }}
     76 };
     77 
     78 //
     79 // Driver name table
     80 //
     81 GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mI2cBusDriverNameTable[] = {
     82   { "eng;en", (CHAR16 *) L"I2C Bus Driver" },
     83   { NULL , NULL }
     84 };
     85 
     86 //
     87 // EFI Component Name Protocol
     88 //
     89 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL  gI2cBusComponentName = {
     90   (EFI_COMPONENT_NAME_GET_DRIVER_NAME) I2cBusComponentNameGetDriverName,
     91   (EFI_COMPONENT_NAME_GET_CONTROLLER_NAME) I2cBusComponentNameGetControllerName,
     92   "eng"
     93 };
     94 
     95 //
     96 // EFI Component Name 2 Protocol
     97 //
     98 GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gI2cBusComponentName2 = {
     99   I2cBusComponentNameGetDriverName,
    100   I2cBusComponentNameGetControllerName,
    101   "en"
    102 };
    103 
    104 /**
    105   Retrieves a Unicode string that is the user readable name of the driver.
    106 
    107   This function retrieves the user readable name of a driver in the form of a
    108   Unicode string. If the driver specified by This has a user readable name in
    109   the language specified by Language, then a pointer to the driver name is
    110   returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
    111   by This does not support the language specified by Language,
    112   then EFI_UNSUPPORTED is returned.
    113 
    114   @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
    115                                 EFI_COMPONENT_NAME_PROTOCOL instance.
    116 
    117   @param  Language[in]          A pointer to a Null-terminated ASCII string
    118                                 array indicating the language. This is the
    119                                 language of the driver name that the caller is
    120                                 requesting, and it must match one of the
    121                                 languages specified in SupportedLanguages. The
    122                                 number of languages supported by a driver is up
    123                                 to the driver writer. Language is specified
    124                                 in RFC 4646 or ISO 639-2 language code format.
    125 
    126   @param  DriverName[out]       A pointer to the Unicode string to return.
    127                                 This Unicode string is the name of the
    128                                 driver specified by This in the language
    129                                 specified by Language.
    130 
    131   @retval EFI_SUCCESS           The Unicode string for the Driver specified by
    132                                 This and the language specified by Language was
    133                                 returned in DriverName.
    134 
    135   @retval EFI_INVALID_PARAMETER Language is NULL.
    136 
    137   @retval EFI_INVALID_PARAMETER DriverName is NULL.
    138 
    139   @retval EFI_UNSUPPORTED       The driver specified by This does not support
    140                                 the language specified by Language.
    141 
    142 **/
    143 EFI_STATUS
    144 EFIAPI
    145 I2cBusComponentNameGetDriverName (
    146   IN  EFI_COMPONENT_NAME2_PROTOCOL  *This,
    147   IN  CHAR8                        *Language,
    148   OUT CHAR16                       **DriverName
    149   )
    150 {
    151   return LookupUnicodeString2 (
    152            Language,
    153            This->SupportedLanguages,
    154            mI2cBusDriverNameTable,
    155            DriverName,
    156            (BOOLEAN)(This != &gI2cBusComponentName2)
    157            );
    158 }
    159 
    160 /**
    161   Retrieves a Unicode string that is the user readable name of the controller
    162   that is being managed by a driver.
    163 
    164   This function retrieves the user readable name of the controller specified by
    165   ControllerHandle and ChildHandle in the form of a Unicode string. If the
    166   driver specified by This has a user readable name in the language specified by
    167   Language, then a pointer to the controller name is returned in ControllerName,
    168   and EFI_SUCCESS is returned.  If the driver specified by This is not currently
    169   managing the controller specified by ControllerHandle and ChildHandle,
    170   then EFI_UNSUPPORTED is returned.  If the driver specified by This does not
    171   support the language specified by Language, then EFI_UNSUPPORTED is returned.
    172 
    173   @param  This[in]              A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
    174                                 EFI_COMPONENT_NAME_PROTOCOL instance.
    175 
    176   @param  ControllerHandle[in]  The handle of a controller that the driver
    177                                 specified by This is managing.  This handle
    178                                 specifies the controller whose name is to be
    179                                 returned.
    180 
    181   @param  ChildHandle[in]       The handle of the child controller to retrieve
    182                                 the name of.  This is an optional parameter that
    183                                 may be NULL.  It will be NULL for device
    184                                 drivers.  It will also be NULL for a bus drivers
    185                                 that wish to retrieve the name of the bus
    186                                 controller.  It will not be NULL for a bus
    187                                 driver that wishes to retrieve the name of a
    188                                 child controller.
    189 
    190   @param  Language[in]          A pointer to a Null-terminated ASCII string
    191                                 array indicating the language.  This is the
    192                                 language of the driver name that the caller is
    193                                 requesting, and it must match one of the
    194                                 languages specified in SupportedLanguages. The
    195                                 number of languages supported by a driver is up
    196                                 to the driver writer. Language is specified in
    197                                 RFC 4646 or ISO 639-2 language code format.
    198 
    199   @param  ControllerName[out]   A pointer to the Unicode string to return.
    200                                 This Unicode string is the name of the
    201                                 controller specified by ControllerHandle and
    202                                 ChildHandle in the language specified by
    203                                 Language from the point of view of the driver
    204                                 specified by This.
    205 
    206   @retval EFI_SUCCESS           The Unicode string for the user readable name in
    207                                 the language specified by Language for the
    208                                 driver specified by This was returned in
    209                                 DriverName.
    210 
    211   @retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
    212 
    213   @retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
    214                                 EFI_HANDLE.
    215 
    216   @retval EFI_INVALID_PARAMETER Language is NULL.
    217 
    218   @retval EFI_INVALID_PARAMETER ControllerName is NULL.
    219 
    220   @retval EFI_UNSUPPORTED       The driver specified by This is not currently
    221                                 managing the controller specified by
    222                                 ControllerHandle and ChildHandle.
    223 
    224   @retval EFI_UNSUPPORTED       The driver specified by This does not support
    225                                 the language specified by Language.
    226 
    227 **/
    228 EFI_STATUS
    229 EFIAPI
    230 I2cBusComponentNameGetControllerName (
    231   IN  EFI_COMPONENT_NAME2_PROTOCOL                     *This,
    232   IN  EFI_HANDLE                                      ControllerHandle,
    233   IN  EFI_HANDLE                                      ChildHandle        OPTIONAL,
    234   IN  CHAR8                                           *Language,
    235   OUT CHAR16                                          **ControllerName
    236   )
    237 {
    238   return EFI_UNSUPPORTED;
    239 }
    240 
    241 /**
    242   Check if the child of I2C controller has been created.
    243 
    244   @param[in] This                         A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    245   @param[in] Controller                   I2C controller handle.
    246   @param[in] RemainingDevicePath          A pointer to the remaining portion of a device path.
    247   @param[in] RemainingHasControllerNode   Indicate if RemainingDevicePath contains CONTROLLER_DEVICE_PATH.
    248   @param[in] RemainingControllerNumber    Controller number in CONTROLLER_DEVICE_PATH.
    249 
    250   @retval EFI_SUCCESS                     The child of I2C controller is not created.
    251   @retval Others                          The child of I2C controller has been created or other errors happen.
    252 
    253 **/
    254 EFI_STATUS
    255 CheckRemainingDevicePath (
    256   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    257   IN EFI_HANDLE                   Controller,
    258   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath,
    259   IN BOOLEAN                      RemainingHasControllerNode,
    260   IN UINT32                       RemainingControllerNumber
    261   )
    262 {
    263   EFI_STATUS                              Status;
    264   EFI_DEVICE_PATH_PROTOCOL                *SystemDevicePath;
    265   EFI_OPEN_PROTOCOL_INFORMATION_ENTRY     *OpenInfoBuffer;
    266   UINTN                                   EntryCount;
    267   UINTN                                   Index;
    268   BOOLEAN                                 SystemHasControllerNode;
    269   UINT32                                  SystemControllerNumber;
    270 
    271   SystemHasControllerNode = FALSE;
    272   SystemControllerNumber    = 0;
    273 
    274   Status = gBS->OpenProtocolInformation (
    275                   Controller,
    276                   &gEfiI2cHostProtocolGuid,
    277                   &OpenInfoBuffer,
    278                   &EntryCount
    279                   );
    280   if (EFI_ERROR (Status)) {
    281     return Status;
    282   }
    283 
    284   for (Index = 0; Index < EntryCount; Index++) {
    285     if ((OpenInfoBuffer[Index].Attributes & EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER) != 0) {
    286       Status = gBS->OpenProtocol (
    287                       OpenInfoBuffer[Index].ControllerHandle,
    288                       &gEfiDevicePathProtocolGuid,
    289                       (VOID **) &SystemDevicePath,
    290                       This->DriverBindingHandle,
    291                       Controller,
    292                       EFI_OPEN_PROTOCOL_GET_PROTOCOL
    293                       );
    294       if (!EFI_ERROR (Status)) {
    295         //
    296         // Find vendor device path node and compare
    297         //
    298         while (!IsDevicePathEnd (SystemDevicePath)) {
    299           if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
    300               (DevicePathSubType (SystemDevicePath) == HW_VENDOR_DP)) {
    301             //
    302             // Check if vendor device path is same between system device path and remaining device path
    303             //
    304             if (CompareMem (SystemDevicePath, RemainingDevicePath, sizeof (VENDOR_DEVICE_PATH)) == 0) {
    305               //
    306               // Get controller node appended after vendor node
    307               //
    308               SystemDevicePath = NextDevicePathNode (SystemDevicePath);
    309               if ((DevicePathType (SystemDevicePath) == HARDWARE_DEVICE_PATH) &&
    310                   (DevicePathSubType (SystemDevicePath) == HW_CONTROLLER_DP)) {
    311                 SystemHasControllerNode = TRUE;
    312                 SystemControllerNumber    = ((CONTROLLER_DEVICE_PATH *) SystemDevicePath)->ControllerNumber;
    313               } else {
    314                 SystemHasControllerNode = FALSE;
    315                 SystemControllerNumber    = 0;
    316               }
    317               if (((SystemHasControllerNode)  && (!RemainingHasControllerNode) && (SystemControllerNumber == 0)) ||
    318                   ((!SystemHasControllerNode) && (RemainingHasControllerNode)  && (RemainingControllerNumber == 0)) ||
    319                   ((SystemHasControllerNode)  && (RemainingHasControllerNode)  && (SystemControllerNumber == RemainingControllerNumber)) ||
    320                   ((!SystemHasControllerNode) && (!RemainingHasControllerNode))) {
    321                   DEBUG ((EFI_D_ERROR, "This I2C device has been already started.\n"));
    322                   Status = EFI_UNSUPPORTED;
    323                   break;
    324               }
    325             }
    326           }
    327           SystemDevicePath = NextDevicePathNode (SystemDevicePath);
    328         }
    329         if (EFI_ERROR (Status)) {
    330           break;
    331         }
    332       }
    333     }
    334   }
    335   FreePool (OpenInfoBuffer);
    336   return Status;
    337 }
    338 
    339 /**
    340   Tests to see if this driver supports a given controller. If a child device is provided,
    341   it further tests to see if this driver supports creating a handle for the specified child device.
    342 
    343   This function checks to see if the driver specified by This supports the device specified by
    344   ControllerHandle. Drivers will typically use the device path attached to
    345   ControllerHandle and/or the services from the bus I/O abstraction attached to
    346   ControllerHandle to determine if the driver supports ControllerHandle. This function
    347   may be called many times during platform initialization. In order to reduce boot times, the tests
    348   performed by this function must be very small, and take as little time as possible to execute. This
    349   function must not change the state of any hardware devices, and this function must be aware that the
    350   device specified by ControllerHandle may already be managed by the same driver or a
    351   different driver. This function must match its calls to AllocatePages() with FreePages(),
    352   AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
    353   Since ControllerHandle may have been previously started by the same driver, if a protocol is
    354   already in the opened state, then it must not be closed with CloseProtocol(). This is required
    355   to guarantee the state of ControllerHandle is not modified by this function.
    356 
    357   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    358   @param[in]  ControllerHandle     The handle of the controller to test. This handle
    359                                    must support a protocol interface that supplies
    360                                    an I/O abstraction to the driver.
    361   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    362                                    parameter is ignored by device drivers, and is optional for bus
    363                                    drivers. For bus drivers, if this parameter is not NULL, then
    364                                    the bus driver must determine if the bus controller specified
    365                                    by ControllerHandle and the child controller specified
    366                                    by RemainingDevicePath are both supported by this
    367                                    bus driver.
    368 
    369   @retval EFI_SUCCESS              The device specified by ControllerHandle and
    370                                    RemainingDevicePath is supported by the driver specified by This.
    371   @retval EFI_ALREADY_STARTED      The device specified by ControllerHandle and
    372                                    RemainingDevicePath is already being managed by the driver
    373                                    specified by This.
    374   @retval EFI_ACCESS_DENIED        The device specified by ControllerHandle and
    375                                    RemainingDevicePath is already being managed by a different
    376                                    driver or an application that requires exclusive access.
    377                                    Currently not implemented.
    378   @retval EFI_UNSUPPORTED          The device specified by ControllerHandle and
    379                                    RemainingDevicePath is not supported by the driver specified by This.
    380 **/
    381 EFI_STATUS
    382 EFIAPI
    383 I2cBusDriverSupported (
    384   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    385   IN EFI_HANDLE                   Controller,
    386   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    387   )
    388 {
    389   EFI_STATUS                          Status;
    390   EFI_I2C_ENUMERATE_PROTOCOL          *I2cEnumerate;
    391   EFI_I2C_HOST_PROTOCOL               *I2cHost;
    392   EFI_DEVICE_PATH_PROTOCOL            *ParentDevicePath;
    393   EFI_DEVICE_PATH_PROTOCOL            *DevPathNode;
    394   BOOLEAN                             RemainingHasControllerNode;
    395   UINT32                              RemainingControllerNumber;
    396 
    397   RemainingHasControllerNode = FALSE;
    398   RemainingControllerNumber    = 0;
    399 
    400   //
    401   //  Determine if the I2c Enumerate Protocol is available
    402   //
    403   Status = gBS->OpenProtocol (
    404                   Controller,
    405                   &gEfiI2cEnumerateProtocolGuid,
    406                   (VOID **) &I2cEnumerate,
    407                   This->DriverBindingHandle,
    408                   Controller,
    409                   EFI_OPEN_PROTOCOL_BY_DRIVER
    410                   );
    411   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    412     return Status;
    413   }
    414 
    415   if (!EFI_ERROR (Status)) {
    416     gBS->CloseProtocol (
    417           Controller,
    418           &gEfiI2cEnumerateProtocolGuid,
    419           This->DriverBindingHandle,
    420           Controller
    421           );
    422   }
    423 
    424   Status = gBS->OpenProtocol (
    425                   Controller,
    426                   &gEfiDevicePathProtocolGuid,
    427                   (VOID **) &ParentDevicePath,
    428                   This->DriverBindingHandle,
    429                   Controller,
    430                   EFI_OPEN_PROTOCOL_BY_DRIVER
    431                   );
    432 
    433   if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
    434     return Status;
    435   }
    436 
    437   if (!EFI_ERROR (Status)) {
    438     gBS->CloseProtocol (
    439           Controller,
    440           &gEfiDevicePathProtocolGuid,
    441           This->DriverBindingHandle,
    442           Controller
    443           );
    444   }
    445 
    446   if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
    447     //
    448     // Check if the first node of RemainingDevicePath is a hardware vendor device path
    449     //
    450     if ((DevicePathType (RemainingDevicePath) != HARDWARE_DEVICE_PATH) ||
    451         (DevicePathSubType (RemainingDevicePath) != HW_VENDOR_DP)) {
    452       return EFI_UNSUPPORTED;
    453     }
    454     //
    455     // Check if the second node of RemainingDevicePath is a controller node
    456     //
    457     DevPathNode = NextDevicePathNode (RemainingDevicePath);
    458     if (!IsDevicePathEnd (DevPathNode)) {
    459       if ((DevicePathType (DevPathNode) != HARDWARE_DEVICE_PATH) ||
    460           (DevicePathSubType (DevPathNode) != HW_CONTROLLER_DP)) {
    461         return EFI_UNSUPPORTED;
    462       } else {
    463         RemainingHasControllerNode = TRUE;
    464         RemainingControllerNumber    = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
    465       }
    466     }
    467   }
    468 
    469   //
    470   // Determine if the I2C Host Protocol is available
    471   //
    472   Status = gBS->OpenProtocol (
    473                   Controller,
    474                   &gEfiI2cHostProtocolGuid,
    475                   (VOID **) &I2cHost,
    476                   This->DriverBindingHandle,
    477                   Controller,
    478                   EFI_OPEN_PROTOCOL_BY_DRIVER
    479                   );
    480 
    481   if (!EFI_ERROR (Status)) {
    482     gBS->CloseProtocol (
    483           Controller,
    484           &gEfiI2cHostProtocolGuid,
    485           This->DriverBindingHandle,
    486           Controller
    487           );
    488   }
    489 
    490 
    491   if (Status == EFI_ALREADY_STARTED) {
    492     if ((RemainingDevicePath == NULL) ||
    493         ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath))) {
    494       //
    495       // If RemainingDevicePath is NULL or is the End of Device Path Node, return EFI_SUCCESS.
    496       //
    497       Status = EFI_SUCCESS;
    498     } else {
    499       //
    500       // Test if the child with the RemainingDevicePath has already been created.
    501       //
    502       Status = CheckRemainingDevicePath (
    503                  This,
    504                  Controller,
    505                  RemainingDevicePath,
    506                  RemainingHasControllerNode,
    507                  RemainingControllerNumber
    508                  );
    509     }
    510   }
    511 
    512   return Status;
    513 }
    514 
    515 /**
    516   Starts a device controller or a bus controller.
    517 
    518   The Start() function is designed to be invoked from the EFI boot service ConnectController().
    519   As a result, much of the error checking on the parameters to Start() has been moved into this
    520   common boot service. It is legal to call Start() from other locations,
    521   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    522   1. ControllerHandle must be a valid EFI_HANDLE.
    523   2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
    524      EFI_DEVICE_PATH_PROTOCOL.
    525   3. Prior to calling Start(), the Supported() function for the driver specified by This must
    526      have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
    527 
    528   @param[in]  This                 A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    529   @param[in]  ControllerHandle     The handle of the controller to start. This handle
    530                                    must support a protocol interface that supplies
    531                                    an I/O abstraction to the driver.
    532   @param[in]  RemainingDevicePath  A pointer to the remaining portion of a device path.  This
    533                                    parameter is ignored by device drivers, and is optional for bus
    534                                    drivers. For a bus driver, if this parameter is NULL, then handles
    535                                    for all the children of Controller are created by this driver.
    536                                    If this parameter is not NULL and the first Device Path Node is
    537                                    not the End of Device Path Node, then only the handle for the
    538                                    child device specified by the first Device Path Node of
    539                                    RemainingDevicePath is created by this driver.
    540                                    If the first Device Path Node of RemainingDevicePath is
    541                                    the End of Device Path Node, no child handle is created by this
    542                                    driver.
    543 
    544   @retval EFI_SUCCESS              The device was started.
    545   @retval EFI_DEVICE_ERROR         The device could not be started due to a device error.Currently not implemented.
    546   @retval EFI_OUT_OF_RESOURCES     The request could not be completed due to a lack of resources.
    547   @retval Others                   The driver failded to start the device.
    548 
    549 **/
    550 EFI_STATUS
    551 EFIAPI
    552 I2cBusDriverStart (
    553   IN EFI_DRIVER_BINDING_PROTOCOL  *This,
    554   IN EFI_HANDLE                   Controller,
    555   IN EFI_DEVICE_PATH_PROTOCOL     *RemainingDevicePath
    556   )
    557 {
    558   EFI_I2C_ENUMERATE_PROTOCOL *I2cEnumerate;
    559   EFI_I2C_HOST_PROTOCOL      *I2cHost;
    560   I2C_BUS_CONTEXT            *I2cBusContext;
    561   EFI_STATUS                 Status;
    562   EFI_DEVICE_PATH_PROTOCOL   *ParentDevicePath;
    563 
    564   I2cBusContext     = NULL;
    565   ParentDevicePath  = NULL;
    566   I2cEnumerate      = NULL;
    567   I2cHost           = NULL;
    568 
    569   //
    570   //  Determine if the I2C controller is available
    571   //
    572   Status = gBS->OpenProtocol (
    573                   Controller,
    574                   &gEfiI2cHostProtocolGuid,
    575                   (VOID**)&I2cHost,
    576                   This->DriverBindingHandle,
    577                   Controller,
    578                   EFI_OPEN_PROTOCOL_BY_DRIVER
    579                   );
    580   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    581     DEBUG ((EFI_D_ERROR, "I2cBus: open I2C host error, Status = %r\n", Status));
    582     return Status;
    583   }
    584 
    585   if (Status == EFI_ALREADY_STARTED) {
    586     Status = gBS->OpenProtocol (
    587                     Controller,
    588                     &gEfiCallerIdGuid,
    589                     (VOID **) &I2cBusContext,
    590                     This->DriverBindingHandle,
    591                     Controller,
    592                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    593                     );
    594     if (EFI_ERROR (Status)) {
    595       DEBUG ((EFI_D_ERROR, "I2cBus: open private protocol error, Status = %r.\n", Status));
    596       return Status;
    597     }
    598   }
    599 
    600   //
    601   //  Get the I2C bus enumeration API
    602   //
    603   Status = gBS->OpenProtocol (
    604                   Controller,
    605                   &gEfiI2cEnumerateProtocolGuid,
    606                   (VOID**)&I2cEnumerate,
    607                   This->DriverBindingHandle,
    608                   Controller,
    609                   EFI_OPEN_PROTOCOL_BY_DRIVER
    610                   );
    611   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    612     DEBUG ((EFI_D_ERROR, "I2cBus: open I2C enumerate error, Status = %r\n", Status));
    613     goto Error;
    614   }
    615 
    616   Status = gBS->OpenProtocol (
    617                    Controller,
    618                    &gEfiDevicePathProtocolGuid,
    619                    (VOID **) &ParentDevicePath,
    620                    This->DriverBindingHandle,
    621                    Controller,
    622                    EFI_OPEN_PROTOCOL_BY_DRIVER
    623                    );
    624   if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
    625     DEBUG ((EFI_D_ERROR, "I2cBus: open device path error, Status = %r\n", Status));
    626     goto Error;
    627   }
    628 
    629   if ((RemainingDevicePath != NULL) && IsDevicePathEnd (RemainingDevicePath)) {
    630     //
    631     // If RemainingDevicePath is the End of Device Path Node,
    632     // don't create any child device and return EFI_SUCESS
    633     //
    634     return EFI_SUCCESS;
    635   }
    636 
    637   //
    638   // Allocate the buffer for I2C_BUS_CONTEXT if it is not allocated before.
    639   //
    640   if (I2cBusContext == NULL) {
    641     //
    642     //  Allocate the I2C context structure for the current I2C controller
    643     //
    644     I2cBusContext = AllocateZeroPool (sizeof (I2C_BUS_CONTEXT));
    645     if (I2cBusContext == NULL) {
    646       DEBUG ((EFI_D_ERROR, "I2cBus: there is no enough memory to allocate.\n"));
    647       Status = EFI_OUT_OF_RESOURCES;
    648       goto Error;
    649     }
    650 
    651     /*
    652        +----------------+
    653     .->| I2C_BUS_CONTEXT|<----- This file Protocol (gEfiCallerIdGuid) installed on I2C Controller handle
    654     |  +----------------+
    655     |
    656     |  +----------------------------+
    657     |  | I2C_DEVICE_CONTEXT         |
    658     `--|                            |
    659        |                            |
    660        | I2C IO Protocol Structure  | <----- I2C IO Protocol
    661        |                            |
    662        +----------------------------+
    663 
    664     */
    665     I2cBusContext->I2cHost      = I2cHost;
    666     I2cBusContext->I2cEnumerate = I2cEnumerate;
    667     //
    668     // Parent controller used to create children
    669     //
    670     I2cBusContext->Controller   = Controller;
    671     //
    672     // Parent controller device path used to create children device path
    673     //
    674     I2cBusContext->ParentDevicePath = ParentDevicePath;
    675 
    676     I2cBusContext->DriverBindingHandle = This->DriverBindingHandle;
    677 
    678     Status = gBS->InstallMultipleProtocolInterfaces (
    679                     &Controller,
    680                     &gEfiCallerIdGuid,
    681                     I2cBusContext,
    682                     NULL
    683                     );
    684     if (EFI_ERROR (Status)) {
    685       DEBUG ((EFI_D_ERROR, "I2cBus: install private protocol error, Status = %r.\n", Status));
    686       goto Error;
    687     }
    688   }
    689 
    690   //
    691   //  Start the driver
    692   //
    693   Status = RegisterI2cDevice (I2cBusContext, Controller, RemainingDevicePath);
    694 
    695   return Status;
    696 
    697 Error:
    698   if (EFI_ERROR (Status)) {
    699     DEBUG ((EFI_D_ERROR, "I2cBus: Start() function failed, Status = %r\n", Status));
    700     if (ParentDevicePath != NULL) {
    701       gBS->CloseProtocol (
    702             Controller,
    703             &gEfiDevicePathProtocolGuid,
    704             This->DriverBindingHandle,
    705             Controller
    706             );
    707     }
    708 
    709     if (I2cHost != NULL) {
    710       gBS->CloseProtocol (
    711             Controller,
    712             &gEfiI2cHostProtocolGuid,
    713             This->DriverBindingHandle,
    714             Controller
    715             );
    716     }
    717 
    718     if (I2cEnumerate != NULL) {
    719       gBS->CloseProtocol (
    720             Controller,
    721             &gEfiI2cEnumerateProtocolGuid,
    722             This->DriverBindingHandle,
    723             Controller
    724             );
    725     }
    726 
    727     if (I2cBusContext != NULL) {
    728       Status = gBS->UninstallMultipleProtocolInterfaces (
    729                       &Controller,
    730                       gEfiCallerIdGuid,
    731                       I2cBusContext,
    732                       NULL
    733                       );
    734       FreePool (I2cBusContext);
    735     }
    736   }
    737 
    738   //
    739   //  Return the operation status.
    740   //
    741   return Status;
    742 }
    743 
    744 
    745 /**
    746   Stops a device controller or a bus controller.
    747 
    748   The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
    749   As a result, much of the error checking on the parameters to Stop() has been moved
    750   into this common boot service. It is legal to call Stop() from other locations,
    751   but the following calling restrictions must be followed or the system behavior will not be deterministic.
    752   1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
    753      same driver's Start() function.
    754   2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
    755      EFI_HANDLE. In addition, all of these handles must have been created in this driver's
    756      Start() function, and the Start() function must have called OpenProtocol() on
    757      ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
    758 
    759   @param[in]  This              A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
    760   @param[in]  ControllerHandle  A handle to the device being stopped. The handle must
    761                                 support a bus specific I/O protocol for the driver
    762                                 to use to stop the device.
    763   @param[in]  NumberOfChildren  The number of child device handles in ChildHandleBuffer.
    764   @param[in]  ChildHandleBuffer An array of child handles to be freed. May be NULL
    765                                 if NumberOfChildren is 0.
    766 
    767   @retval EFI_SUCCESS           The device was stopped.
    768   @retval EFI_DEVICE_ERROR      The device could not be stopped due to a device error.
    769 
    770 **/
    771 EFI_STATUS
    772 EFIAPI
    773 I2cBusDriverStop (
    774   IN  EFI_DRIVER_BINDING_PROTOCOL  *This,
    775   IN  EFI_HANDLE                   Controller,
    776   IN  UINTN                        NumberOfChildren,
    777   IN  EFI_HANDLE                   *ChildHandleBuffer
    778   )
    779 {
    780   I2C_BUS_CONTEXT             *I2cBusContext;
    781   EFI_STATUS                  Status;
    782   BOOLEAN                     AllChildrenStopped;
    783   UINTN                       Index;
    784 
    785   if (NumberOfChildren == 0) {
    786     gBS->CloseProtocol (
    787           Controller,
    788           &gEfiDevicePathProtocolGuid,
    789           This->DriverBindingHandle,
    790           Controller
    791           );
    792 
    793     gBS->CloseProtocol (
    794           Controller,
    795           &gEfiI2cHostProtocolGuid,
    796           This->DriverBindingHandle,
    797           Controller
    798           );
    799 
    800     gBS->CloseProtocol (
    801           Controller,
    802           &gEfiI2cEnumerateProtocolGuid,
    803           This->DriverBindingHandle,
    804           Controller
    805           );
    806 
    807     Status = gBS->OpenProtocol (
    808                     Controller,
    809                     &gEfiCallerIdGuid,
    810                     (VOID **) &I2cBusContext,
    811                     This->DriverBindingHandle,
    812                     Controller,
    813                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    814                     );
    815     if (!EFI_ERROR (Status)) {
    816       gBS->UninstallMultipleProtocolInterfaces (
    817             Controller,
    818             &gEfiCallerIdGuid,
    819             I2cBusContext,
    820             NULL
    821             );
    822       //
    823       // No more child now, free bus context data.
    824       //
    825       FreePool (I2cBusContext);
    826     }
    827     return Status;
    828   }
    829 
    830   AllChildrenStopped = TRUE;
    831 
    832   for (Index = 0; Index < NumberOfChildren; Index++) {
    833 
    834     Status = UnRegisterI2cDevice (This, Controller, ChildHandleBuffer[Index]);
    835     if (EFI_ERROR (Status)) {
    836       AllChildrenStopped = FALSE;
    837     }
    838   }
    839 
    840   if (!AllChildrenStopped) {
    841     return EFI_DEVICE_ERROR;
    842   }
    843   return EFI_SUCCESS;
    844 }
    845 
    846 /**
    847   Enumerate the I2C bus
    848 
    849   This routine walks the platform specific data describing the
    850   I2C bus to create the I2C devices where driver GUIDs were
    851   specified.
    852 
    853   @param[in] I2cBusContext            Address of an I2C_BUS_CONTEXT structure
    854   @param[in] Controller               Handle to the controller
    855   @param[in] RemainingDevicePath      A pointer to the remaining portion of a device path.
    856 
    857   @retval EFI_SUCCESS       The bus is successfully configured
    858 
    859 **/
    860 EFI_STATUS
    861 RegisterI2cDevice (
    862   IN I2C_BUS_CONTEXT            *I2cBusContext,
    863   IN EFI_HANDLE                 Controller,
    864   IN EFI_DEVICE_PATH_PROTOCOL   *RemainingDevicePath
    865   )
    866 {
    867   I2C_DEVICE_CONTEXT                *I2cDeviceContext;
    868   EFI_STATUS                        Status;
    869   CONST EFI_I2C_DEVICE              *Device;
    870   CONST EFI_I2C_DEVICE              *TempDevice;
    871   UINT32                            RemainingPathDeviceIndex;
    872   EFI_DEVICE_PATH_PROTOCOL          *DevPathNode;
    873   BOOLEAN                           BuildControllerNode;
    874   UINTN                             Count;
    875 
    876   Status                   = EFI_SUCCESS;
    877   BuildControllerNode      = TRUE;
    878 
    879   //
    880   // Default DeviceIndex
    881   //
    882   RemainingPathDeviceIndex = 0;
    883 
    884   //
    885   // Determine the controller number in Controller Node Device Path when RemainingDevicePath is not NULL.
    886   //
    887   if (RemainingDevicePath != NULL) {
    888     //
    889     // Check if there is a controller node appended after vendor node
    890     //
    891     DevPathNode = NextDevicePathNode (RemainingDevicePath);
    892     if ((DevicePathType (DevPathNode) == HARDWARE_DEVICE_PATH) &&
    893         (DevicePathSubType(DevPathNode) == HW_CONTROLLER_DP)) {
    894       //
    895       // RemainingDevicePath != NULL and RemainingDevicePath contains Controller Node,
    896       // add Controller Node to Device Path on child handle.
    897       //
    898       RemainingPathDeviceIndex = ((CONTROLLER_DEVICE_PATH *) DevPathNode)->ControllerNumber;
    899     } else {
    900       //
    901       // RemainingDevicePath != NULL and RemainingDevicePath does not contain Controller Node,
    902       // do not add controller node to Device Path on child handle.
    903       //
    904       BuildControllerNode = FALSE;
    905     }
    906   }
    907 
    908   //
    909   //  Walk the list of I2C devices on this bus
    910   //
    911   Device = NULL;
    912   while (TRUE) {
    913     //
    914     //  Get the next I2C device
    915     //
    916     Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &Device);
    917     if (EFI_ERROR (Status) || Device == NULL) {
    918       if (RemainingDevicePath != NULL) {
    919         Status = EFI_NOT_FOUND;
    920       } else {
    921         Status = EFI_SUCCESS;
    922       }
    923       break;
    924     }
    925 
    926     //
    927     //  Determine if the device info is valid
    928     //
    929     if ((Device->DeviceGuid == NULL) || (Device->SlaveAddressCount == 0) || (Device->SlaveAddressArray == NULL)) {
    930       DEBUG ((EFI_D_ERROR, "Invalid EFI_I2C_DEVICE reported by I2c Enumerate protocol.\n"));
    931       continue;
    932     }
    933 
    934     if (RemainingDevicePath == NULL) {
    935       if (Device->DeviceIndex == 0) {
    936         //
    937         // Determine if the controller node is necessary when controller number is zero in I2C device
    938         //
    939         TempDevice = NULL;
    940         Count      = 0;
    941         while (TRUE) {
    942           //
    943           //  Get the next I2C device
    944           //
    945           Status = I2cBusContext->I2cEnumerate->Enumerate (I2cBusContext->I2cEnumerate, &TempDevice);
    946           if (EFI_ERROR (Status) || TempDevice == NULL) {
    947             Status = EFI_SUCCESS;
    948             break;
    949           }
    950           if (CompareGuid (Device->DeviceGuid, TempDevice->DeviceGuid)) {
    951             Count++;
    952           }
    953         }
    954         if (Count == 1) {
    955           //
    956           // RemainingDevicePath == NULL and only DeviceIndex 0 is present on the I2C bus,
    957           // do not add Controller Node to Device Path on child handle.
    958           //
    959           BuildControllerNode = FALSE;
    960         }
    961       }
    962     } else {
    963       //
    964       // Find I2C device reported in Remaining Device Path
    965       //
    966       if ((!CompareGuid (&((VENDOR_DEVICE_PATH *)RemainingDevicePath)->Guid, Device->DeviceGuid)) ||
    967           (RemainingPathDeviceIndex != Device->DeviceIndex)) {
    968         continue;
    969       }
    970     }
    971 
    972     //
    973     // Build the device context for current I2C device.
    974     //
    975     I2cDeviceContext = NULL;
    976     I2cDeviceContext = AllocateCopyPool (sizeof (I2C_DEVICE_CONTEXT), &gI2cDeviceContextTemplate);
    977     ASSERT (I2cDeviceContext != NULL);
    978     if (I2cDeviceContext == NULL) {
    979       continue;
    980     }
    981 
    982     //
    983     //  Initialize the specific device context
    984     //
    985     I2cDeviceContext->I2cBusContext          = I2cBusContext;
    986     I2cDeviceContext->I2cDevice              = Device;
    987     I2cDeviceContext->I2cIo.DeviceGuid       = Device->DeviceGuid;
    988     I2cDeviceContext->I2cIo.DeviceIndex      = Device->DeviceIndex;
    989     I2cDeviceContext->I2cIo.HardwareRevision = Device->HardwareRevision;
    990     I2cDeviceContext->I2cIo.I2cControllerCapabilities = I2cBusContext->I2cHost->I2cControllerCapabilities;
    991 
    992     //
    993     //  Build the device path
    994     //
    995     Status = I2cBusDevicePathAppend (I2cDeviceContext, BuildControllerNode);
    996     ASSERT_EFI_ERROR (Status);
    997     if (EFI_ERROR (Status)) {
    998       continue;
    999     }
   1000 
   1001     //
   1002     //  Install the protocol
   1003     //
   1004     Status = gBS->InstallMultipleProtocolInterfaces (
   1005               &I2cDeviceContext->Handle,
   1006               &gEfiI2cIoProtocolGuid,
   1007               &I2cDeviceContext->I2cIo,
   1008               &gEfiDevicePathProtocolGuid,
   1009               I2cDeviceContext->DevicePath,
   1010               NULL );
   1011     if (EFI_ERROR (Status)) {
   1012       //
   1013       // Free resources for this I2C device
   1014       //
   1015       ReleaseI2cDeviceContext (I2cDeviceContext);
   1016       continue;
   1017     }
   1018 
   1019     //
   1020     // Create the child handle
   1021     //
   1022     Status = gBS->OpenProtocol (
   1023                     Controller,
   1024                     &gEfiI2cHostProtocolGuid,
   1025                     (VOID **) &I2cBusContext->I2cHost,
   1026                     I2cBusContext->DriverBindingHandle,
   1027                     I2cDeviceContext->Handle,
   1028                     EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1029                     );
   1030     if (EFI_ERROR (Status)) {
   1031       Status = gBS->UninstallMultipleProtocolInterfaces (
   1032                       I2cDeviceContext->Handle,
   1033                       &gEfiDevicePathProtocolGuid,
   1034                       I2cDeviceContext->DevicePath,
   1035                       &gEfiI2cIoProtocolGuid,
   1036                       &I2cDeviceContext->I2cIo,
   1037                       NULL
   1038                       );
   1039       //
   1040       // Free resources for this I2C device
   1041       //
   1042       ReleaseI2cDeviceContext (I2cDeviceContext);
   1043       continue;
   1044     }
   1045 
   1046     if (RemainingDevicePath != NULL) {
   1047       //
   1048       // Child has been created successfully
   1049       //
   1050       break;
   1051     }
   1052   }
   1053 
   1054   return Status;
   1055 }
   1056 
   1057 
   1058 /**
   1059   Queue an I2C transaction for execution on the I2C device.
   1060 
   1061   This routine must be called at or below TPL_NOTIFY.  For synchronous
   1062   requests this routine must be called at or below TPL_CALLBACK.
   1063 
   1064   This routine queues an I2C transaction to the I2C controller for
   1065   execution on the I2C bus.
   1066 
   1067   When Event is NULL, QueueRequest() operates synchronously and returns
   1068   the I2C completion status as its return value.
   1069 
   1070   When Event is not NULL, QueueRequest() synchronously returns EFI_SUCCESS
   1071   indicating that the asynchronous I2C transaction was queued.  The values
   1072   above are returned in the buffer pointed to by I2cStatus upon the
   1073   completion of the I2C transaction when I2cStatus is not NULL.
   1074 
   1075   The upper layer driver writer provides the following to the platform
   1076   vendor:
   1077 
   1078   1.  Vendor specific GUID for the I2C part
   1079   2.  Guidance on proper construction of the slave address array when the
   1080       I2C device uses more than one slave address.  The I2C bus protocol
   1081       uses the SlaveAddressIndex to perform relative to physical address
   1082       translation to access the blocks of hardware within the I2C device.
   1083 
   1084   @param[in] This               Pointer to an EFI_I2C_IO_PROTOCOL structure.
   1085   @param[in] SlaveAddressIndex  Index value into an array of slave addresses
   1086                                 for the I2C device.  The values in the array
   1087                                 are specified by the board designer, with the
   1088                                 third party I2C device driver writer providing
   1089                                 the slave address order.
   1090 
   1091                                 For devices that have a single slave address,
   1092                                 this value must be zero.  If the I2C device
   1093                                 uses more than one slave address then the
   1094                                 third party (upper level) I2C driver writer
   1095                                 needs to specify the order of entries in the
   1096                                 slave address array.
   1097 
   1098                                 \ref ThirdPartyI2cDrivers "Third Party I2C
   1099                                 Drivers" section in I2cMaster.h.
   1100   @param[in] Event              Event to signal for asynchronous transactions,
   1101                                 NULL for synchronous transactions
   1102   @param[in] RequestPacket      Pointer to an EFI_I2C_REQUEST_PACKET structure
   1103                                 describing the I2C transaction
   1104   @param[out] I2cStatus         Optional buffer to receive the I2C transaction
   1105                                 completion status
   1106 
   1107   @retval EFI_SUCCESS           The asynchronous transaction was successfully
   1108                                 queued when Event is not NULL.
   1109   @retval EFI_SUCCESS           The transaction completed successfully when
   1110                                 Event is NULL.
   1111   @retval EFI_BAD_BUFFER_SIZE   The RequestPacket->LengthInBytes value is too
   1112                                 large.
   1113   @retval EFI_DEVICE_ERROR      There was an I2C error (NACK) during the
   1114                                 transaction.
   1115   @retval EFI_INVALID_PARAMETER RequestPacket is NULL
   1116   @retval EFI_NO_MAPPING        The EFI_I2C_HOST_PROTOCOL could not set the
   1117                                 bus configuration required to access this I2C
   1118                                 device.
   1119   @retval EFI_NO_RESPONSE       The I2C device is not responding to the slave
   1120                                 address selected by SlaveAddressIndex.
   1121                                 EFI_DEVICE_ERROR will be returned if the
   1122                                 controller cannot distinguish when the NACK
   1123                                 occurred.
   1124   @retval EFI_OUT_OF_RESOURCES  Insufficient memory for I2C transaction
   1125   @retval EFI_UNSUPPORTED       The controller does not support the requested
   1126                                 transaction.
   1127 
   1128 **/
   1129 EFI_STATUS
   1130 EFIAPI
   1131 I2cBusQueueRequest (
   1132   IN CONST EFI_I2C_IO_PROTOCOL  *This,
   1133   IN UINTN                      SlaveAddressIndex,
   1134   IN EFI_EVENT                  Event               OPTIONAL,
   1135   IN EFI_I2C_REQUEST_PACKET     *RequestPacket,
   1136   OUT EFI_STATUS                *I2cStatus          OPTIONAL
   1137   )
   1138 {
   1139   CONST EFI_I2C_DEVICE        *I2cDevice;
   1140   I2C_BUS_CONTEXT             *I2cBusContext;
   1141   CONST EFI_I2C_HOST_PROTOCOL *I2cHost;
   1142   I2C_DEVICE_CONTEXT          *I2cDeviceContext;
   1143   EFI_STATUS                  Status;
   1144 
   1145   if (RequestPacket == NULL) {
   1146     return EFI_INVALID_PARAMETER;
   1147   }
   1148 
   1149   //
   1150   //  Validate the I2C slave index
   1151   //
   1152   I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (This);
   1153   I2cDevice        = I2cDeviceContext->I2cDevice;
   1154   if ( SlaveAddressIndex >= I2cDevice->SlaveAddressCount ) {
   1155     return EFI_INVALID_PARAMETER;
   1156   }
   1157 
   1158   //
   1159   //  Locate the I2c Host Protocol to queue request
   1160   //
   1161   I2cBusContext = I2cDeviceContext->I2cBusContext;
   1162   I2cHost       = I2cBusContext->I2cHost;
   1163 
   1164   //
   1165   //  Start the I2C operation
   1166   //
   1167   Status = I2cHost->QueueRequest (
   1168                       I2cHost,
   1169                       I2cDevice->I2cBusConfiguration,
   1170                       I2cDevice->SlaveAddressArray [SlaveAddressIndex],
   1171                       Event,
   1172                       RequestPacket,
   1173                       I2cStatus
   1174                       );
   1175 
   1176   return Status;
   1177 }
   1178 
   1179 /**
   1180   Release all the resources allocated for the I2C device.
   1181 
   1182   This function releases all the resources allocated for the I2C device.
   1183 
   1184   @param  I2cDeviceContext         The I2C child device involved for the operation.
   1185 
   1186 **/
   1187 VOID
   1188 ReleaseI2cDeviceContext (
   1189   IN I2C_DEVICE_CONTEXT          *I2cDeviceContext
   1190   )
   1191 {
   1192   if (I2cDeviceContext == NULL) {
   1193     return;
   1194   }
   1195 
   1196   if (I2cDeviceContext->DevicePath != NULL) {
   1197     FreePool (I2cDeviceContext->DevicePath);
   1198   }
   1199 
   1200   FreePool (I2cDeviceContext);
   1201 }
   1202 
   1203 /**
   1204   Unregister an I2C device.
   1205 
   1206   This function removes the protocols installed on the controller handle and
   1207   frees the resources allocated for the I2C device.
   1208 
   1209   @param  This                  The pointer to EFI_DRIVER_BINDING_PROTOCOL instance.
   1210   @param  Controller            The controller handle of the I2C device.
   1211   @param  Handle                The child handle.
   1212 
   1213   @retval EFI_SUCCESS           The I2C device is successfully unregistered.
   1214   @return Others                Some error occurs when unregistering the I2C device.
   1215 
   1216 **/
   1217 EFI_STATUS
   1218 UnRegisterI2cDevice (
   1219   IN  EFI_DRIVER_BINDING_PROTOCOL    *This,
   1220   IN  EFI_HANDLE                     Controller,
   1221   IN  EFI_HANDLE                     Handle
   1222   )
   1223 {
   1224   EFI_STATUS                  Status;
   1225   I2C_DEVICE_CONTEXT          *I2cDeviceContext;
   1226   EFI_I2C_IO_PROTOCOL         *I2cIo;
   1227   EFI_I2C_HOST_PROTOCOL       *I2cHost;
   1228 
   1229   I2cIo = NULL;
   1230 
   1231   Status = gBS->OpenProtocol (
   1232                   Handle,
   1233                   &gEfiI2cIoProtocolGuid,
   1234                   (VOID **) &I2cIo,
   1235                   This->DriverBindingHandle,
   1236                   Controller,
   1237                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
   1238                   );
   1239   if (EFI_ERROR (Status)) {
   1240     return Status;
   1241   }
   1242 
   1243   //
   1244   // Get I2c device context data.
   1245   //
   1246   I2cDeviceContext = I2C_DEVICE_CONTEXT_FROM_PROTOCOL (I2cIo);
   1247 
   1248   //
   1249   // Close the child handle
   1250   //
   1251   gBS->CloseProtocol (
   1252          Controller,
   1253          &gEfiI2cHostProtocolGuid,
   1254          This->DriverBindingHandle,
   1255          Handle
   1256          );
   1257 
   1258   //
   1259   // The I2C Bus driver installs the I2C Io and Device Path Protocol in the DriverBindingStart().
   1260   // Here should uninstall them.
   1261   //
   1262   Status = gBS->UninstallMultipleProtocolInterfaces (
   1263                   Handle,
   1264                   &gEfiDevicePathProtocolGuid,
   1265                   I2cDeviceContext->DevicePath,
   1266                   &gEfiI2cIoProtocolGuid,
   1267                   &I2cDeviceContext->I2cIo,
   1268                   NULL
   1269                   );
   1270 
   1271   if (EFI_ERROR (Status)) {
   1272     //
   1273     // Keep parent and child relationship
   1274     //
   1275     gBS->OpenProtocol (
   1276           Controller,
   1277           &gEfiI2cHostProtocolGuid,
   1278           (VOID **) &I2cHost,
   1279           This->DriverBindingHandle,
   1280           Handle,
   1281           EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
   1282           );
   1283     return Status;
   1284   }
   1285 
   1286   //
   1287   // Free resources for this I2C device
   1288   //
   1289   ReleaseI2cDeviceContext (I2cDeviceContext);
   1290 
   1291   return EFI_SUCCESS;
   1292 }
   1293 
   1294 /**
   1295   Create a path for the I2C device
   1296 
   1297   Append the I2C slave path to the I2C master controller path.
   1298 
   1299   @param[in] I2cDeviceContext           Address of an I2C_DEVICE_CONTEXT structure.
   1300   @param[in] BuildControllerNode        Flag to build controller node in device path.
   1301 
   1302   @retval EFI_SUCCESS           The I2C device path is built successfully.
   1303   @return Others                It is failed to built device path.
   1304 
   1305 **/
   1306 EFI_STATUS
   1307 I2cBusDevicePathAppend (
   1308   IN I2C_DEVICE_CONTEXT     *I2cDeviceContext,
   1309   IN BOOLEAN                BuildControllerNode
   1310   )
   1311 {
   1312   EFI_DEVICE_PATH_PROTOCOL  *PreviousDevicePath;
   1313 
   1314   PreviousDevicePath = NULL;
   1315 
   1316   //
   1317   // Build vendor device path
   1318   //
   1319   CopyMem (&gVendorDevicePathTemplate.Guid, I2cDeviceContext->I2cDevice->DeviceGuid, sizeof (EFI_GUID));
   1320   I2cDeviceContext->DevicePath                    = AppendDevicePathNode (
   1321                                                       I2cDeviceContext->I2cBusContext->ParentDevicePath,
   1322                                                       (EFI_DEVICE_PATH_PROTOCOL *) &gVendorDevicePathTemplate
   1323                                                       );
   1324   ASSERT (I2cDeviceContext->DevicePath != NULL);
   1325   if (I2cDeviceContext->DevicePath == NULL) {
   1326     return EFI_OUT_OF_RESOURCES;
   1327   }
   1328 
   1329   if ((BuildControllerNode) && (I2cDeviceContext->DevicePath != NULL)) {
   1330     //
   1331     // Build the final I2C device path with controller node
   1332     //
   1333     PreviousDevicePath = I2cDeviceContext->DevicePath;
   1334     gControllerDevicePathTemplate.ControllerNumber = I2cDeviceContext->I2cDevice->DeviceIndex;
   1335     I2cDeviceContext->DevicePath          = AppendDevicePathNode (
   1336                                               I2cDeviceContext->DevicePath,
   1337                                               (EFI_DEVICE_PATH_PROTOCOL *) &gControllerDevicePathTemplate
   1338                                               );
   1339     gBS->FreePool (PreviousDevicePath);
   1340     ASSERT (I2cDeviceContext->DevicePath != NULL);
   1341     if (I2cDeviceContext->DevicePath == NULL) {
   1342       return EFI_OUT_OF_RESOURCES;
   1343     }
   1344   }
   1345 
   1346   return EFI_SUCCESS;
   1347 }
   1348 
   1349 /**
   1350   The user entry point for the I2C bus module. The user code starts with
   1351   this function.
   1352 
   1353   @param[in] ImageHandle    The firmware allocated handle for the EFI image.
   1354   @param[in] SystemTable    A pointer to the EFI System Table.
   1355 
   1356   @retval EFI_SUCCESS       The entry point is executed successfully.
   1357   @retval other             Some error occurs when executing this entry point.
   1358 
   1359 **/
   1360 EFI_STATUS
   1361 EFIAPI
   1362 InitializeI2cBus(
   1363   IN EFI_HANDLE           ImageHandle,
   1364   IN EFI_SYSTEM_TABLE     *SystemTable
   1365   )
   1366 {
   1367   EFI_STATUS              Status;
   1368 
   1369   //
   1370   // Install driver model protocol(s).
   1371   //
   1372   Status = EfiLibInstallDriverBindingComponentName2 (
   1373              ImageHandle,
   1374              SystemTable,
   1375              &gI2cBusDriverBinding,
   1376              NULL,
   1377              &gI2cBusComponentName,
   1378              &gI2cBusComponentName2
   1379              );
   1380   ASSERT_EFI_ERROR (Status);
   1381 
   1382 
   1383   return Status;
   1384 }
   1385 
   1386 /**
   1387   This is the unload handle for I2C bus module.
   1388 
   1389   Disconnect the driver specified by ImageHandle from all the devices in the handle database.
   1390   Uninstall all the protocols installed in the driver entry point.
   1391 
   1392   @param[in] ImageHandle           The drivers' driver image.
   1393 
   1394   @retval    EFI_SUCCESS           The image is unloaded.
   1395   @retval    Others                Failed to unload the image.
   1396 
   1397 **/
   1398 EFI_STATUS
   1399 EFIAPI
   1400 I2cBusUnload (
   1401   IN EFI_HANDLE             ImageHandle
   1402   )
   1403 {
   1404   EFI_STATUS                        Status;
   1405   EFI_HANDLE                        *DeviceHandleBuffer;
   1406   UINTN                             DeviceHandleCount;
   1407   UINTN                             Index;
   1408   EFI_COMPONENT_NAME_PROTOCOL       *ComponentName;
   1409   EFI_COMPONENT_NAME2_PROTOCOL      *ComponentName2;
   1410 
   1411   //
   1412   // Get the list of all I2C Controller handles in the handle database.
   1413   // If there is an error getting the list, then the unload
   1414   // operation fails.
   1415   //
   1416   Status = gBS->LocateHandleBuffer (
   1417                   ByProtocol,
   1418                   &gEfiI2cHostProtocolGuid,
   1419                   NULL,
   1420                   &DeviceHandleCount,
   1421                   &DeviceHandleBuffer
   1422                   );
   1423 
   1424   if (!EFI_ERROR (Status)) {
   1425     //
   1426     // Disconnect the driver specified by Driver BindingHandle from all
   1427     // the devices in the handle database.
   1428     //
   1429     for (Index = 0; Index < DeviceHandleCount; Index++) {
   1430       Status = gBS->DisconnectController (
   1431                       DeviceHandleBuffer[Index],
   1432                       gI2cBusDriverBinding.DriverBindingHandle,
   1433                       NULL
   1434                       );
   1435       if (EFI_ERROR (Status)) {
   1436         goto Done;
   1437       }
   1438     }
   1439   }
   1440 
   1441   //
   1442   // Uninstall all the protocols installed in the driver entry point
   1443   //
   1444   Status = gBS->UninstallMultipleProtocolInterfaces (
   1445                   gI2cBusDriverBinding.DriverBindingHandle,
   1446                   &gEfiDriverBindingProtocolGuid,
   1447                   &gI2cBusDriverBinding,
   1448                   NULL
   1449                   );
   1450   ASSERT_EFI_ERROR (Status);
   1451 
   1452   //
   1453   // Note we have to one by one uninstall the following protocols.
   1454   // It's because some of them are optionally installed based on
   1455   // the following PCD settings.
   1456   //   gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnosticsDisable
   1457   //   gEfiMdePkgTokenSpaceGuid.PcdComponentNameDisable
   1458   //   gEfiMdePkgTokenSpaceGuid.PcdDriverDiagnostics2Disable
   1459   //   gEfiMdePkgTokenSpaceGuid.PcdComponentName2Disable
   1460   //
   1461   Status = gBS->HandleProtocol (
   1462                   gI2cBusDriverBinding.DriverBindingHandle,
   1463                   &gEfiComponentNameProtocolGuid,
   1464                   (VOID **) &ComponentName
   1465                   );
   1466   if (!EFI_ERROR (Status)) {
   1467     gBS->UninstallProtocolInterface (
   1468            gI2cBusDriverBinding.DriverBindingHandle,
   1469            &gEfiComponentNameProtocolGuid,
   1470            ComponentName
   1471            );
   1472   }
   1473 
   1474   Status = gBS->HandleProtocol (
   1475                   gI2cBusDriverBinding.DriverBindingHandle,
   1476                   &gEfiComponentName2ProtocolGuid,
   1477                   (VOID **) &ComponentName2
   1478                   );
   1479   if (!EFI_ERROR (Status)) {
   1480     gBS->UninstallProtocolInterface (
   1481            gI2cBusDriverBinding.DriverBindingHandle,
   1482            &gEfiComponentName2ProtocolGuid,
   1483            ComponentName2
   1484            );
   1485   }
   1486 
   1487   Status = EFI_SUCCESS;
   1488 
   1489 Done:
   1490   //
   1491   // Free the buffer containing the list of handles from the handle database
   1492   //
   1493   if (DeviceHandleBuffer != NULL) {
   1494     gBS->FreePool (DeviceHandleBuffer);
   1495   }
   1496 
   1497   return Status;
   1498 }
   1499