2007-06-28 16:02:17 +02:00
|
|
|
/** @file
|
2009-06-24 04:21:05 +02:00
|
|
|
Implementation of UEFI driver Dialnostics protocol which to perform diagnostic on the IDE
|
|
|
|
Bus controller.
|
|
|
|
|
2011-07-05 11:21:58 +02:00
|
|
|
Copyright (c) 2006 - 2011, Intel Corporation. All rights reserved.<BR>
|
2010-04-23 18:28:26 +02:00
|
|
|
This program and the accompanying materials
|
2007-06-28 16:02:17 +02:00
|
|
|
are licensed and made available under the terms and conditions of the BSD License
|
|
|
|
which accompanies this distribution. The full text of the license may be found at
|
|
|
|
http://opensource.org/licenses/bsd-license.php
|
|
|
|
|
|
|
|
THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
|
|
|
|
WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
|
|
|
|
|
|
|
|
**/
|
|
|
|
|
|
|
|
|
2008-07-16 04:54:54 +02:00
|
|
|
#include "IdeBus.h"
|
2007-06-28 16:02:17 +02:00
|
|
|
|
|
|
|
#define IDE_BUS_DIAGNOSTIC_ERROR L"PCI IDE/ATAPI Driver Diagnostics Failed"
|
|
|
|
|
|
|
|
//
|
|
|
|
// EFI Driver Diagnostics Protocol
|
|
|
|
//
|
2007-10-30 07:45:44 +01:00
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS_PROTOCOL gIDEBusDriverDiagnostics = {
|
2007-06-28 16:02:17 +02:00
|
|
|
IDEBusDriverDiagnosticsRunDiagnostics,
|
|
|
|
"eng"
|
|
|
|
};
|
|
|
|
|
2007-10-30 07:45:44 +01:00
|
|
|
//
|
|
|
|
// EFI Driver Diagnostics 2 Protocol
|
|
|
|
//
|
|
|
|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gIDEBusDriverDiagnostics2 = {
|
|
|
|
(EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) IDEBusDriverDiagnosticsRunDiagnostics,
|
|
|
|
"en"
|
|
|
|
};
|
|
|
|
|
2007-06-28 16:02:17 +02:00
|
|
|
/**
|
|
|
|
Runs diagnostics on a controller.
|
|
|
|
|
2009-06-24 04:21:05 +02:00
|
|
|
@param This A pointer to the EFI_DRIVER_DIAGNOSTICS_PROTOCOLinstance.
|
2007-06-28 16:02:17 +02:00
|
|
|
@param ControllerHandle The handle of the controller to run diagnostics on.
|
2009-06-24 04:21:05 +02:00
|
|
|
@param ChildHandle The handle of the child controller to run diagnostics on
|
|
|
|
This is an optional parameter that may be NULL. It will
|
|
|
|
be NULL for device drivers. It will also be NULL for a
|
|
|
|
bus drivers that wish to run diagnostics on the bus controller.
|
|
|
|
It will not be NULL for a bus driver that wishes to run
|
|
|
|
diagnostics on one of its child controllers.
|
|
|
|
@param DiagnosticType Indicates type of diagnostics to perform on the controller
|
|
|
|
specified by ControllerHandle and ChildHandle.
|
|
|
|
@param Language A pointer to a three character ISO 639-2 language identifier.
|
|
|
|
This is the language in which the optional error message should
|
|
|
|
be returned in Buffer, and it must match one of the languages
|
|
|
|
specified in SupportedLanguages. The number of languages supported by
|
|
|
|
a driver is up to the driver writer.
|
|
|
|
@param ErrorType A GUID that defines the format of the data returned in Buffer.
|
|
|
|
@param BufferSize The size, in bytes, of the data returned in Buffer.
|
|
|
|
@param Buffer A buffer that contains a Null-terminated Unicode string
|
|
|
|
plus some additional data whose format is defined by ErrorType.
|
|
|
|
Buffer is allocated by this function with AllocatePool(), and
|
|
|
|
it is the caller's responsibility to free it with a call to FreePool().
|
2007-06-28 16:02:17 +02:00
|
|
|
|
2009-06-24 04:21:05 +02:00
|
|
|
@retval EFI_SUCCESS The controller specified by ControllerHandle and ChildHandle passed
|
|
|
|
the diagnostic.
|
2011-07-05 11:21:58 +02:00
|
|
|
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
2009-06-24 04:21:05 +02:00
|
|
|
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid EFI_HANDLE.
|
2007-06-28 16:02:17 +02:00
|
|
|
@retval EFI_INVALID_PARAMETER Language is NULL.
|
|
|
|
@retval EFI_INVALID_PARAMETER ErrorType is NULL.
|
|
|
|
@retval EFI_INVALID_PARAMETER BufferType is NULL.
|
|
|
|
@retval EFI_INVALID_PARAMETER Buffer is NULL.
|
2009-06-24 04:21:05 +02:00
|
|
|
@retval EFI_UNSUPPORTED The driver specified by This does not support running
|
|
|
|
diagnostics for the controller specified by ControllerHandle
|
|
|
|
and ChildHandle.
|
|
|
|
@retval EFI_UNSUPPORTED The driver specified by This does not support the
|
|
|
|
type of diagnostic specified by DiagnosticType.
|
|
|
|
@retval EFI_UNSUPPORTED The driver specified by This does not support the language
|
|
|
|
specified by Language.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to complete the
|
|
|
|
diagnostics.
|
|
|
|
@retval EFI_OUT_OF_RESOURCES There are not enough resources available to return the
|
|
|
|
status information in ErrorType, BufferSize,and Buffer.
|
|
|
|
@retval EFI_DEVICE_ERROR The controller specified by ControllerHandle and ChildHandle
|
|
|
|
did not pass the diagnostic.
|
2007-06-28 16:02:17 +02:00
|
|
|
**/
|
|
|
|
EFI_STATUS
|
2009-04-14 01:07:44 +02:00
|
|
|
EFIAPI
|
2007-06-28 16:02:17 +02:00
|
|
|
IDEBusDriverDiagnosticsRunDiagnostics (
|
|
|
|
IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,
|
|
|
|
IN EFI_HANDLE ControllerHandle,
|
|
|
|
IN EFI_HANDLE ChildHandle OPTIONAL,
|
|
|
|
IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,
|
|
|
|
IN CHAR8 *Language,
|
|
|
|
OUT EFI_GUID **ErrorType,
|
|
|
|
OUT UINTN *BufferSize,
|
|
|
|
OUT CHAR16 **Buffer
|
|
|
|
)
|
|
|
|
{
|
|
|
|
EFI_STATUS Status;
|
|
|
|
EFI_PCI_IO_PROTOCOL *PciIo;
|
|
|
|
EFI_BLOCK_IO_PROTOCOL *BlkIo;
|
|
|
|
IDE_BLK_IO_DEV *IdeBlkIoDevice;
|
|
|
|
UINT32 VendorDeviceId;
|
|
|
|
VOID *BlockBuffer;
|
2007-10-30 07:45:44 +01:00
|
|
|
CHAR8 *SupportedLanguages;
|
|
|
|
BOOLEAN Iso639Language;
|
|
|
|
BOOLEAN Found;
|
|
|
|
UINTN Index;
|
|
|
|
|
|
|
|
if (Language == NULL ||
|
|
|
|
ErrorType == NULL ||
|
|
|
|
Buffer == NULL ||
|
|
|
|
ControllerHandle == NULL ||
|
|
|
|
BufferSize == NULL) {
|
|
|
|
|
|
|
|
return EFI_INVALID_PARAMETER;
|
|
|
|
}
|
|
|
|
|
|
|
|
SupportedLanguages = This->SupportedLanguages;
|
|
|
|
Iso639Language = (BOOLEAN)(This == &gIDEBusDriverDiagnostics);
|
|
|
|
//
|
|
|
|
// Make sure Language is in the set of Supported Languages
|
|
|
|
//
|
|
|
|
Found = FALSE;
|
|
|
|
while (*SupportedLanguages != 0) {
|
|
|
|
if (Iso639Language) {
|
|
|
|
if (CompareMem (Language, SupportedLanguages, 3) == 0) {
|
|
|
|
Found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SupportedLanguages += 3;
|
|
|
|
} else {
|
|
|
|
for (Index = 0; SupportedLanguages[Index] != 0 && SupportedLanguages[Index] != ';'; Index++);
|
2008-02-14 03:43:38 +01:00
|
|
|
if ((AsciiStrnCmp(SupportedLanguages, Language, Index) == 0) && (Language[Index] == 0)) {
|
2007-10-30 07:45:44 +01:00
|
|
|
Found = TRUE;
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
SupportedLanguages += Index;
|
|
|
|
for (; *SupportedLanguages != 0 && *SupportedLanguages == ';'; SupportedLanguages++);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
//
|
|
|
|
// If Language is not a member of SupportedLanguages, then return EFI_UNSUPPORTED
|
|
|
|
//
|
|
|
|
if (!Found) {
|
|
|
|
return EFI_UNSUPPORTED;
|
|
|
|
}
|
2007-06-28 16:02:17 +02:00
|
|
|
|
|
|
|
*ErrorType = NULL;
|
|
|
|
*BufferSize = 0;
|
|
|
|
|
|
|
|
if (ChildHandle == NULL) {
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiCallerIdGuid,
|
|
|
|
NULL,
|
|
|
|
gIDEBusDriverBinding.DriverBindingHandle,
|
|
|
|
ControllerHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_TEST_PROTOCOL
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2008-02-19 05:16:16 +01:00
|
|
|
return Status;
|
2007-06-28 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ControllerHandle,
|
|
|
|
&gEfiPciIoProtocolGuid,
|
|
|
|
(VOID **) &PciIo,
|
|
|
|
gIDEBusDriverBinding.DriverBindingHandle,
|
|
|
|
ControllerHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return EFI_DEVICE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
//
|
|
|
|
// Use services of PCI I/O Protocol to test the PCI IDE/ATAPI Controller
|
|
|
|
// The following test simply reads the Device ID and Vendor ID.
|
|
|
|
// It should never fail. A real test would perform more advanced
|
|
|
|
// diagnostics.
|
|
|
|
//
|
|
|
|
|
|
|
|
Status = PciIo->Pci.Read (PciIo, EfiPciIoWidthUint32, 0, 1, &VendorDeviceId);
|
|
|
|
if (EFI_ERROR (Status) || VendorDeviceId == 0xffffffff) {
|
|
|
|
return EFI_DEVICE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
return EFI_SUCCESS;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = gBS->OpenProtocol (
|
|
|
|
ChildHandle,
|
|
|
|
&gEfiBlockIoProtocolGuid,
|
|
|
|
(VOID **) &BlkIo,
|
|
|
|
gIDEBusDriverBinding.DriverBindingHandle,
|
|
|
|
ChildHandle,
|
|
|
|
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
2008-02-19 05:16:16 +01:00
|
|
|
return Status;
|
2007-06-28 16:02:17 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
IdeBlkIoDevice = IDE_BLOCK_IO_DEV_FROM_THIS (BlkIo);
|
|
|
|
|
|
|
|
//
|
|
|
|
// Use services available from IdeBlkIoDevice to test the IDE/ATAPI device
|
|
|
|
//
|
|
|
|
Status = gBS->AllocatePool (
|
|
|
|
EfiBootServicesData,
|
|
|
|
IdeBlkIoDevice->BlkMedia.BlockSize,
|
|
|
|
(VOID **) &BlockBuffer
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
Status = IdeBlkIoDevice->BlkIo.ReadBlocks (
|
|
|
|
&IdeBlkIoDevice->BlkIo,
|
|
|
|
IdeBlkIoDevice->BlkMedia.MediaId,
|
|
|
|
0,
|
|
|
|
IdeBlkIoDevice->BlkMedia.BlockSize,
|
|
|
|
BlockBuffer
|
|
|
|
);
|
|
|
|
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
*ErrorType = &gEfiCallerIdGuid;
|
|
|
|
*BufferSize = sizeof (IDE_BUS_DIAGNOSTIC_ERROR);
|
|
|
|
|
|
|
|
Status = gBS->AllocatePool (
|
|
|
|
EfiBootServicesData,
|
|
|
|
(UINTN) (*BufferSize),
|
|
|
|
(VOID **) Buffer
|
|
|
|
);
|
|
|
|
if (EFI_ERROR (Status)) {
|
|
|
|
return Status;
|
|
|
|
}
|
|
|
|
|
|
|
|
CopyMem (*Buffer, IDE_BUS_DIAGNOSTIC_ERROR, *BufferSize);
|
|
|
|
|
|
|
|
Status = EFI_DEVICE_ERROR;
|
|
|
|
}
|
|
|
|
|
|
|
|
gBS->FreePool (BlockBuffer);
|
|
|
|
|
|
|
|
return Status;
|
|
|
|
}
|