Home | History | Annotate | Download | only in IdeBusDxe
      1 /** @file
      2   Implementation of UEFI driver Dialnostics protocol which to perform diagnostic on the IDE
      3   Bus controller.
      4 
      5   Copyright (c) 2006 - 2011, 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 
     17 #include "IdeBus.h"
     18 
     19 #define IDE_BUS_DIAGNOSTIC_ERROR  L"PCI IDE/ATAPI Driver Diagnostics Failed"
     20 
     21 //
     22 // EFI Driver Diagnostics Protocol
     23 //
     24 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = {
     25   IDEBusDriverDiagnosticsRunDiagnostics,
     26   "eng"
     27 };
     28 
     29 //
     30 // EFI Driver Diagnostics 2 Protocol
     31 //
     32 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2 = {
     33   (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) IDEBusDriverDiagnosticsRunDiagnostics,
     34   "en"
     35 };
     36 
     37 /**
     38   Runs diagnostics on a controller.
     39 
     40   @param  This             A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance.
     41   @param  ControllerHandle The handle of the controller to run diagnostics on.
     42   @param  ChildHandle      The handle of the child controller to run diagnostics on
     43                            This is an optional parameter that may be NULL.  It will
     44                            be NULL for device drivers.  It will also be NULL for a
     45                            bus drivers that wish to run diagnostics on the bus controller.
     46                            It will not be NULL for a bus driver that wishes to run
     47                            diagnostics on one of its child controllers.
     48   @param  DiagnosticType   Indicates type of diagnostics to perform on the controller
     49                            specified by ControllerHandle and ChildHandle.
     50   @param  Language         A pointer to a three character ISO 639-2 language identifier.
     51                            This is the language in which the optional error message should
     52                            be returned in Buffer, and it must match one of the languages
     53                            specified in SupportedLanguages. The number of languages supported by
     54                            a driver is up to the driver writer.
     55   @param  ErrorType        A GUID that defines the format of the data returned in Buffer.
     56   @param  BufferSize       The size, in bytes, of the data returned in Buffer.
     57   @param  Buffer           A buffer that contains a Null-terminated Unicode string
     58                            plus some additional data whose format is defined by ErrorType.
     59                            Buffer is allocated by this function with AllocatePool(), and
     60                            it is the caller's responsibility to free it with a call to FreePool().
     61 
     62   @retval  EFI_SUCCESS           The controller specified by ControllerHandle and ChildHandle passed
     63                                  the diagnostic.
     64   @retval  EFI_INVALID_PARAMETER ControllerHandle is NULL.
     65   @retval  EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
     66   @retval  EFI_INVALID_PARAMETER Language is NULL.
     67   @retval  EFI_INVALID_PARAMETER ErrorType is NULL.
     68   @retval  EFI_INVALID_PARAMETER BufferType is NULL.
     69   @retval  EFI_INVALID_PARAMETER Buffer is NULL.
     70   @retval  EFI_UNSUPPORTED       The driver specified by This does not support running
     71                                  diagnostics for the controller specified by ControllerHandle
     72                                  and ChildHandle.
     73   @retval  EFI_UNSUPPORTED       The driver specified by This does not support the
     74                                  type of diagnostic specified by DiagnosticType.
     75   @retval  EFI_UNSUPPORTED       The driver specified by This does not support the language
     76                                  specified by Language.
     77   @retval  EFI_OUT_OF_RESOURCES  There are not enough resources available to complete the
     78                                  diagnostics.
     79   @retval  EFI_OUT_OF_RESOURCES  There are not enough resources available to return the
     80                                  status information in ErrorType, BufferSize,and Buffer.
     81   @retval  EFI_DEVICE_ERROR      The controller specified by ControllerHandle and ChildHandle
     82                                  did not pass the diagnostic.
     83 **/
     84 EFI_STATUS
     85 EFIAPI
     86 IDEBusDriverDiagnosticsRunDiagnostics (
     87   IN  EFI_DRIVER_DIAGNOSTICS_PROTOCOL               *This,
     88   IN  EFI_HANDLE                                    ControllerHandle,
     89   IN  EFI_HANDLE                                    ChildHandle  OPTIONAL,
     90   IN  EFI_DRIVER_DIAGNOSTIC_TYPE                    DiagnosticType,
     91   IN  CHAR8                                         *Language,
     92   OUT EFI_GUID                                      **ErrorType,
     93   OUT UINTN                                         *BufferSize,
     94   OUT CHAR16                                        **Buffer
     95   )
     96 {
     97   EFI_STATUS            Status;
     98   EFI_PCI_IO_PROTOCOL   *PciIo;
     99   EFI_BLOCK_IO_PROTOCOL *BlkIo;
    100   IDE_BLK_IO_DEV        *IdeBlkIoDevice;
    101   UINT32                VendorDeviceId;
    102   VOID                  *BlockBuffer;
    103   CHAR8                 *SupportedLanguages;
    104   BOOLEAN               Iso639Language;
    105   BOOLEAN               Found;
    106   UINTN                 Index;
    107 
    108   if (Language         == NULL ||
    109       ErrorType        == NULL ||
    110       Buffer           == NULL ||
    111       ControllerHandle == NULL ||
    112       BufferSize       == NULL) {
    113 
    114     return EFI_INVALID_PARAMETER;
    115   }
    116 
    117   SupportedLanguages = This->SupportedLanguages;
    118   Iso639Language = (BOOLEAN)(This == &gIDEBusDriverDiagnostics);
    119   //
    120   // Make sure Language is in the set of Supported Languages
    121   //
    122   Found = FALSE;
    123   while (*SupportedLanguages != 0) {
    124     if (Iso639Language) {
    125       if (CompareMem (Language, SupportedLanguages, 3) == 0) {
    126         Found = TRUE;
    127         break;
    128       }
    129       SupportedLanguages += 3;
    130     } else {
    131       for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
    132       if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) {
    133         Found = TRUE;
    134         break;
    135       }
    136       SupportedLanguages += Index;
    137       for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
    138     }
    139   }
    140   //
    141   // If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
    142   //
    143   if (!Found) {
    144     return EFI_UNSUPPORTED;
    145   }
    146 
    147   *ErrorType  = NULL;
    148   *BufferSize = 0;
    149 
    150   if (ChildHandle == NULL) {
    151     Status = gBS->OpenProtocol (
    152                     ControllerHandle,
    153                     &gEfiCallerIdGuid,
    154                     NULL,
    155                     gIDEBusDriverBinding.DriverBindingHandle,
    156                     ControllerHandle,
    157                     EFI_OPEN_PROTOCOL_TEST_PROTOCOL
    158                     );
    159     if (EFI_ERROR (Status)) {
    160       return Status;
    161     }
    162 
    163     Status = gBS->OpenProtocol (
    164                     ControllerHandle,
    165                     &gEfiPciIoProtocolGuid,
    166                     (VOID **) &PciIo,
    167                     gIDEBusDriverBinding.DriverBindingHandle,
    168                     ControllerHandle,
    169                     EFI_OPEN_PROTOCOL_GET_PROTOCOL
    170                     );
    171     if (EFI_ERROR (Status)) {
    172       return EFI_DEVICE_ERROR;
    173     }
    174 
    175     //
    176     // Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller
    177     // The following test simply reads the Device ID and Vendor ID.
    178     // It should never fail.  A real test would perform more advanced
    179     // diagnostics.
    180     //
    181 
    182     Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId);
    183     if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) {
    184       return EFI_DEVICE_ERROR;
    185     }
    186 
    187     return EFI_SUCCESS;
    188   }
    189 
    190   Status = gBS->OpenProtocol (
    191                   ChildHandle,
    192                   &gEfiBlockIoProtocolGuid,
    193                   (VOID **) &BlkIo,
    194                   gIDEBusDriverBinding.DriverBindingHandle,
    195                   ChildHandle,
    196                   EFI_OPEN_PROTOCOL_GET_PROTOCOL
    197                   );
    198   if (EFI_ERROR (Status)) {
    199     return Status;
    200   }
    201 
    202   IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
    203 
    204   //
    205   // Use services available from IdeBlkIoDevice to test the IDE/ATAPI device
    206   //
    207   Status = gBS->AllocatePool (
    208                   EfiBootServicesData,
    209                   IdeBlkIoDevice->BlkMedia.BlockSize,
    210                   (VOID **) &BlockBuffer
    211                   );
    212   if (EFI_ERROR (Status)) {
    213     return Status;
    214   }
    215 
    216   Status = IdeBlkIoDevice->BlkIo.ReadBlocks (
    217                                   &IdeBlkIoDevice->BlkIo,
    218                                   IdeBlkIoDevice->BlkMedia.MediaId,
    219                                   0,
    220                                   IdeBlkIoDevice->BlkMedia.BlockSize,
    221                                   BlockBuffer
    222                                   );
    223 
    224   if (EFI_ERROR (Status)) {
    225     *ErrorType  = &gEfiCallerIdGuid;
    226     *BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR);
    227 
    228     Status = gBS->AllocatePool (
    229                     EfiBootServicesData,
    230                     (UINTN) (*BufferSize),
    231                     (VOID **) Buffer
    232                     );
    233     if (EFI_ERROR (Status)) {
    234       return Status;
    235     }
    236 
    237     CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize);
    238 
    239     Status = EFI_DEVICE_ERROR;
    240   }
    241 
    242   gBS->FreePool (BlockBuffer);
    243 
    244   return Status;
    245 }
    246