• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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
I2cBusComponentNameGetDriverName(IN EFI_COMPONENT_NAME2_PROTOCOL * This,IN CHAR8 * Language,OUT CHAR16 ** DriverName)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
I2cBusComponentNameGetControllerName(IN EFI_COMPONENT_NAME2_PROTOCOL * This,IN EFI_HANDLE ControllerHandle,IN EFI_HANDLE ChildHandle OPTIONAL,IN CHAR8 * Language,OUT CHAR16 ** ControllerName)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
CheckRemainingDevicePath(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath,IN BOOLEAN RemainingHasControllerNode,IN UINT32 RemainingControllerNumber)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
I2cBusDriverSupported(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
I2cBusDriverStart(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
I2cBusDriverStop(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN UINTN NumberOfChildren,IN EFI_HANDLE * ChildHandleBuffer)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
RegisterI2cDevice(IN I2C_BUS_CONTEXT * I2cBusContext,IN EFI_HANDLE Controller,IN EFI_DEVICE_PATH_PROTOCOL * RemainingDevicePath)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
I2cBusQueueRequest(IN CONST EFI_I2C_IO_PROTOCOL * This,IN UINTN SlaveAddressIndex,IN EFI_EVENT Event OPTIONAL,IN EFI_I2C_REQUEST_PACKET * RequestPacket,OUT EFI_STATUS * I2cStatus OPTIONAL)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
ReleaseI2cDeviceContext(IN I2C_DEVICE_CONTEXT * I2cDeviceContext)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
UnRegisterI2cDevice(IN EFI_DRIVER_BINDING_PROTOCOL * This,IN EFI_HANDLE Controller,IN EFI_HANDLE Handle)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
I2cBusDevicePathAppend(IN I2C_DEVICE_CONTEXT * I2cDeviceContext,IN BOOLEAN BuildControllerNode)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
InitializeI2cBus(IN EFI_HANDLE ImageHandle,IN EFI_SYSTEM_TABLE * SystemTable)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
I2cBusUnload(IN EFI_HANDLE ImageHandle)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