mirror of https://github.com/acidanthera/audk.git
MdeModulePkg: Add UFS (Universal Flash Storage) Stack
It includes 4 drivers: 1. UfsPassThruDxe, which is a UEFI driver and consumes EFI_UFS_HOST_CONTROLLER_PROTOCOL and produces EFI_EXT_SCSI_PASS_THRU_PROTOCOL 2. UfsPciHcDxe, which is specific for pci-based UFS HC implementation and is a UEFI driver to produce EFI_UFS_HOST_CONTROLLER_PROTOCOL. 3. UfsBlockIoPei, which is a PEI driver and consumes EFI_UFS_HOST_CONTROLLER_PPI and produces EFI_PEI_VIRTUAL_BLOCK_IO_PPI. 4. UfsPciHcPei, which is specific for pci-based UFS HC implementation and is a PEI driver to produce EFI_UFS_HOST_CONTROLLER_PPI. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Star Zeng <star.zeng@intel.com> git-svn-id: https://svn.code.sf.net/p/edk2/code/trunk/edk2@17246 6f19259b-4bc3-4df7-8a09-765794883524
This commit is contained in:
parent
5230616612
commit
0591696eff
MdeModulePkg
|
@ -0,0 +1,225 @@
|
|||
/** @file
|
||||
UfsHcDxe driver produces EFI_UFS_HOST_CONTROLLER_PROTOCOL. The upper layer module
|
||||
uses it to query the MMIO base address of the UFS host controller.
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "UfsPciHcDxe.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUfsHcComponentName = {
|
||||
UfsHcComponentNameGetDriverName,
|
||||
UfsHcComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUfsHcComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UfsHcComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UfsHcComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsHcDriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"Universal Flash Storage (UFS) Pci Host Controller Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsHcControllerNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"Universal Flash Storage (UFS) Pci Host Controller"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param DriverName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mUfsHcDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gUfsHcComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||
the name of. 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 retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (Language == NULL || ControllerName == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// This is a device driver, so ChildHandle must be NULL.
|
||||
//
|
||||
if (ChildHandle != NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure this driver is currently managing Controller Handle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gUfsHcDriverBinding.DriverBindingHandle,
|
||||
&gEfiPciIoProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mUfsHcControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gUfsHcComponentName)
|
||||
);
|
||||
|
||||
}
|
|
@ -0,0 +1,699 @@
|
|||
/** @file
|
||||
UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
|
||||
MMIO base, to upper layer UFS drivers.
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "UfsPciHcDxe.h"
|
||||
|
||||
//
|
||||
// NVM Express Driver Binding Protocol Instance
|
||||
//
|
||||
EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding = {
|
||||
UfsHcDriverBindingSupported,
|
||||
UfsHcDriverBindingStart,
|
||||
UfsHcDriverBindingStop,
|
||||
0x10,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
//
|
||||
// Template for Ufs host controller private data.
|
||||
//
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA gUfsHcTemplate = {
|
||||
UFS_HC_PRIVATE_DATA_SIGNATURE, // Signature
|
||||
NULL, // Handle
|
||||
{ // UfsHcProtocol
|
||||
UfsHcGetMmioBar,
|
||||
UfsHcAllocateBuffer,
|
||||
UfsHcFreeBuffer,
|
||||
UfsHcMap,
|
||||
UfsHcUnmap,
|
||||
UfsHcFlush
|
||||
},
|
||||
NULL, // PciIo
|
||||
0 // PciAttributes
|
||||
};
|
||||
|
||||
/**
|
||||
Get the MMIO base of the UFS host controller.
|
||||
|
||||
@param[in] This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param[out] MmioBar The MMIO base address of UFS host controller.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval others The operation fails.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcGetMmioBar (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
OUT UINTN *MmioBar
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (MmioBar == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint8,
|
||||
PCI_BASE_ADDRESSREG_OFFSET,
|
||||
sizeof (UINT32),
|
||||
MmioBar
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*MmioBar &= (UINTN)~0xF;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Provides the UFS controller-specific addresses needed to access system memory.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Operation Indicates if the bus master is going to read or write to system memory.
|
||||
@param HostAddress The system memory address to map to the UFS controller.
|
||||
@param NumberOfBytes On input the number of bytes to map. On output the number of bytes
|
||||
that were mapped.
|
||||
@param DeviceAddress The resulting map address for the bus master UFS controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
|
||||
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcMap (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (HostAddress == NULL) || (NumberOfBytes == NULL) || (DeviceAddress == NULL) || (Mapping == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->Map (PciIo, Operation, HostAddress, NumberOfBytes, DeviceAddress, Mapping);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Completes the Map() operation and releases any corresponding resources.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
@retval EFI_SUCCESS The range was unmapped.
|
||||
@retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcUnmap (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN VOID *Mapping
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (Mapping == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->Unmap (PciIo, Mapping);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer
|
||||
mapping.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Type This parameter is not used and must be ignored.
|
||||
@param MemoryType The type of memory to allocate, EfiBootServicesData or
|
||||
EfiRuntimeServicesData.
|
||||
@param Pages The number of pages to allocate.
|
||||
@param HostAddress A pointer to store the base system memory address of the
|
||||
allocated range.
|
||||
@param Attributes The requested bit mask of attributes for the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were allocated.
|
||||
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
|
||||
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcAllocateBuffer (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
OUT VOID **HostAddress,
|
||||
IN UINT64 Attributes
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (HostAddress == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->AllocateBuffer (PciIo, Type, MemoryType, Pages, HostAddress, Attributes);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Frees memory that was allocated with AllocateBuffer().
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Pages The number of pages to free.
|
||||
@param HostAddress The base system memory address of the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were freed.
|
||||
@retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
|
||||
was not allocated with AllocateBuffer().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcFreeBuffer (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
if ((This == NULL) || (HostAddress == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->FreeBuffer (PciIo, Pages, HostAddress);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Flushes all posted write transactions from the UFS bus to attached UFS device.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The posted write transactions were flushed from the UFS bus
|
||||
to attached UFS device.
|
||||
@retval EFI_DEVICE_ERROR The posted write transactions were not flushed from the UFS
|
||||
bus to attached UFS device due to a hardware error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcFlush (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
EFI_STATUS Status;
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (This);
|
||||
PciIo = Private->PciIo;
|
||||
|
||||
Status = PciIo->Flush (PciIo);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Tests to see if this driver supports a given controller. If a child device is provided,
|
||||
it further tests to see if this driver supports creating a handle for the specified child device.
|
||||
|
||||
This function checks to see if the driver specified by This supports the device specified by
|
||||
ControllerHandle. Drivers will typically use the device path attached to
|
||||
ControllerHandle and/or the services from the bus I/O abstraction attached to
|
||||
ControllerHandle to determine if the driver supports ControllerHandle. This function
|
||||
may be called many times during platform initialization. In order to reduce boot times, the tests
|
||||
performed by this function must be very small, and take as little time as possible to execute. This
|
||||
function must not change the state of any hardware devices, and this function must be aware that the
|
||||
device specified by ControllerHandle may already be managed by the same driver or a
|
||||
different driver. This function must match its calls to AllocatePages() with FreePages(),
|
||||
AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
|
||||
Since ControllerHandle may have been previously started by the same driver, if a protocol is
|
||||
already in the opened state, then it must not be closed with CloseProtocol(). This is required
|
||||
to guarantee the state of ControllerHandle is not modified by this function.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to test. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For bus drivers, if this parameter is not NULL, then
|
||||
the bus driver must determine if the bus controller specified
|
||||
by ControllerHandle and the child controller specified
|
||||
by RemainingDevicePath are both supported by this
|
||||
bus driver.
|
||||
|
||||
@retval EFI_SUCCESS The device specified by ControllerHandle and
|
||||
RemainingDevicePath is supported by the driver specified by This.
|
||||
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by the driver
|
||||
specified by This.
|
||||
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by a different
|
||||
driver or an application that requires exclusive access.
|
||||
Currently not implemented.
|
||||
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is not supported by the driver specified by This.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN UfsHcFound;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
PCI_TYPE00 PciData;
|
||||
|
||||
PciIo = NULL;
|
||||
ParentDevicePath = NULL;
|
||||
UfsHcFound = FALSE;
|
||||
|
||||
//
|
||||
// UfsHcDxe is a device driver, and should ingore the
|
||||
// "RemainingDevicePath" according to EFI spec
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID *) &ParentDevicePath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// EFI_ALREADY_STARTED is also an error
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Close the protocol because we don't use it here
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
//
|
||||
// Now test the EfiPciIoProtocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &PciIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Now further check the PCI header: Base class (offset 0x0B) and
|
||||
// Sub Class (offset 0x0A). This controller should be an UFS controller
|
||||
//
|
||||
Status = PciIo->Pci.Read (
|
||||
PciIo,
|
||||
EfiPciIoWidthUint8,
|
||||
0,
|
||||
sizeof (PciData),
|
||||
&PciData
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
//
|
||||
// Since we already got the PciData, we can close protocol to avoid to carry it on for multiple exit points.
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
//
|
||||
// Examine UFS Host Controller PCI Configuration table fields
|
||||
//
|
||||
if (PciData.Hdr.ClassCode[2] == PCI_CLASS_MASS_STORAGE) {
|
||||
if (PciData.Hdr.ClassCode[1] == 0x09 ) { //UFS Controller Subclass
|
||||
UfsHcFound = TRUE;
|
||||
}
|
||||
}
|
||||
|
||||
if (!UfsHcFound) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Starts a device controller or a bus controller.
|
||||
|
||||
The Start() function is designed to be invoked from the EFI boot service ConnectController().
|
||||
As a result, much of the error checking on the parameters to Start() has been moved into this
|
||||
common boot service. It is legal to call Start() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE.
|
||||
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
|
||||
EFI_DEVICE_PATH_PROTOCOL.
|
||||
3. Prior to calling Start(), the Supported() function for the driver specified by This must
|
||||
have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to start. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For a bus driver, if this parameter is NULL, then handles
|
||||
for all the children of Controller are created by this driver.
|
||||
If this parameter is not NULL and the first Device Path Node is
|
||||
not the End of Device Path Node, then only the handle for the
|
||||
child device specified by the first Device Path Node of
|
||||
RemainingDevicePath is created by this driver.
|
||||
If the first Device Path Node of RemainingDevicePath is
|
||||
the End of Device Path Node, no child handle is created by this
|
||||
driver.
|
||||
|
||||
@retval EFI_SUCCESS The device was started.
|
||||
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval Others The driver failded to start the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
UINT64 Supports;
|
||||
|
||||
PciIo = NULL;
|
||||
Private = NULL;
|
||||
Supports = 0;
|
||||
|
||||
//
|
||||
// Now test and open the EfiPciIoProtocol
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
(VOID **) &PciIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
//
|
||||
// Status == 0 - A normal execution flow, SUCCESS and the program proceeds.
|
||||
// Status == ALREADY_STARTED - A non-zero Status code returned. It indicates
|
||||
// that the protocol has been opened and should be treated as a
|
||||
// normal condition and the program proceeds. The Protocol will not
|
||||
// opened 'again' by this call.
|
||||
// Status != ALREADY_STARTED - Error status, terminate program execution
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// EFI_ALREADY_STARTED is also an error
|
||||
//
|
||||
return Status;
|
||||
}
|
||||
|
||||
Private = AllocateCopyPool (sizeof (UFS_HOST_CONTROLLER_PRIVATE_DATA), &gUfsHcTemplate);
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Private->PciIo = PciIo;
|
||||
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationGet,
|
||||
0,
|
||||
&Private->PciAttributes
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationSupported,
|
||||
0,
|
||||
&Supports
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Supports &= (UINT64)EFI_PCI_DEVICE_ENABLE;
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationEnable,
|
||||
Supports,
|
||||
NULL
|
||||
);
|
||||
} else {
|
||||
goto Done;
|
||||
}
|
||||
|
||||
///
|
||||
/// Install UFS_HOST_CONTROLLER protocol
|
||||
///
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&Controller,
|
||||
&gEdkiiUfsHostControllerProtocolGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
(VOID*)&(Private->UfsHc)
|
||||
);
|
||||
|
||||
Done:
|
||||
if (EFI_ERROR (Status)) {
|
||||
if ((Private != NULL) && (Private->PciAttributes != 0)) {
|
||||
//
|
||||
// Restore original PCI attributes
|
||||
//
|
||||
Status = PciIo->Attributes (
|
||||
PciIo,
|
||||
EfiPciIoAttributeOperationSet,
|
||||
Private->PciAttributes,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
}
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
if (Private != NULL) {
|
||||
FreePool (Private);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Stops a device controller or a bus controller.
|
||||
|
||||
The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
|
||||
As a result, much of the error checking on the parameters to Stop() has been moved
|
||||
into this common boot service. It is legal to call Stop() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
|
||||
same driver's Start() function.
|
||||
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
|
||||
EFI_HANDLE. In addition, all of these handles must have been created in this driver's
|
||||
Start() function, and the Start() function must have called OpenProtocol() on
|
||||
ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
||||
support a bus specific I/O protocol for the driver
|
||||
to use to stop the device.
|
||||
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
||||
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA *Private;
|
||||
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHc;
|
||||
|
||||
///
|
||||
/// Get private data
|
||||
///
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEdkiiUfsHostControllerProtocolGuid,
|
||||
(VOID **) &UfsHc,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Private = UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC (UfsHc);
|
||||
|
||||
Status = gBS->UninstallProtocolInterface (
|
||||
Controller,
|
||||
&gEdkiiUfsHostControllerProtocolGuid,
|
||||
&(Private->UfsHc)
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// Restore original PCI attributes
|
||||
//
|
||||
Status = Private->PciIo->Attributes (
|
||||
Private->PciIo,
|
||||
EfiPciIoAttributeOperationSet,
|
||||
Private->PciAttributes,
|
||||
NULL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
//
|
||||
// Close protocols opened by UFS host controller driver
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiPciIoProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
FreePool (Private);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The entry point for UFS host controller driver, used to install this driver on the ImageHandle.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for this driver image.
|
||||
@param[in] SystemTable Pointer to the EFI system table.
|
||||
|
||||
@retval EFI_SUCCESS Driver loaded.
|
||||
@retval other Driver not loaded.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverEntry (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
Status = EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gUfsHcDriverBinding,
|
||||
ImageHandle,
|
||||
&gUfsHcComponentName,
|
||||
&gUfsHcComponentName2
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,453 @@
|
|||
/** @file
|
||||
UfsHcDxe driver is used to provide platform-dependent info, mainly UFS host controller
|
||||
MMIO base, to upper layer UFS drivers.
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EFI_UFS_HOST_CONTROLLER_H_
|
||||
#define _EFI_UFS_HOST_CONTROLLER_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
|
||||
#include <Protocol/ComponentName.h>
|
||||
#include <Protocol/ComponentName2.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Protocol/LoadedImage.h>
|
||||
#include <Protocol/DevicePath.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/UfsHostController.h>
|
||||
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gUfsHcDriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gUfsHcComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gUfsHcComponentName2;
|
||||
|
||||
//
|
||||
// Unique signature for private data structure.
|
||||
//
|
||||
#define UFS_HC_PRIVATE_DATA_SIGNATURE SIGNATURE_32 ('U','F','S','H')
|
||||
|
||||
typedef struct _UFS_HOST_CONTROLLER_PRIVATE_DATA UFS_HOST_CONTROLLER_PRIVATE_DATA;
|
||||
|
||||
//
|
||||
// Nvme private data structure.
|
||||
//
|
||||
struct _UFS_HOST_CONTROLLER_PRIVATE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
|
||||
EDKII_UFS_HOST_CONTROLLER_PROTOCOL UfsHc;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
UINT64 PciAttributes;
|
||||
};
|
||||
|
||||
#define UFS_HOST_CONTROLLER_PRIVATE_DATA_FROM_UFSHC(a) \
|
||||
CR (a, \
|
||||
UFS_HOST_CONTROLLER_PRIVATE_DATA, \
|
||||
UfsHc, \
|
||||
UFS_HC_PRIVATE_DATA_SIGNATURE \
|
||||
)
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param DriverName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||
the name of. 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 retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
/**
|
||||
Tests to see if this driver supports a given controller. If a child device is provided,
|
||||
it further tests to see if this driver supports creating a handle for the specified child device.
|
||||
|
||||
This function checks to see if the driver specified by This supports the device specified by
|
||||
ControllerHandle. Drivers will typically use the device path attached to
|
||||
ControllerHandle and/or the services from the bus I/O abstraction attached to
|
||||
ControllerHandle to determine if the driver supports ControllerHandle. This function
|
||||
may be called many times during platform initialization. In order to reduce boot times, the tests
|
||||
performed by this function must be very small, and take as little time as possible to execute. This
|
||||
function must not change the state of any hardware devices, and this function must be aware that the
|
||||
device specified by ControllerHandle may already be managed by the same driver or a
|
||||
different driver. This function must match its calls to AllocatePages() with FreePages(),
|
||||
AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
|
||||
Since ControllerHandle may have been previously started by the same driver, if a protocol is
|
||||
already in the opened state, then it must not be closed with CloseProtocol(). This is required
|
||||
to guarantee the state of ControllerHandle is not modified by this function.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to test. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For bus drivers, if this parameter is not NULL, then
|
||||
the bus driver must determine if the bus controller specified
|
||||
by ControllerHandle and the child controller specified
|
||||
by RemainingDevicePath are both supported by this
|
||||
bus driver.
|
||||
|
||||
@retval EFI_SUCCESS The device specified by ControllerHandle and
|
||||
RemainingDevicePath is supported by the driver specified by This.
|
||||
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by the driver
|
||||
specified by This.
|
||||
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by a different
|
||||
driver or an application that requires exclusive access.
|
||||
Currently not implemented.
|
||||
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is not supported by the driver specified by This.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Starts a device controller or a bus controller.
|
||||
|
||||
The Start() function is designed to be invoked from the EFI boot service ConnectController().
|
||||
As a result, much of the error checking on the parameters to Start() has been moved into this
|
||||
common boot service. It is legal to call Start() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE.
|
||||
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
|
||||
EFI_DEVICE_PATH_PROTOCOL.
|
||||
3. Prior to calling Start(), the Supported() function for the driver specified by This must
|
||||
have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to start. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For a bus driver, if this parameter is NULL, then handles
|
||||
for all the children of Controller are created by this driver.
|
||||
If this parameter is not NULL and the first Device Path Node is
|
||||
not the End of Device Path Node, then only the handle for the
|
||||
child device specified by the first Device Path Node of
|
||||
RemainingDevicePath is created by this driver.
|
||||
If the first Device Path Node of RemainingDevicePath is
|
||||
the End of Device Path Node, no child handle is created by this
|
||||
driver.
|
||||
|
||||
@retval EFI_SUCCESS The device was started.
|
||||
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval Others The driver failded to start the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Stops a device controller or a bus controller.
|
||||
|
||||
The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
|
||||
As a result, much of the error checking on the parameters to Stop() has been moved
|
||||
into this common boot service. It is legal to call Stop() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
|
||||
same driver's Start() function.
|
||||
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
|
||||
EFI_HANDLE. In addition, all of these handles must have been created in this driver's
|
||||
Start() function, and the Start() function must have called OpenProtocol() on
|
||||
ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
||||
support a bus specific I/O protocol for the driver
|
||||
to use to stop the device.
|
||||
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
||||
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
Get the MMIO base of the UFS host controller.
|
||||
|
||||
@param[in] This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param[out] MmioBar The MMIO base address of UFS host controller.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval others The operation fails.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcGetMmioBar (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
OUT UINTN *MmioBar
|
||||
);
|
||||
|
||||
/**
|
||||
Provides the UFS controller-specific addresses needed to access system memory.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Operation Indicates if the bus master is going to read or write to system memory.
|
||||
@param HostAddress The system memory address to map to the UFS controller.
|
||||
@param NumberOfBytes On input the number of bytes to map. On output the number of bytes
|
||||
that were mapped.
|
||||
@param DeviceAddress The resulting map address for the bus master UFS controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
|
||||
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcMap (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Completes the Map() operation and releases any corresponding resources.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
@retval EFI_SUCCESS The range was unmapped.
|
||||
@retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcUnmap (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN VOID *Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer
|
||||
mapping.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Type This parameter is not used and must be ignored.
|
||||
@param MemoryType The type of memory to allocate, EfiBootServicesData or
|
||||
EfiRuntimeServicesData.
|
||||
@param Pages The number of pages to allocate.
|
||||
@param HostAddress A pointer to store the base system memory address of the
|
||||
allocated range.
|
||||
@param Attributes The requested bit mask of attributes for the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were allocated.
|
||||
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
|
||||
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcAllocateBuffer (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
OUT VOID **HostAddress,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
/**
|
||||
Frees memory that was allocated with AllocateBuffer().
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Pages The number of pages to free.
|
||||
@param HostAddress The base system memory address of the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were freed.
|
||||
@retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
|
||||
was not allocated with AllocateBuffer().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcFreeBuffer (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Flushes all posted write transactions from the UFS bus to attached UFS device.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The posted write transactions were flushed from the UFS bus
|
||||
to attached UFS device.
|
||||
@retval EFI_DEVICE_ERROR The posted write transactions were not flushed from the UFS
|
||||
bus to attached UFS device due to a hardware error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsHcFlush (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
## @file
|
||||
# Component Description File For Universal Flash Storage Pci Host Controller Module.
|
||||
#
|
||||
# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = UfsPciHcDxe
|
||||
MODULE_UNI_FILE = UfsPciHcDxe.uni
|
||||
FILE_GUID = AF43E178-C2E9-4712-A7CD-08BFDAC7482C
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 0.9
|
||||
ENTRY_POINT = UfsHcDriverEntry
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gUfsHcDriverBinding
|
||||
# COMPONENT_NAME = gUfsHcComponentName
|
||||
# COMPONENT_NAME2 = gUfsHcComponentName2
|
||||
|
||||
[Sources]
|
||||
ComponentName.c
|
||||
UfsPciHcDxe.c
|
||||
UfsPciHcDxe.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
BaseLib
|
||||
DebugLib
|
||||
DevicePathLib
|
||||
UefiDriverEntryPoint
|
||||
UefiBootServicesTableLib
|
||||
UefiLib
|
||||
|
||||
[Protocols]
|
||||
gEfiPciIoProtocolGuid ## TO_START
|
||||
gEfiDevicePathProtocolGuid ## TO_START
|
||||
gEdkiiUfsHostControllerProtocolGuid ## BY_START
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
UfsPciHcDxeExtra.uni
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,152 @@
|
|||
/** @file
|
||||
UfsPciHcPei driver is used to provide platform-dependent info, mainly UFS host controller
|
||||
MMIO base, to upper layer UFS drivers.
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "UfsPciHcPei.h"
|
||||
|
||||
EDKII_UFS_HOST_CONTROLLER_PPI mUfsHostControllerPpi = { GetUfsHcMmioBar };
|
||||
|
||||
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
|
||||
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
||||
&gEdkiiPeiUfsHostControllerPpiGuid,
|
||||
&mUfsHostControllerPpi
|
||||
};
|
||||
|
||||
/**
|
||||
Get the MMIO base address of UFS host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the UFS host controller.
|
||||
@param[out] MmioBar Pointer to the UFS host controller MMIO base address.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetUfsHcMmioBar (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
OUT UINTN *MmioBar
|
||||
)
|
||||
{
|
||||
UFS_HC_PEI_PRIVATE_DATA *Private;
|
||||
|
||||
if ((This == NULL) || (MmioBar == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = UFS_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
if (ControllerId >= Private->TotalUfsHcs) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*MmioBar = (UINTN)Private->UfsHcPciAddr[ControllerId];
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
The user code starts with this function.
|
||||
|
||||
@param FileHandle Handle of the file being invoked.
|
||||
@param PeiServices Describes the list of possible PEI Services.
|
||||
|
||||
@retval EFI_SUCCESS The driver is successfully initialized.
|
||||
@retval Others Can't initialize the driver.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeUfsHcPeim (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_BOOT_MODE BootMode;
|
||||
EFI_STATUS Status;
|
||||
UINT16 Bus;
|
||||
UINT16 Device;
|
||||
UINT16 Function;
|
||||
UINT32 Size;
|
||||
UINT8 SubClass;
|
||||
UINT8 BaseClass;
|
||||
UFS_HC_PEI_PRIVATE_DATA *Private;
|
||||
|
||||
//
|
||||
// Shadow this PEIM to run from memory
|
||||
//
|
||||
if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Status = PeiServicesGetBootMode (&BootMode);
|
||||
///
|
||||
/// We do not export this in S3 boot path, because it is only for recovery.
|
||||
///
|
||||
if (BootMode == BOOT_ON_S3_RESUME) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Private = (UFS_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (UFS_HC_PEI_PRIVATE_DATA));
|
||||
if (Private == NULL) {
|
||||
DEBUG ((EFI_D_ERROR, "Failed to allocate memory for UFS_HC_PEI_PRIVATE_DATA! \n"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Private->Signature = UFS_HC_PEI_SIGNATURE;
|
||||
Private->UfsHostControllerPpi = mUfsHostControllerPpi;
|
||||
Private->PpiList = mPpiList;
|
||||
Private->PpiList.Ppi = &Private->UfsHostControllerPpi;
|
||||
|
||||
for (Bus = 0; Bus < 256; Bus++) {
|
||||
for (Device = 0; Device < 32; Device++) {
|
||||
for (Function = 0; Function < 8; Function++) {
|
||||
SubClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0A));
|
||||
BaseClass = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, 0x0B));
|
||||
|
||||
if ((SubClass == 0x09) && (BaseClass == PCI_CLASS_MASS_STORAGE)) {
|
||||
//
|
||||
// Get the Ufs Pci host controller's MMIO region size.
|
||||
//
|
||||
PciAnd16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (UINT16)~(EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
|
||||
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), 0xFFFFFFFF);
|
||||
Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET));
|
||||
//
|
||||
// Assign resource to the Ufs Pci host controller's MMIO BAR.
|
||||
// Enable the Ufs Pci host controller by setting BME and MSE bits of PCI_CMD register.
|
||||
//
|
||||
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET), (UINT32)(PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs));
|
||||
PciOr16 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_COMMAND_OFFSET), (EFI_PCI_COMMAND_BUS_MASTER | EFI_PCI_COMMAND_MEMORY_SPACE));
|
||||
//
|
||||
// Record the allocated Mmio base address.
|
||||
//
|
||||
Private->UfsHcPciAddr[Private->TotalUfsHcs] = PcdGet32 (PcdUfsPciHostControllerMmioBase) + Size * Private->TotalUfsHcs;
|
||||
Private->TotalUfsHcs++;
|
||||
ASSERT (Private->TotalUfsHcs < MAX_UFS_HCS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Install Ufs Host Controller PPI
|
||||
///
|
||||
Status = PeiServicesInstallPpi (&Private->PpiList);
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,62 @@
|
|||
/** @file
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _UFS_PCI_HOST_CONTROLLER_PEI_H_
|
||||
#define _UFS_PCI_HOST_CONTROLLER_PEI_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Ppi/MasterBootMode.h>
|
||||
#include <Ppi/UfsHostController.h>
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/PciLib.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
|
||||
#define UFS_HC_PEI_SIGNATURE SIGNATURE_32 ('U', 'F', 'S', 'P')
|
||||
#define MAX_UFS_HCS 8
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
EDKII_UFS_HOST_CONTROLLER_PPI UfsHostControllerPpi;
|
||||
EFI_PEI_PPI_DESCRIPTOR PpiList;
|
||||
UINTN TotalUfsHcs;
|
||||
UINTN UfsHcPciAddr[MAX_UFS_HCS];
|
||||
} UFS_HC_PEI_PRIVATE_DATA;
|
||||
|
||||
#define UFS_HC_PEI_PRIVATE_DATA_FROM_THIS(a) CR (a, UFS_HC_PEI_PRIVATE_DATA, UfsHostControllerPpi, UFS_HC_PEI_SIGNATURE)
|
||||
|
||||
/**
|
||||
Get the MMIO base address of UFS host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the UFS host controller.
|
||||
@param[out] MmioBar Pointer to the UFS host controller MMIO base address.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetUfsHcMmioBar (
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
OUT UINTN *MmioBar
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
## @file
|
||||
# Component Description File For Universal Flash Storage Pci Host Controller Pei Module.
|
||||
#
|
||||
# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# 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.
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = UfsPciHcPei
|
||||
MODULE_UNI_FILE = UfsPciHcPei.uni
|
||||
FILE_GUID = 905DC1AD-C44D-4965-98AC-B6B4444BFD65
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 0.9
|
||||
|
||||
ENTRY_POINT = InitializeUfsHcPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
UfsPciHcPei.c
|
||||
UfsPciHcPei.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PciLib
|
||||
DebugLib
|
||||
PeiServicesLib
|
||||
MemoryAllocationLib
|
||||
PeimEntryPoint
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUfsPciHostControllerMmioBase ## CONSUMES
|
||||
|
||||
[Ppis]
|
||||
gEdkiiPeiUfsHostControllerPpiGuid ## PRODUCES
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
UfsPciHcPeiExtra.uni
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,995 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "UfsBlockIoPei.h"
|
||||
|
||||
//
|
||||
// Template for UFS HC Peim Private Data.
|
||||
//
|
||||
UFS_PEIM_HC_PRIVATE_DATA gUfsHcPeimTemplate = {
|
||||
UFS_PEIM_HC_SIG, // Signature
|
||||
NULL, // Controller
|
||||
NULL, // Pool
|
||||
{ // BlkIoPpi
|
||||
UfsBlockIoPeimGetDeviceNo,
|
||||
UfsBlockIoPeimGetMediaInfo,
|
||||
UfsBlockIoPeimReadBlocks
|
||||
},
|
||||
{ // BlkIoPpiList
|
||||
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
||||
&gEfiPeiVirtualBlockIoPpiGuid,
|
||||
NULL
|
||||
},
|
||||
{ // Media
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
},
|
||||
{
|
||||
UfsDevice,
|
||||
TRUE,
|
||||
0,
|
||||
0x1000
|
||||
}
|
||||
},
|
||||
0, // UfsHcBase
|
||||
0, // Capabilities
|
||||
0, // TaskTag
|
||||
0, // UtpTrlBase
|
||||
0, // Nutrs
|
||||
0, // UtpTmrlBase
|
||||
0, // Nutmrs
|
||||
{ // Luns
|
||||
{
|
||||
UFS_LUN_0, // Ufs Common Lun 0
|
||||
UFS_LUN_1, // Ufs Common Lun 1
|
||||
UFS_LUN_2, // Ufs Common Lun 2
|
||||
UFS_LUN_3, // Ufs Common Lun 3
|
||||
UFS_LUN_4, // Ufs Common Lun 4
|
||||
UFS_LUN_5, // Ufs Common Lun 5
|
||||
UFS_LUN_6, // Ufs Common Lun 6
|
||||
UFS_LUN_7, // Ufs Common Lun 7
|
||||
},
|
||||
0x0000, // By default exposing all Luns.
|
||||
0x0
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Execute Request Sense SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[out] DataBuffer A pointer to output sense data.
|
||||
@param[out] DataBufferLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimRequestSense (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
OUT VOID *DataBuffer,
|
||||
OUT UINT32 *DataBufferLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_REQUEST_SENSE;
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.InDataBuffer = DataBuffer;
|
||||
Packet.InTransferLength = *DataBufferLength;
|
||||
Packet.SenseData = NULL;
|
||||
Packet.SenseDataLength = 0;
|
||||
|
||||
Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*DataBufferLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute TEST UNITY READY SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimTestUnitReady (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_TEST_UNIT_READY;
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.DataDirection = UfsNoData;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private,(UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute INQUIRY SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[out] Inquiry A pointer to Inquiry data buffer.
|
||||
@param[out] InquiryLengths The length of output Inquiry data.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimInquiry (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
OUT VOID *Inquiry,
|
||||
OUT UINT32 *InquiryLength,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIX];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_INQUIRY;
|
||||
Cdb[4] = sizeof (EFI_SCSI_INQUIRY_DATA);
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.InDataBuffer = Inquiry;
|
||||
Packet.InTransferLength = *InquiryLength;
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*InquiryLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute READ CAPACITY(10) SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[out] DataBuffer A pointer to READ_CAPACITY data buffer.
|
||||
@param[out] DataLength The length of output READ_CAPACITY data.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimReadCapacity (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
OUT VOID *DataBuffer,
|
||||
OUT UINT32 *DataLength,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_READ_CAPACITY;
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.InDataBuffer = DataBuffer;
|
||||
Packet.InTransferLength = *DataLength;
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*DataLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute READ CAPACITY(16) SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[out] DataBuffer A pointer to READ_CAPACITY data buffer.
|
||||
@param[out] DataLength The length of output READ_CAPACITY data.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimReadCapacity16 (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
OUT VOID *DataBuffer,
|
||||
OUT UINT32 *DataLength,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_READ_CAPACITY16;
|
||||
Cdb[1] = 0x10; // Service Action should be 0x10 for UFS device.
|
||||
Cdb[13] = 0x20; // The maximum number of bytes for returned data.
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.InDataBuffer = DataBuffer;
|
||||
Packet.InTransferLength = *DataLength;
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*DataLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute READ (10) SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[in] StartLba The start LBA.
|
||||
@param[in] SectorNum The sector number to be read.
|
||||
@param[out] DataBuffer A pointer to data buffer.
|
||||
@param[out] DataLength The length of output data.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimRead10 (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
IN UINTN StartLba,
|
||||
IN UINT32 SectorNum,
|
||||
OUT VOID *DataBuffer,
|
||||
OUT UINT32 *DataLength,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_TEN];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_READ10;
|
||||
WriteUnaligned32 ((UINT32 *)&Cdb[2], SwapBytes32 ((UINT32) StartLba));
|
||||
WriteUnaligned16 ((UINT16 *)&Cdb[7], SwapBytes16 ((UINT16) SectorNum));
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.InDataBuffer = DataBuffer;
|
||||
Packet.InTransferLength = *DataLength;
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*DataLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Execute READ (16) SCSI command on a specific UFS device.
|
||||
|
||||
@param[in] Private A pointer to UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The lun on which the SCSI cmd executed.
|
||||
@param[in] StartLba The start LBA.
|
||||
@param[in] SectorNum The sector number to be read.
|
||||
@param[out] DataBuffer A pointer to data buffer.
|
||||
@param[out] DataLength The length of output data.
|
||||
@param[out] SenseData A pointer to output sense data.
|
||||
@param[out] SenseDataLength The length of output sense data.
|
||||
|
||||
@retval EFI_SUCCESS The command executed successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send SCSI Request Packet.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimRead16 (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINTN Lun,
|
||||
IN UINTN StartLba,
|
||||
IN UINT32 SectorNum,
|
||||
OUT VOID *DataBuffer,
|
||||
OUT UINT32 *DataLength,
|
||||
OUT VOID *SenseData, OPTIONAL
|
||||
OUT UINT8 *SenseDataLength
|
||||
)
|
||||
{
|
||||
UFS_SCSI_REQUEST_PACKET Packet;
|
||||
UINT8 Cdb[UFS_SCSI_OP_LENGTH_SIXTEEN];
|
||||
EFI_STATUS Status;
|
||||
|
||||
ZeroMem (&Packet, sizeof (UFS_SCSI_REQUEST_PACKET));
|
||||
ZeroMem (Cdb, sizeof (Cdb));
|
||||
|
||||
Cdb[0] = EFI_SCSI_OP_READ16;
|
||||
WriteUnaligned64 ((UINT64 *)&Cdb[2], SwapBytes64 (StartLba));
|
||||
WriteUnaligned32 ((UINT32 *)&Cdb[10], SwapBytes32 (SectorNum));
|
||||
|
||||
Packet.Timeout = UFS_TIMEOUT;
|
||||
Packet.Cdb = Cdb;
|
||||
Packet.CdbLength = sizeof (Cdb);
|
||||
Packet.InDataBuffer = DataBuffer;
|
||||
Packet.InTransferLength = *DataLength;
|
||||
Packet.DataDirection = UfsDataIn;
|
||||
Packet.SenseData = SenseData;
|
||||
Packet.SenseDataLength = *SenseDataLength;
|
||||
|
||||
Status = UfsExecScsiCmds (Private, (UINT8)Lun, &Packet);
|
||||
|
||||
if (*SenseDataLength != 0) {
|
||||
*SenseDataLength = Packet.SenseDataLength;
|
||||
}
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
*DataLength = Packet.InTransferLength;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Parsing Sense Keys from sense data.
|
||||
|
||||
@param Media The pointer of EFI_PEI_BLOCK_IO_MEDIA
|
||||
@param SenseData The pointer of EFI_SCSI_SENSE_DATA
|
||||
@param NeedRetry The pointer of action which indicates what is need to retry
|
||||
|
||||
@retval EFI_DEVICE_ERROR Indicates that error occurs
|
||||
@retval EFI_SUCCESS Successfully to complete the parsing
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimParsingSenseKeys (
|
||||
IN EFI_PEI_BLOCK_IO_MEDIA *Media,
|
||||
IN EFI_SCSI_SENSE_DATA *SenseData,
|
||||
OUT BOOLEAN *NeedRetry
|
||||
)
|
||||
{
|
||||
if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
|
||||
(SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NO_MEDIA)) {
|
||||
Media->MediaPresent = FALSE;
|
||||
*NeedRetry = FALSE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is No Media\n"));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
|
||||
(SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_CHANGE)) {
|
||||
*NeedRetry = TRUE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Is Media Change\n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((SenseData->Sense_Key == EFI_SCSI_SK_UNIT_ATTENTION) &&
|
||||
(SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_RESET)) {
|
||||
*NeedRetry = TRUE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((SenseData->Sense_Key == EFI_SCSI_SK_MEDIUM_ERROR) ||
|
||||
((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
|
||||
(SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_MEDIA_UPSIDE_DOWN))) {
|
||||
*NeedRetry = FALSE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Media Error\n"));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if (SenseData->Sense_Key == EFI_SCSI_SK_HARDWARE_ERROR) {
|
||||
*NeedRetry = FALSE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Hardware Error\n"));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if ((SenseData->Sense_Key == EFI_SCSI_SK_NOT_READY) &&
|
||||
(SenseData->Addnl_Sense_Code == EFI_SCSI_ASC_NOT_READY) &&
|
||||
(SenseData->Addnl_Sense_Code_Qualifier == EFI_SCSI_ASCQ_IN_PROGRESS)) {
|
||||
*NeedRetry = TRUE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Was Reset Before\n"));
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
*NeedRetry = FALSE;
|
||||
DEBUG ((EFI_D_VERBOSE, "UfsBlockIoPei: Sense Key = 0x%x ASC = 0x%x!\n", SenseData->Sense_Key, SenseData->Addnl_Sense_Code));
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
Gets the count of block I/O devices that one specific block driver detects.
|
||||
|
||||
This function is used for getting the count of block I/O devices that one
|
||||
specific block driver detects. To the PEI ATAPI driver, it returns the number
|
||||
of all the detected ATAPI devices it detects during the enumeration process.
|
||||
To the PEI legacy floppy driver, it returns the number of all the legacy
|
||||
devices it finds during its enumeration process. If no device is detected,
|
||||
then the function will return zero.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available
|
||||
to every PEIM.
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimGetDeviceNo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
)
|
||||
{
|
||||
//
|
||||
// For Ufs device, it has up to 8 normal Luns plus some well-known Luns.
|
||||
// At PEI phase, we will only expose normal Luns to user.
|
||||
// For those disabled Lun, when user try to access it, the operation would fail.
|
||||
//
|
||||
*NumberBlockDevices = UFS_PEIM_MAX_LUNS;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Gets a block device's media information.
|
||||
|
||||
This function will provide the caller with the specified block device's media
|
||||
information. If the media changes, calling this function will update the media
|
||||
information accordingly.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available to every
|
||||
PEIM
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
|
||||
@param[in] DeviceIndex Specifies the block device to which the function wants
|
||||
to talk. Because the driver that implements Block I/O
|
||||
PPIs will manage multiple block devices, the PPIs that
|
||||
want to talk to a single device must specify the
|
||||
device index that was assigned during the enumeration
|
||||
process. This index is a number from one to
|
||||
NumberBlockDevices.
|
||||
@param[out] MediaInfo The media information of the specified block media.
|
||||
The caller is responsible for the ownership of this
|
||||
data structure.
|
||||
|
||||
@par Note:
|
||||
The MediaInfo structure describes an enumeration of possible block device
|
||||
types. This enumeration exists because no device paths are actually passed
|
||||
across interfaces that describe the type or class of hardware that is publishing
|
||||
the block I/O interface. This enumeration will allow for policy decisions
|
||||
in the Recovery PEIM, such as "Try to recover from legacy floppy first,
|
||||
LS-120 second, CD-ROM third." If there are multiple partitions abstracted
|
||||
by a given device type, they should be reported in ascending order; this
|
||||
order also applies to nested partitions, such as legacy MBR, where the
|
||||
outermost partitions would have precedence in the reporting order. The
|
||||
same logic applies to systems such as IDE that have precedence relationships
|
||||
like "Master/Slave" or "Primary/Secondary". The master device should be
|
||||
reported first, the slave second.
|
||||
|
||||
@retval EFI_SUCCESS Media information about the specified block device
|
||||
was obtained successfully.
|
||||
@retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
|
||||
error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimGetMediaInfo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UFS_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EFI_SCSI_SENSE_DATA SenseData;
|
||||
UINT8 SenseDataLength;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA Capacity;
|
||||
EFI_SCSI_DISK_CAPACITY_DATA16 Capacity16;
|
||||
UINTN DataLength;
|
||||
BOOLEAN NeedRetry;
|
||||
|
||||
Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
NeedRetry = TRUE;
|
||||
|
||||
if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
ZeroMem (&SenseData, sizeof (SenseData));
|
||||
ZeroMem (&Capacity, sizeof (Capacity));
|
||||
ZeroMem (&Capacity16, sizeof (Capacity16));
|
||||
SenseDataLength = sizeof (SenseData);
|
||||
//
|
||||
// First test unit ready
|
||||
//
|
||||
do {
|
||||
Status = UfsPeimTestUnitReady (
|
||||
Private,
|
||||
DeviceIndex,
|
||||
&SenseData,
|
||||
&SenseDataLength
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SenseDataLength == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]), &SenseData, &NeedRetry);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
} while (NeedRetry);
|
||||
|
||||
DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA);
|
||||
SenseDataLength = 0;
|
||||
Status = UfsPeimReadCapacity (Private, DeviceIndex, &Capacity, (UINT32 *)&DataLength, NULL, &SenseDataLength);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
if ((Capacity.LastLba3 == 0xff) && (Capacity.LastLba2 == 0xff) &&
|
||||
(Capacity.LastLba1 == 0xff) && (Capacity.LastLba0 == 0xff)) {
|
||||
DataLength = sizeof (EFI_SCSI_DISK_CAPACITY_DATA16);
|
||||
SenseDataLength = 0;
|
||||
Status = UfsPeimReadCapacity16 (Private, DeviceIndex, &Capacity16, (UINT32 *)&DataLength, NULL, &SenseDataLength);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
MediaInfo->LastBlock = (Capacity16.LastLba3 << 24) | (Capacity16.LastLba2 << 16) | (Capacity16.LastLba1 << 8) | Capacity16.LastLba0;
|
||||
MediaInfo->LastBlock |= ((UINT64)Capacity16.LastLba7 << 56) | ((UINT64)Capacity16.LastLba6 << 48) | ((UINT64)Capacity16.LastLba5 << 40) | ((UINT64)Capacity16.LastLba4 << 32);
|
||||
MediaInfo->BlockSize = (Capacity16.BlockSize3 << 24) | (Capacity16.BlockSize2 << 16) | (Capacity16.BlockSize1 << 8) | Capacity16.BlockSize0;
|
||||
} else {
|
||||
MediaInfo->LastBlock = (Capacity.LastLba3 << 24) | (Capacity.LastLba2 << 16) | (Capacity.LastLba1 << 8) | Capacity.LastLba0;
|
||||
MediaInfo->BlockSize = (Capacity.BlockSize3 << 24) | (Capacity.BlockSize2 << 16) | (Capacity.BlockSize1 << 8) | Capacity.BlockSize0;
|
||||
}
|
||||
|
||||
MediaInfo->DeviceType = UfsDevice;
|
||||
MediaInfo->MediaPresent = TRUE;
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reads the requested number of blocks from the specified block device.
|
||||
|
||||
The function reads the requested number of blocks from the device. All the
|
||||
blocks are read, or an error is returned. If there is no media in the device,
|
||||
the function returns EFI_NO_MEDIA.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available to
|
||||
every PEIM.
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
|
||||
@param[in] DeviceIndex Specifies the block device to which the function wants
|
||||
to talk. Because the driver that implements Block I/O
|
||||
PPIs will manage multiple block devices, PPIs that
|
||||
want to talk to a single device must specify the device
|
||||
index that was assigned during the enumeration process.
|
||||
This index is a number from one to NumberBlockDevices.
|
||||
@param[in] StartLBA The starting logical block address (LBA) to read from
|
||||
on the device
|
||||
@param[in] BufferSize The size of the Buffer in bytes. This number must be
|
||||
a multiple of the intrinsic block size of the device.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data.
|
||||
The caller is responsible for the ownership of the
|
||||
buffer.
|
||||
|
||||
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the read operation.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
|
||||
valid, or the buffer is not properly aligned.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
|
||||
the intrinsic block size of the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimReadBlocks (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
IN EFI_PEI_LBA StartLBA,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UINTN BlockSize;
|
||||
UINTN NumberOfBlocks;
|
||||
UFS_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EFI_SCSI_SENSE_DATA SenseData;
|
||||
UINT8 SenseDataLength;
|
||||
BOOLEAN NeedRetry;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
NeedRetry = TRUE;
|
||||
Private = GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
ZeroMem (&SenseData, sizeof (SenseData));
|
||||
SenseDataLength = sizeof (SenseData);
|
||||
|
||||
//
|
||||
// Check parameters
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BufferSize == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (DeviceIndex >= UFS_PEIM_MAX_LUNS) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Private->Luns.BitMask & (BIT0 << DeviceIndex)) == 0) {
|
||||
return EFI_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
BlockSize = Private->Media[DeviceIndex].BlockSize;
|
||||
|
||||
if (BufferSize % BlockSize != 0) {
|
||||
Status = EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (StartLBA > Private->Media[DeviceIndex].LastBlock) {
|
||||
Status = EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NumberOfBlocks = BufferSize / BlockSize;
|
||||
|
||||
do {
|
||||
Status = UfsPeimTestUnitReady (
|
||||
Private,
|
||||
DeviceIndex,
|
||||
&SenseData,
|
||||
&SenseDataLength
|
||||
);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (SenseDataLength == 0) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = UfsPeimParsingSenseKeys (&(Private->Media[DeviceIndex]), &SenseData, &NeedRetry);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
} while (NeedRetry);
|
||||
|
||||
SenseDataLength = 0;
|
||||
if (Private->Media[DeviceIndex].LastBlock != ~((UINTN)0)) {
|
||||
Status = UfsPeimRead10 (
|
||||
Private,
|
||||
DeviceIndex,
|
||||
(UINT32)StartLBA,
|
||||
(UINT32)NumberOfBlocks,
|
||||
Buffer,
|
||||
(UINT32 *)&BufferSize,
|
||||
NULL,
|
||||
&SenseDataLength
|
||||
);
|
||||
} else {
|
||||
Status = UfsPeimRead16 (
|
||||
Private,
|
||||
DeviceIndex,
|
||||
(UINT32)StartLBA,
|
||||
(UINT32)NumberOfBlocks,
|
||||
Buffer,
|
||||
(UINT32 *)&BufferSize,
|
||||
NULL,
|
||||
&SenseDataLength
|
||||
);
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
The user code starts with this function.
|
||||
|
||||
@param FileHandle Handle of the file being invoked.
|
||||
@param PeiServices Describes the list of possible PEI Services.
|
||||
|
||||
@retval EFI_SUCCESS The driver is successfully initialized.
|
||||
@retval Others Can't initialize the driver.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeUfsBlockIoPeim (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
UFS_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EDKII_UFS_HOST_CONTROLLER_PPI *UfsHcPpi;
|
||||
UINT32 Index;
|
||||
UFS_CONFIG_DESC Config;
|
||||
UINTN MmioBase;
|
||||
UINT8 Controller;
|
||||
|
||||
//
|
||||
// Shadow this PEIM to run from memory
|
||||
//
|
||||
if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// locate ufs host controller PPI
|
||||
//
|
||||
Status = PeiServicesLocatePpi (
|
||||
&gEdkiiPeiUfsHostControllerPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **) &UfsHcPpi
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Controller = 0;
|
||||
MmioBase = 0;
|
||||
while (TRUE) {
|
||||
Status = UfsHcPpi->GetUfsHcMmioBar (UfsHcPpi, Controller, &MmioBase);
|
||||
//
|
||||
// When status is error, meant no controller is found
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
Private = AllocateCopyPool (sizeof (UFS_PEIM_HC_PRIVATE_DATA), &gUfsHcPeimTemplate);
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
Private->BlkIoPpiList.Ppi = &Private->BlkIoPpi;
|
||||
Private->UfsHcBase = MmioBase;
|
||||
|
||||
//
|
||||
// Initialize the memory pool which will be used in all transactions.
|
||||
//
|
||||
Status = UfsPeimInitMemPool (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
//
|
||||
// Initialize UFS Host Controller H/W.
|
||||
//
|
||||
Status = UfsControllerInit (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "UfsDevicePei: Host Controller Initialization Error, Status = %r\n", Status));
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// UFS 2.0 spec Section 13.1.3.3:
|
||||
// At the end of the UFS Interconnect Layer initialization on both host and device side,
|
||||
// the host shall send a NOP OUT UPIU to verify that the device UTP Layer is ready.
|
||||
//
|
||||
Status = UfsExecNopCmds (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Ufs Sending NOP IN command Error, Status = %r\n", Status));
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// The host enables the device initialization completion by setting fDeviceInit flag.
|
||||
//
|
||||
Status = UfsSetFlag (Private, UfsFlagDevInit);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Ufs Set fDeviceInit Flag Error, Status = %r\n", Status));
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
//
|
||||
// Get Ufs Device's Lun Info by reading Configuration Descriptor.
|
||||
//
|
||||
Status = UfsRwDeviceDesc (Private, TRUE, UfsConfigDesc, 0, 0, &Config, sizeof (UFS_CONFIG_DESC));
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "Ufs Get Configuration Descriptor Error, Status = %r\n", Status));
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < UFS_PEIM_MAX_LUNS; Index++) {
|
||||
if (Config.UnitDescConfParams[Index].LunEn != 0) {
|
||||
Private->Luns.BitMask |= (BIT0 << Index);
|
||||
DEBUG ((EFI_D_INFO, "Ufs %d Lun %d is enabled\n", Controller, Index));
|
||||
}
|
||||
}
|
||||
|
||||
Status = PeiServicesInstallPpi (&Private->BlkIoPpiList);
|
||||
Controller++;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,434 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _UFS_BLOCK_IO_PEI_H_
|
||||
#define _UFS_BLOCK_IO_PEI_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Ppi/UfsHostController.h>
|
||||
#include <Ppi/BlockIo.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
#include <Library/PeiServicesLib.h>
|
||||
|
||||
#include <IndustryStandard/Scsi.h>
|
||||
|
||||
#include "UfsHci.h"
|
||||
#include "UfsHcMem.h"
|
||||
|
||||
#define UFS_PEIM_HC_SIG SIGNATURE_32 ('U', 'F', 'S', 'H')
|
||||
|
||||
#define UFS_PEIM_MAX_LUNS 8
|
||||
|
||||
typedef struct {
|
||||
UINT8 Lun[UFS_PEIM_MAX_LUNS];
|
||||
UINT16 BitMask:12; // Bit 0~7 is for common luns. Bit 8~11 is reserved for those well known luns
|
||||
UINT16 Rsvd:4;
|
||||
} UFS_PEIM_EXPOSED_LUNS;
|
||||
|
||||
typedef struct {
|
||||
///
|
||||
/// The timeout, in 100 ns units, to use for the execution of this SCSI
|
||||
/// Request Packet. A Timeout value of 0 means that this function
|
||||
/// will wait indefinitely for the SCSI Request Packet to execute. If
|
||||
/// Timeout is greater than zero, then this function will return
|
||||
/// EFI_TIMEOUT if the time required to execute the SCSI
|
||||
/// Request Packet is greater than Timeout.
|
||||
///
|
||||
UINT64 Timeout;
|
||||
///
|
||||
/// A pointer to the data buffer to transfer between the SCSI
|
||||
/// controller and the SCSI device for read and bidirectional commands.
|
||||
///
|
||||
VOID *InDataBuffer;
|
||||
///
|
||||
/// A pointer to the data buffer to transfer between the SCSI
|
||||
/// controller and the SCSI device for write or bidirectional commands.
|
||||
///
|
||||
VOID *OutDataBuffer;
|
||||
///
|
||||
/// A pointer to the sense data that was generated by the execution of
|
||||
/// the SCSI Request Packet.
|
||||
///
|
||||
VOID *SenseData;
|
||||
///
|
||||
/// A pointer to buffer that contains the Command Data Block to
|
||||
/// send to the SCSI device specified by Target and Lun.
|
||||
///
|
||||
VOID *Cdb;
|
||||
///
|
||||
/// On Input, the size, in bytes, of InDataBuffer. On output, the
|
||||
/// number of bytes transferred between the SCSI controller and the SCSI device.
|
||||
///
|
||||
UINT32 InTransferLength;
|
||||
///
|
||||
/// On Input, the size, in bytes of OutDataBuffer. On Output, the
|
||||
/// Number of bytes transferred between SCSI Controller and the SCSI device.
|
||||
///
|
||||
UINT32 OutTransferLength;
|
||||
///
|
||||
/// The length, in bytes, of the buffer Cdb. The standard values are 6,
|
||||
/// 10, 12, and 16, but other values are possible if a variable length CDB is used.
|
||||
///
|
||||
UINT8 CdbLength;
|
||||
///
|
||||
/// The direction of the data transfer. 0 for reads, 1 for writes. A
|
||||
/// value of 2 is Reserved for Bi-Directional SCSI commands.
|
||||
///
|
||||
UINT8 DataDirection;
|
||||
///
|
||||
/// On input, the length in bytes of the SenseData buffer. On
|
||||
/// output, the number of bytes written to the SenseData buffer.
|
||||
///
|
||||
UINT8 SenseDataLength;
|
||||
} UFS_SCSI_REQUEST_PACKET;
|
||||
|
||||
typedef struct _UFS_PEIM_HC_PRIVATE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Controller;
|
||||
|
||||
UFS_PEIM_MEM_POOL *Pool;
|
||||
|
||||
EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;
|
||||
EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;
|
||||
EFI_PEI_BLOCK_IO_MEDIA Media[UFS_PEIM_MAX_LUNS];
|
||||
|
||||
UINTN UfsHcBase;
|
||||
UINT32 Capabilities;
|
||||
|
||||
UINT8 TaskTag;
|
||||
|
||||
VOID *UtpTrlBase;
|
||||
UINT8 Nutrs;
|
||||
VOID *UtpTmrlBase;
|
||||
UINT8 Nutmrs;
|
||||
|
||||
UFS_PEIM_EXPOSED_LUNS Luns;
|
||||
} UFS_PEIM_HC_PRIVATE_DATA;
|
||||
|
||||
#define UFS_TIMEOUT MultU64x32((UINT64)(3), 10000000)
|
||||
|
||||
#define ROUNDUP8(x) (((x) % 8 == 0) ? (x) : ((x) / 8 + 1) * 8)
|
||||
|
||||
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
|
||||
|
||||
#define GET_UFS_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, UFS_PEIM_HC_PRIVATE_DATA, BlkIoPpi, UFS_PEIM_HC_SIG)
|
||||
|
||||
#define UFS_SCSI_OP_LENGTH_SIX 0x6
|
||||
#define UFS_SCSI_OP_LENGTH_TEN 0xa
|
||||
#define UFS_SCSI_OP_LENGTH_SIXTEEN 0x10
|
||||
|
||||
typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {
|
||||
UINT64 Timeout;
|
||||
VOID *InDataBuffer;
|
||||
VOID *OutDataBuffer;
|
||||
UINT8 Opcode;
|
||||
UINT8 DescId;
|
||||
UINT8 Index;
|
||||
UINT8 Selector;
|
||||
UINT32 InTransferLength;
|
||||
UINT32 OutTransferLength;
|
||||
UINT8 DataDirection;
|
||||
UINT8 Ocs;
|
||||
} UFS_DEVICE_MANAGEMENT_REQUEST_PACKET;
|
||||
|
||||
/**
|
||||
Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The LUN of the UFS device to send the SCSI Request Packet.
|
||||
@param[in, out] Packet A pointer to the SCSI Request Packet to send to a specified Lun of the
|
||||
UFS device.
|
||||
|
||||
@retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
|
||||
commands, InTransferLength bytes were transferred from
|
||||
InDataBuffer. For write and bi-directional commands,
|
||||
OutTransferLength bytes were transferred by
|
||||
OutDataBuffer.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
|
||||
Packet.
|
||||
@retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsExecScsiCmds (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 Lun,
|
||||
IN OUT UFS_SCSI_REQUEST_PACKET *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The Ufs Host Controller is initialized successfully.
|
||||
@retval Others A device error occurred while initializing the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsControllerInit (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Stop the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The Ufs Host Controller is stopped successfully.
|
||||
@retval Others A device error occurred while stopping the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsControllerStop (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Set specified flag to 1 on a UFS device.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] FlagId The ID of flag to be set.
|
||||
|
||||
@retval EFI_SUCCESS The flag was set successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to set the flag.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of setting the flag.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsSetFlag (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 FlagId
|
||||
);
|
||||
|
||||
/**
|
||||
Read or write specified device descriptor of a UFS device.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
@param[in] Read The boolean variable to show r/w direction.
|
||||
@param[in] DescId The ID of device descriptor.
|
||||
@param[in] Index The Index of device descriptor.
|
||||
@param[in] Selector The Selector of device descriptor.
|
||||
@param[in, out] Descriptor The buffer of device descriptor to be read or written.
|
||||
@param[in] DescSize The size of device descriptor buffer.
|
||||
|
||||
@retval EFI_SUCCESS The device descriptor was read/written successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsRwDeviceDesc (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private,
|
||||
IN BOOLEAN Read,
|
||||
IN UINT8 DescId,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Selector,
|
||||
IN OUT VOID *Descriptor,
|
||||
IN UINT32 DescSize
|
||||
);
|
||||
|
||||
/**
|
||||
Sends NOP IN cmd to a UFS device for initialization process request.
|
||||
For more details, please refer to UFS 2.0 spec Figure 13.3.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PEIM_HC_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The NOP IN command was sent by the host. The NOP OUT response was
|
||||
received successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to execute NOP IN command.
|
||||
@retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the NOP IN command to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsExecNopCmds (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Gets the count of block I/O devices that one specific block driver detects.
|
||||
|
||||
This function is used for getting the count of block I/O devices that one
|
||||
specific block driver detects. To the PEI ATAPI driver, it returns the number
|
||||
of all the detected ATAPI devices it detects during the enumeration process.
|
||||
To the PEI legacy floppy driver, it returns the number of all the legacy
|
||||
devices it finds during its enumeration process. If no device is detected,
|
||||
then the function will return zero.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available
|
||||
to every PEIM.
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimGetDeviceNo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
);
|
||||
|
||||
/**
|
||||
Gets a block device's media information.
|
||||
|
||||
This function will provide the caller with the specified block device's media
|
||||
information. If the media changes, calling this function will update the media
|
||||
information accordingly.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available to every
|
||||
PEIM
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
|
||||
@param[in] DeviceIndex Specifies the block device to which the function wants
|
||||
to talk. Because the driver that implements Block I/O
|
||||
PPIs will manage multiple block devices, the PPIs that
|
||||
want to talk to a single device must specify the
|
||||
device index that was assigned during the enumeration
|
||||
process. This index is a number from one to
|
||||
NumberBlockDevices.
|
||||
@param[out] MediaInfo The media information of the specified block media.
|
||||
The caller is responsible for the ownership of this
|
||||
data structure.
|
||||
|
||||
@par Note:
|
||||
The MediaInfo structure describes an enumeration of possible block device
|
||||
types. This enumeration exists because no device paths are actually passed
|
||||
across interfaces that describe the type or class of hardware that is publishing
|
||||
the block I/O interface. This enumeration will allow for policy decisions
|
||||
in the Recovery PEIM, such as "Try to recover from legacy floppy first,
|
||||
LS-120 second, CD-ROM third." If there are multiple partitions abstracted
|
||||
by a given device type, they should be reported in ascending order; this
|
||||
order also applies to nested partitions, such as legacy MBR, where the
|
||||
outermost partitions would have precedence in the reporting order. The
|
||||
same logic applies to systems such as IDE that have precedence relationships
|
||||
like "Master/Slave" or "Primary/Secondary". The master device should be
|
||||
reported first, the slave second.
|
||||
|
||||
@retval EFI_SUCCESS Media information about the specified block device
|
||||
was obtained successfully.
|
||||
@retval EFI_DEVICE_ERROR Cannot get the media information due to a hardware
|
||||
error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimGetMediaInfo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
|
||||
);
|
||||
|
||||
/**
|
||||
Reads the requested number of blocks from the specified block device.
|
||||
|
||||
The function reads the requested number of blocks from the device. All the
|
||||
blocks are read, or an error is returned. If there is no media in the device,
|
||||
the function returns EFI_NO_MEDIA.
|
||||
|
||||
@param[in] PeiServices General-purpose services that are available to
|
||||
every PEIM.
|
||||
@param[in] This Indicates the EFI_PEI_RECOVERY_BLOCK_IO_PPI instance.
|
||||
@param[in] DeviceIndex Specifies the block device to which the function wants
|
||||
to talk. Because the driver that implements Block I/O
|
||||
PPIs will manage multiple block devices, PPIs that
|
||||
want to talk to a single device must specify the device
|
||||
index that was assigned during the enumeration process.
|
||||
This index is a number from one to NumberBlockDevices.
|
||||
@param[in] StartLBA The starting logical block address (LBA) to read from
|
||||
on the device
|
||||
@param[in] BufferSize The size of the Buffer in bytes. This number must be
|
||||
a multiple of the intrinsic block size of the device.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data.
|
||||
The caller is responsible for the ownership of the
|
||||
buffer.
|
||||
|
||||
@retval EFI_SUCCESS The data was read correctly from the device.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while attempting
|
||||
to perform the read operation.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not
|
||||
valid, or the buffer is not properly aligned.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of
|
||||
the intrinsic block size of the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsBlockIoPeimReadBlocks (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
IN EFI_PEI_LBA StartLBA,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the memory management pool for the host controller.
|
||||
|
||||
@param Private The Ufs Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimInitMemPool (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate some memory from the host controller's memory pool
|
||||
which can be used to communicate with host controller.
|
||||
|
||||
@param Pool The host controller's memory pool.
|
||||
@param Size Size of the memory to allocate.
|
||||
|
||||
@return The allocated memory or NULL.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
UfsPeimAllocateMem (
|
||||
IN UFS_PEIM_MEM_POOL *Pool,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
/**
|
||||
Free the allocated memory back to the memory pool.
|
||||
|
||||
@param Pool The memory pool of the host controller.
|
||||
@param Mem The memory to free.
|
||||
@param Size The size of the memory to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UfsPeimFreeMem (
|
||||
IN UFS_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,61 @@
|
|||
## @file
|
||||
# Description file for the Universal Flash Storage (UFS) Peim driver.
|
||||
#
|
||||
# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = UfsBlockIoPei
|
||||
MODULE_UNI_FILE = UfsBlockIoPei.uni
|
||||
FILE_GUID = BE189D38-C963-41CF-B695-D90E9E545A13
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 0.9
|
||||
|
||||
ENTRY_POINT = InitializeUfsBlockIoPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
UfsBlockIoPei.c
|
||||
UfsBlockIoPei.h
|
||||
UfsHci.c
|
||||
UfsHci.h
|
||||
UfsHcMem.c
|
||||
UfsHcMem.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
IoLib
|
||||
TimerLib
|
||||
BaseMemoryLib
|
||||
PeimEntryPoint
|
||||
PeiServicesLib
|
||||
DebugLib
|
||||
|
||||
[Ppis]
|
||||
gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES
|
||||
gEdkiiPeiUfsHostControllerPpiGuid ## CONSUMES
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiUfsHostControllerPpiGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
UfsBlockIoPeiExtra.uni
|
||||
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,455 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#include "UfsBlockIoPei.h"
|
||||
|
||||
/**
|
||||
Allocate a block of memory to be used by the buffer pool.
|
||||
|
||||
@param Pages How many pages to allocate.
|
||||
|
||||
@return The allocated memory block or NULL if failed.
|
||||
|
||||
**/
|
||||
UFS_PEIM_MEM_BLOCK *
|
||||
UfsPeimAllocMemBlock (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_BLOCK *Block;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
|
||||
TempPtr = NULL;
|
||||
Block = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof(UFS_PEIM_MEM_BLOCK), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof(UFS_PEIM_MEM_BLOCK));
|
||||
|
||||
//
|
||||
// each bit in the bit array represents UFS_PEIM_MEM_UNIT
|
||||
// bytes of memory in the memory block.
|
||||
//
|
||||
ASSERT (UFS_PEIM_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
|
||||
|
||||
Block = (UFS_PEIM_MEM_BLOCK*)(UINTN)TempPtr;
|
||||
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
|
||||
Block->BitsLen = Block->BufLen / (UFS_PEIM_MEM_UNIT * 8);
|
||||
|
||||
Status = PeiServicesAllocatePool (Block->BitsLen, &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, Block->BitsLen);
|
||||
|
||||
Block->Bits = (UINT8*)(UINTN)TempPtr;
|
||||
|
||||
Status = PeiServicesAllocatePages (
|
||||
EfiBootServicesCode,
|
||||
Pages,
|
||||
&Address
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)Address, EFI_PAGES_TO_SIZE (Pages));
|
||||
|
||||
Block->Buf = (UINT8*)((UINTN)Address);
|
||||
Block->Next = NULL;
|
||||
|
||||
return Block;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the memory block from the memory pool.
|
||||
|
||||
@param Pool The memory pool to free the block from.
|
||||
@param Block The memory block to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UfsPeimFreeMemBlock (
|
||||
IN UFS_PEIM_MEM_POOL *Pool,
|
||||
IN UFS_PEIM_MEM_BLOCK *Block
|
||||
)
|
||||
{
|
||||
ASSERT ((Pool != NULL) && (Block != NULL));
|
||||
}
|
||||
|
||||
/**
|
||||
Alloc some memory from the block.
|
||||
|
||||
@param Block The memory block to allocate memory from.
|
||||
@param Units Number of memory units to allocate.
|
||||
|
||||
@return The pointer to the allocated memory. If couldn't allocate the needed memory,
|
||||
the return value is NULL.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
UfsPeimAllocMemFromBlock (
|
||||
IN UFS_PEIM_MEM_BLOCK *Block,
|
||||
IN UINTN Units
|
||||
)
|
||||
{
|
||||
UINTN Byte;
|
||||
UINT8 Bit;
|
||||
UINTN StartByte;
|
||||
UINT8 StartBit;
|
||||
UINTN Available;
|
||||
UINTN Count;
|
||||
|
||||
ASSERT ((Block != 0) && (Units != 0));
|
||||
|
||||
StartByte = 0;
|
||||
StartBit = 0;
|
||||
Available = 0;
|
||||
|
||||
for (Byte = 0, Bit = 0; Byte < Block->BitsLen;) {
|
||||
//
|
||||
// If current bit is zero, the corresponding memory unit is
|
||||
// available, otherwise we need to restart our searching.
|
||||
// Available counts the consective number of zero bit.
|
||||
//
|
||||
if (!UFS_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit)) {
|
||||
Available++;
|
||||
|
||||
if (Available >= Units) {
|
||||
break;
|
||||
}
|
||||
|
||||
UFS_PEIM_NEXT_BIT (Byte, Bit);
|
||||
|
||||
} else {
|
||||
UFS_PEIM_NEXT_BIT (Byte, Bit);
|
||||
|
||||
Available = 0;
|
||||
StartByte = Byte;
|
||||
StartBit = Bit;
|
||||
}
|
||||
}
|
||||
|
||||
if (Available < Units) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Mark the memory as allocated
|
||||
//
|
||||
Byte = StartByte;
|
||||
Bit = StartBit;
|
||||
|
||||
for (Count = 0; Count < Units; Count++) {
|
||||
ASSERT (!UFS_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) UFS_PEIM_MEM_BIT (Bit));
|
||||
UFS_PEIM_NEXT_BIT (Byte, Bit);
|
||||
}
|
||||
|
||||
return Block->Buf + (StartByte * 8 + StartBit) * UFS_PEIM_MEM_UNIT;
|
||||
}
|
||||
|
||||
/**
|
||||
Insert the memory block to the pool's list of the blocks.
|
||||
|
||||
@param Head The head of the memory pool's block list.
|
||||
@param Block The memory block to insert.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UfsPeimInsertMemBlockToPool (
|
||||
IN UFS_PEIM_MEM_BLOCK *Head,
|
||||
IN UFS_PEIM_MEM_BLOCK *Block
|
||||
)
|
||||
{
|
||||
ASSERT ((Head != NULL) && (Block != NULL));
|
||||
Block->Next = Head->Next;
|
||||
Head->Next = Block;
|
||||
}
|
||||
|
||||
/**
|
||||
Is the memory block empty?
|
||||
|
||||
@param Block The memory block to check.
|
||||
|
||||
@retval TRUE The memory block is empty.
|
||||
@retval FALSE The memory block isn't empty.
|
||||
|
||||
**/
|
||||
BOOLEAN
|
||||
UfsPeimIsMemBlockEmpty (
|
||||
IN UFS_PEIM_MEM_BLOCK *Block
|
||||
)
|
||||
{
|
||||
UINTN Index;
|
||||
|
||||
|
||||
for (Index = 0; Index < Block->BitsLen; Index++) {
|
||||
if (Block->Bits[Index] != 0) {
|
||||
return FALSE;
|
||||
}
|
||||
}
|
||||
|
||||
return TRUE;
|
||||
}
|
||||
|
||||
/**
|
||||
Unlink the memory block from the pool's list.
|
||||
|
||||
@param Head The block list head of the memory's pool.
|
||||
@param BlockToUnlink The memory block to unlink.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UfsPeimUnlinkMemBlock (
|
||||
IN UFS_PEIM_MEM_BLOCK *Head,
|
||||
IN UFS_PEIM_MEM_BLOCK *BlockToUnlink
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_BLOCK *Block;
|
||||
|
||||
ASSERT ((Head != NULL) && (BlockToUnlink != NULL));
|
||||
|
||||
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||
if (Block->Next == BlockToUnlink) {
|
||||
Block->Next = BlockToUnlink->Next;
|
||||
BlockToUnlink->Next = NULL;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
Initialize the memory management pool for the host controller.
|
||||
|
||||
@param Private The Ufs Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimInitMemPool (
|
||||
IN UFS_PEIM_HC_PRIVATE_DATA *Private
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_POOL *Pool;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
|
||||
TempPtr = NULL;
|
||||
Pool = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof (UFS_PEIM_MEM_POOL), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof (UFS_PEIM_MEM_POOL));
|
||||
|
||||
Pool = (UFS_PEIM_MEM_POOL *)((UINTN)TempPtr);
|
||||
|
||||
Pool->Head = UfsPeimAllocMemBlock (UFS_PEIM_MEM_DEFAULT_PAGES);
|
||||
|
||||
if (Pool->Head == NULL) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Private->Pool = Pool;
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Release the memory management pool.
|
||||
|
||||
@param Pool The memory pool to free.
|
||||
|
||||
@retval EFI_DEVICE_ERROR Fail to free the memory pool.
|
||||
@retval EFI_SUCCESS The memory pool is freed.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsPeimFreeMemPool (
|
||||
IN UFS_PEIM_MEM_POOL *Pool
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_BLOCK *Block;
|
||||
|
||||
ASSERT (Pool->Head != NULL);
|
||||
|
||||
//
|
||||
// Unlink all the memory blocks from the pool, then free them.
|
||||
// UfsPeimUnlinkMemBlock can't be used to unlink and free the
|
||||
// first block.
|
||||
//
|
||||
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
|
||||
UfsPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
UfsPeimFreeMemBlock (Pool, Pool->Head);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Allocate some memory from the host controller's memory pool
|
||||
which can be used to communicate with host controller.
|
||||
|
||||
@param Pool The host controller's memory pool.
|
||||
@param Size Size of the memory to allocate.
|
||||
|
||||
@return The allocated memory or NULL.
|
||||
|
||||
**/
|
||||
VOID *
|
||||
UfsPeimAllocateMem (
|
||||
IN UFS_PEIM_MEM_POOL *Pool,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_BLOCK *Head;
|
||||
UFS_PEIM_MEM_BLOCK *Block;
|
||||
UFS_PEIM_MEM_BLOCK *NewBlock;
|
||||
VOID *Mem;
|
||||
UINTN AllocSize;
|
||||
UINTN Pages;
|
||||
|
||||
Mem = NULL;
|
||||
AllocSize = UFS_PEIM_MEM_ROUND (Size);
|
||||
Head = Pool->Head;
|
||||
ASSERT (Head != NULL);
|
||||
|
||||
//
|
||||
// First check whether current memory blocks can satisfy the allocation.
|
||||
//
|
||||
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||
Mem = UfsPeimAllocMemFromBlock (Block, AllocSize / UFS_PEIM_MEM_UNIT);
|
||||
|
||||
if (Mem != NULL) {
|
||||
ZeroMem (Mem, Size);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (Mem != NULL) {
|
||||
return Mem;
|
||||
}
|
||||
|
||||
//
|
||||
// Create a new memory block if there is not enough memory
|
||||
// in the pool. If the allocation size is larger than the
|
||||
// default page number, just allocate a large enough memory
|
||||
// block. Otherwise allocate default pages.
|
||||
//
|
||||
if (AllocSize > EFI_PAGES_TO_SIZE (UFS_PEIM_MEM_DEFAULT_PAGES)) {
|
||||
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
|
||||
} else {
|
||||
Pages = UFS_PEIM_MEM_DEFAULT_PAGES;
|
||||
}
|
||||
|
||||
NewBlock = UfsPeimAllocMemBlock (Pages);
|
||||
if (NewBlock == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the new memory block to the pool, then allocate memory from it
|
||||
//
|
||||
UfsPeimInsertMemBlockToPool (Head, NewBlock);
|
||||
Mem = UfsPeimAllocMemFromBlock (NewBlock, AllocSize / UFS_PEIM_MEM_UNIT);
|
||||
|
||||
if (Mem != NULL) {
|
||||
ZeroMem (Mem, Size);
|
||||
}
|
||||
|
||||
return Mem;
|
||||
}
|
||||
|
||||
/**
|
||||
Free the allocated memory back to the memory pool.
|
||||
|
||||
@param Pool The memory pool of the host controller.
|
||||
@param Mem The memory to free.
|
||||
@param Size The size of the memory to free.
|
||||
|
||||
**/
|
||||
VOID
|
||||
UfsPeimFreeMem (
|
||||
IN UFS_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
UFS_PEIM_MEM_BLOCK *Head;
|
||||
UFS_PEIM_MEM_BLOCK *Block;
|
||||
UINT8 *ToFree;
|
||||
UINTN AllocSize;
|
||||
UINTN Byte;
|
||||
UINTN Bit;
|
||||
UINTN Count;
|
||||
|
||||
Head = Pool->Head;
|
||||
AllocSize = UFS_PEIM_MEM_ROUND (Size);
|
||||
ToFree = (UINT8 *) Mem;
|
||||
|
||||
for (Block = Head; Block != NULL; Block = Block->Next) {
|
||||
//
|
||||
// scan the memory block list for the memory block that
|
||||
// completely contains the memory to free.
|
||||
//
|
||||
if ((Block->Buf <= ToFree) && ((ToFree + AllocSize) <= (Block->Buf + Block->BufLen))) {
|
||||
//
|
||||
// compute the start byte and bit in the bit array
|
||||
//
|
||||
Byte = ((ToFree - Block->Buf) / UFS_PEIM_MEM_UNIT) / 8;
|
||||
Bit = ((ToFree - Block->Buf) / UFS_PEIM_MEM_UNIT) % 8;
|
||||
|
||||
//
|
||||
// reset associated bits in bit arry
|
||||
//
|
||||
for (Count = 0; Count < (AllocSize / UFS_PEIM_MEM_UNIT); Count++) {
|
||||
ASSERT (UFS_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ UFS_PEIM_MEM_BIT (Bit));
|
||||
UFS_PEIM_NEXT_BIT (Byte, Bit);
|
||||
}
|
||||
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// If Block == NULL, it means that the current memory isn't
|
||||
// in the host controller's pool. This is critical because
|
||||
// the caller has passed in a wrong memory point
|
||||
//
|
||||
ASSERT (Block != NULL);
|
||||
|
||||
//
|
||||
// Release the current memory block if it is empty and not the head
|
||||
//
|
||||
if ((Block != Head) && UfsPeimIsMemBlockEmpty (Block)) {
|
||||
UfsPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _UFS_PEIM_MEM_H_
|
||||
#define _UFS_PEIM_MEM_H_
|
||||
|
||||
#define UFS_PEIM_MEM_BIT(a) ((UINTN)(1 << (a)))
|
||||
|
||||
#define UFS_PEIM_MEM_BIT_IS_SET(Data, Bit) \
|
||||
((BOOLEAN)(((Data) & UFS_PEIM_MEM_BIT(Bit)) == UFS_PEIM_MEM_BIT(Bit)))
|
||||
|
||||
typedef struct _UFS_PEIM_MEM_BLOCK UFS_PEIM_MEM_BLOCK;
|
||||
|
||||
struct _UFS_PEIM_MEM_BLOCK {
|
||||
UINT8 *Bits; // Bit array to record which unit is allocated
|
||||
UINTN BitsLen;
|
||||
UINT8 *Buf;
|
||||
UINTN BufLen; // Memory size in bytes
|
||||
UFS_PEIM_MEM_BLOCK *Next;
|
||||
};
|
||||
|
||||
typedef struct _UFS_PEIM_MEM_POOL {
|
||||
UFS_PEIM_MEM_BLOCK *Head;
|
||||
} UFS_PEIM_MEM_POOL;
|
||||
|
||||
//
|
||||
// Memory allocation unit, note that the value must meet UFS spec alignment requirement.
|
||||
//
|
||||
#define UFS_PEIM_MEM_UNIT 128
|
||||
|
||||
#define UFS_PEIM_MEM_UNIT_MASK (UFS_PEIM_MEM_UNIT - 1)
|
||||
#define UFS_PEIM_MEM_DEFAULT_PAGES 16
|
||||
|
||||
#define UFS_PEIM_MEM_ROUND(Len) (((Len) + UFS_PEIM_MEM_UNIT_MASK) & (~UFS_PEIM_MEM_UNIT_MASK))
|
||||
|
||||
//
|
||||
// Advance the byte and bit to the next bit, adjust byte accordingly.
|
||||
//
|
||||
#define UFS_PEIM_NEXT_BIT(Byte, Bit) \
|
||||
do { \
|
||||
(Bit)++; \
|
||||
if ((Bit) > 7) { \
|
||||
(Byte)++; \
|
||||
(Bit) = 0; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,222 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
#include "UfsPassThru.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUfsPassThruComponentName = {
|
||||
UfsPassThruComponentNameGetDriverName,
|
||||
UfsPassThruComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUfsPassThruComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) UfsPassThruComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) UfsPassThruComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsPassThruDriverNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"Universal Flash Storage (UFS) Pass Thru Driver"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mUfsPassThruControllerNameTable[] = {
|
||||
{
|
||||
"eng;en",
|
||||
L"Universal Flash Storage (UFS) Host Controller"
|
||||
},
|
||||
{
|
||||
NULL,
|
||||
NULL
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param DriverName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mUfsPassThruDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gUfsPassThruComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||
the name of. 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 retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
if (Language == NULL || ControllerName == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
//
|
||||
// This is a device driver, so ChildHandle must be NULL.
|
||||
//
|
||||
if (ChildHandle != NULL) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Make sure this driver is currently managing Controller Handle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gUfsPassThruDriverBinding.DriverBindingHandle,
|
||||
&gEdkiiUfsHostControllerProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mUfsPassThruControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gUfsPassThruComponentName)
|
||||
);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,727 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _UFS_PASS_THRU_H_
|
||||
#define _UFS_PASS_THRU_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <Protocol/ScsiPassThruExt.h>
|
||||
#include <Protocol/UfsHostController.h>
|
||||
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/BaseLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
#include <Library/IoLib.h>
|
||||
#include <Library/TimerLib.h>
|
||||
|
||||
#include "UfsPassThruHci.h"
|
||||
|
||||
#define UFS_PASS_THRU_SIG SIGNATURE_32 ('U', 'F', 'S', 'P')
|
||||
|
||||
//
|
||||
// Lun 0~7 is for 8 common luns.
|
||||
// Lun 8~11 is for those 4 well known luns (Refer to UFS 2.0 spec Table 10.58 for details):
|
||||
// Lun 8: REPORT LUNS
|
||||
// Lun 9: UFS DEVICE
|
||||
// Lun 10: BOOT
|
||||
// Lun 11: RPMB
|
||||
//
|
||||
#define UFS_MAX_LUNS 12
|
||||
#define UFS_WLUN_PREFIX 0xC1
|
||||
|
||||
typedef struct {
|
||||
UINT8 Lun[UFS_MAX_LUNS];
|
||||
UINT16 BitMask:12; // Bit 0~7 is 1/1 mapping to common luns. Bit 8~11 is 1/1 mapping to well-known luns.
|
||||
UINT16 Rsvd:4;
|
||||
} UFS_EXPOSED_LUNS;
|
||||
|
||||
typedef struct _UFS_PASS_THRU_PRIVATE_DATA {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_EXT_SCSI_PASS_THRU_MODE ExtScsiPassThruMode;
|
||||
EFI_EXT_SCSI_PASS_THRU_PROTOCOL ExtScsiPassThru;
|
||||
EDKII_UFS_HOST_CONTROLLER_PROTOCOL *UfsHostController;
|
||||
UINTN UfsHcBase;
|
||||
UINT32 Capabilities;
|
||||
|
||||
UINT8 TaskTag;
|
||||
|
||||
VOID *UtpTrlBase;
|
||||
UINT8 Nutrs;
|
||||
VOID *TrlMapping;
|
||||
VOID *UtpTmrlBase;
|
||||
UINT8 Nutmrs;
|
||||
VOID *TmrlMapping;
|
||||
|
||||
UFS_EXPOSED_LUNS Luns;
|
||||
} UFS_PASS_THRU_PRIVATE_DATA;
|
||||
|
||||
#define UFS_TIMEOUT EFI_TIMER_PERIOD_SECONDS(3)
|
||||
|
||||
#define ROUNDUP8(x) (((x) % 8 == 0) ? (x) : ((x) / 8 + 1) * 8)
|
||||
|
||||
#define IS_ALIGNED(addr, size) (((UINTN) (addr) & (size - 1)) == 0)
|
||||
|
||||
#define UFS_PASS_THRU_PRIVATE_DATA_FROM_THIS(a) \
|
||||
CR (a, \
|
||||
UFS_PASS_THRU_PRIVATE_DATA, \
|
||||
ExtScsiPassThru, \
|
||||
UFS_PASS_THRU_SIG \
|
||||
)
|
||||
|
||||
typedef struct _UFS_DEVICE_MANAGEMENT_REQUEST_PACKET {
|
||||
UINT64 Timeout;
|
||||
VOID *InDataBuffer;
|
||||
VOID *OutDataBuffer;
|
||||
UINT8 Opcode;
|
||||
UINT8 DescId;
|
||||
UINT8 Index;
|
||||
UINT8 Selector;
|
||||
UINT32 InTransferLength;
|
||||
UINT32 OutTransferLength;
|
||||
UINT8 DataDirection;
|
||||
UINT8 Ocs;
|
||||
} UFS_DEVICE_MANAGEMENT_REQUEST_PACKET;
|
||||
|
||||
//
|
||||
// function prototype
|
||||
//
|
||||
/**
|
||||
Tests to see if this driver supports a given controller. If a child device is provided,
|
||||
it further tests to see if this driver supports creating a handle for the specified child device.
|
||||
|
||||
This function checks to see if the driver specified by This supports the device specified by
|
||||
ControllerHandle. Drivers will typically use the device path attached to
|
||||
ControllerHandle and/or the services from the bus I/O abstraction attached to
|
||||
ControllerHandle to determine if the driver supports ControllerHandle. This function
|
||||
may be called many times during platform initialization. In order to reduce boot times, the tests
|
||||
performed by this function must be very small, and take as little time as possible to execute. This
|
||||
function must not change the state of any hardware devices, and this function must be aware that the
|
||||
device specified by ControllerHandle may already be managed by the same driver or a
|
||||
different driver. This function must match its calls to AllocatePages() with FreePages(),
|
||||
AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
|
||||
Since ControllerHandle may have been previously started by the same driver, if a protocol is
|
||||
already in the opened state, then it must not be closed with CloseProtocol(). This is required
|
||||
to guarantee the state of ControllerHandle is not modified by this function.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to test. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For bus drivers, if this parameter is not NULL, then
|
||||
the bus driver must determine if the bus controller specified
|
||||
by ControllerHandle and the child controller specified
|
||||
by RemainingDevicePath are both supported by this
|
||||
bus driver.
|
||||
|
||||
@retval EFI_SUCCESS The device specified by ControllerHandle and
|
||||
RemainingDevicePath is supported by the driver specified by This.
|
||||
@retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by the driver
|
||||
specified by This.
|
||||
@retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is already being managed by a different
|
||||
driver or an application that requires exclusive access.
|
||||
Currently not implemented.
|
||||
@retval EFI_UNSUPPORTED The device specified by ControllerHandle and
|
||||
RemainingDevicePath is not supported by the driver specified by This.
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Starts a device controller or a bus controller.
|
||||
|
||||
The Start() function is designed to be invoked from the EFI boot service ConnectController().
|
||||
As a result, much of the error checking on the parameters to Start() has been moved into this
|
||||
common boot service. It is legal to call Start() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE.
|
||||
2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
|
||||
EFI_DEVICE_PATH_PROTOCOL.
|
||||
3. Prior to calling Start(), the Supported() function for the driver specified by This must
|
||||
have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle The handle of the controller to start. This handle
|
||||
must support a protocol interface that supplies
|
||||
an I/O abstraction to the driver.
|
||||
@param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
|
||||
parameter is ignored by device drivers, and is optional for bus
|
||||
drivers. For a bus driver, if this parameter is NULL, then handles
|
||||
for all the children of Controller are created by this driver.
|
||||
If this parameter is not NULL and the first Device Path Node is
|
||||
not the End of Device Path Node, then only the handle for the
|
||||
child device specified by the first Device Path Node of
|
||||
RemainingDevicePath is created by this driver.
|
||||
If the first Device Path Node of RemainingDevicePath is
|
||||
the End of Device Path Node, no child handle is created by this
|
||||
driver.
|
||||
|
||||
@retval EFI_SUCCESS The device was started.
|
||||
@retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval Others The driver failded to start the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Stops a device controller or a bus controller.
|
||||
|
||||
The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
|
||||
As a result, much of the error checking on the parameters to Stop() has been moved
|
||||
into this common boot service. It is legal to call Stop() from other locations,
|
||||
but the following calling restrictions must be followed or the system behavior will not be deterministic.
|
||||
1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
|
||||
same driver's Start() function.
|
||||
2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
|
||||
EFI_HANDLE. In addition, all of these handles must have been created in this driver's
|
||||
Start() function, and the Start() function must have called OpenProtocol() on
|
||||
ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
|
||||
|
||||
@param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
|
||||
@param[in] ControllerHandle A handle to the device being stopped. The handle must
|
||||
support a bus specific I/O protocol for the driver
|
||||
to use to stop the device.
|
||||
@param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
|
||||
@param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
|
||||
if NumberOfChildren is 0.
|
||||
|
||||
@retval EFI_SUCCESS The device was stopped.
|
||||
@retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
//
|
||||
// EFI Component Name Functions
|
||||
//
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the driver.
|
||||
|
||||
This function retrieves the user readable name of a driver in the form of a
|
||||
Unicode string. If the driver specified by This has a user readable name in
|
||||
the language specified by Language, then a pointer to the driver name is
|
||||
returned in DriverName, and EFI_SUCCESS is returned. If the driver specified
|
||||
by This does not support the language specified by Language,
|
||||
then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified
|
||||
in RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param DriverName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
driver specified by This in the language
|
||||
specified by Language.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the Driver specified by
|
||||
This and the language specified by Language was
|
||||
returned in DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER DriverName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
);
|
||||
|
||||
|
||||
/**
|
||||
Retrieves a Unicode string that is the user readable name of the controller
|
||||
that is being managed by a driver.
|
||||
|
||||
This function retrieves the user readable name of the controller specified by
|
||||
ControllerHandle and ChildHandle in the form of a Unicode string. If the
|
||||
driver specified by This has a user readable name in the language specified by
|
||||
Language, then a pointer to the controller name is returned in ControllerName,
|
||||
and EFI_SUCCESS is returned. If the driver specified by This is not currently
|
||||
managing the controller specified by ControllerHandle and ChildHandle,
|
||||
then EFI_UNSUPPORTED is returned. If the driver specified by This does not
|
||||
support the language specified by Language, then EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param This[in] A pointer to the EFI_COMPONENT_NAME2_PROTOCOL or
|
||||
EFI_COMPONENT_NAME_PROTOCOL instance.
|
||||
|
||||
@param ControllerHandle[in] The handle of a controller that the driver
|
||||
specified by This is managing. This handle
|
||||
specifies the controller whose name is to be
|
||||
returned.
|
||||
|
||||
@param ChildHandle[in] The handle of the child controller to retrieve
|
||||
the name of. 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 retrieve the name of the bus
|
||||
controller. It will not be NULL for a bus
|
||||
driver that wishes to retrieve the name of a
|
||||
child controller.
|
||||
|
||||
@param Language[in] A pointer to a Null-terminated ASCII string
|
||||
array indicating the language. This is the
|
||||
language of the driver name that the caller is
|
||||
requesting, 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. Language is specified in
|
||||
RFC 4646 or ISO 639-2 language code format.
|
||||
|
||||
@param ControllerName[out] A pointer to the Unicode string to return.
|
||||
This Unicode string is the name of the
|
||||
controller specified by ControllerHandle and
|
||||
ChildHandle in the language specified by
|
||||
Language from the point of view of the driver
|
||||
specified by This.
|
||||
|
||||
@retval EFI_SUCCESS The Unicode string for the user readable name in
|
||||
the language specified by Language for the
|
||||
driver specified by This was returned in
|
||||
DriverName.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerHandle is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ChildHandle is not NULL and it is not a valid
|
||||
EFI_HANDLE.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER Language is NULL.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER ControllerName is NULL.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This is not currently
|
||||
managing the controller specified by
|
||||
ControllerHandle and ChildHandle.
|
||||
|
||||
@retval EFI_UNSUPPORTED The driver specified by This does not support
|
||||
the language specified by Language.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
/**
|
||||
Sends a SCSI Request Packet to a SCSI device that is attached to the SCSI channel. This function
|
||||
supports both blocking I/O and nonblocking I/O. The blocking I/O functionality is required, and the
|
||||
nonblocking I/O functionality is optional.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param Target The Target is an array of size TARGET_MAX_BYTES and it represents
|
||||
the id of the SCSI device to send the SCSI Request Packet. Each
|
||||
transport driver may choose to utilize a subset of this size to suit the needs
|
||||
of transport target representation. For example, a Fibre Channel driver
|
||||
may use only 8 bytes (WWN) to represent an FC target.
|
||||
@param Lun The LUN of the SCSI device to send the SCSI Request Packet.
|
||||
@param Packet A pointer to the SCSI Request Packet to send to the SCSI device
|
||||
specified by Target and Lun.
|
||||
@param Event If nonblocking I/O is not supported then Event is ignored, and blocking
|
||||
I/O is performed. If Event is NULL, then blocking I/O is performed. If
|
||||
Event is not NULL and non blocking I/O is supported, then
|
||||
nonblocking I/O is performed, and Event will be signaled when the
|
||||
SCSI Request Packet completes.
|
||||
|
||||
@retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
|
||||
commands, InTransferLength bytes were transferred from
|
||||
InDataBuffer. For write and bi-directional commands,
|
||||
OutTransferLength bytes were transferred by
|
||||
OutDataBuffer.
|
||||
@retval EFI_BAD_BUFFER_SIZE The SCSI Request Packet was not executed. The number of bytes that
|
||||
could be transferred is returned in InTransferLength. For write
|
||||
and bi-directional commands, OutTransferLength bytes were
|
||||
transferred by OutDataBuffer.
|
||||
@retval EFI_NOT_READY The SCSI Request Packet could not be sent because there are too many
|
||||
SCSI Request Packets already queued. The caller may retry again later.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
|
||||
Packet.
|
||||
@retval EFI_INVALID_PARAMETER Target, Lun, or the contents of ScsiRequestPacket are invalid.
|
||||
@retval EFI_UNSUPPORTED The command described by the SCSI Request Packet is not supported
|
||||
by the host adapter. This includes the case of Bi-directional SCSI
|
||||
commands not supported by the implementation. The SCSI Request
|
||||
Packet was not sent, so no additional status information is available.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruPassThru (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 *Target,
|
||||
IN UINT64 Lun,
|
||||
IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet,
|
||||
IN EFI_EVENT Event OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Used to retrieve the list of legal Target IDs and LUNs for SCSI devices on a SCSI channel. These
|
||||
can either be the list SCSI devices that are actually present on the SCSI channel, or the list of legal
|
||||
Target Ids and LUNs for the SCSI channel. Regardless, the caller of this function must probe the
|
||||
Target ID and LUN returned to see if a SCSI device is actually present at that location on the SCSI
|
||||
channel.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param Target On input, a pointer to the Target ID (an array of size
|
||||
TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
|
||||
On output, a pointer to the Target ID (an array of
|
||||
TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
|
||||
channel. An input value of 0xF(all bytes in the array are 0xF) in the
|
||||
Target array retrieves the Target ID of the first SCSI device present on a
|
||||
SCSI channel.
|
||||
@param Lun On input, a pointer to the LUN of a SCSI device present on the SCSI
|
||||
channel. On output, a pointer to the LUN of the next SCSI device present
|
||||
on a SCSI channel.
|
||||
|
||||
@retval EFI_SUCCESS The Target ID and LUN of the next SCSI device on the SCSI
|
||||
channel was returned in Target and Lun.
|
||||
@retval EFI_INVALID_PARAMETER Target array is not all 0xF, and Target and Lun were
|
||||
not returned on a previous call to GetNextTargetLun().
|
||||
@retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruGetNextTargetLun (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN OUT UINT8 **Target,
|
||||
IN OUT UINT64 *Lun
|
||||
);
|
||||
|
||||
/**
|
||||
Used to allocate and build a device path node for a SCSI device on a SCSI channel.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param Target The Target is an array of size TARGET_MAX_BYTES and it specifies the
|
||||
Target ID of the SCSI device for which a device path node is to be
|
||||
allocated and built. Transport drivers may chose to utilize a subset of
|
||||
this size to suit the representation of targets. For example, a Fibre
|
||||
Channel driver may use only 8 bytes (WWN) in the array to represent a
|
||||
FC target.
|
||||
@param Lun The LUN of the SCSI device for which a device path node is to be
|
||||
allocated and built.
|
||||
@param DevicePath A pointer to a single device path node that describes the SCSI device
|
||||
specified by Target and Lun. This function is responsible for
|
||||
allocating the buffer DevicePath with the boot service
|
||||
AllocatePool(). It is the caller's responsibility to free
|
||||
DevicePath when the caller is finished with DevicePath.
|
||||
|
||||
@retval EFI_SUCCESS The device path node that describes the SCSI device specified by
|
||||
Target and Lun was allocated and returned in
|
||||
DevicePath.
|
||||
@retval EFI_INVALID_PARAMETER DevicePath is NULL.
|
||||
@retval EFI_NOT_FOUND The SCSI devices specified by Target and Lun does not exist
|
||||
on the SCSI channel.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruBuildDevicePath (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 *Target,
|
||||
IN UINT64 Lun,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
Used to translate a device path node to a Target ID and LUN.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param DevicePath A pointer to a single device path node that describes the SCSI device
|
||||
on the SCSI channel.
|
||||
@param Target A pointer to the Target Array which represents the ID of a SCSI device
|
||||
on the SCSI channel.
|
||||
@param Lun A pointer to the LUN of a SCSI device on the SCSI channel.
|
||||
|
||||
@retval EFI_SUCCESS DevicePath was successfully translated to a Target ID and
|
||||
LUN, and they were returned in Target and Lun.
|
||||
@retval EFI_INVALID_PARAMETER DevicePath or Target or Lun is NULL.
|
||||
@retval EFI_NOT_FOUND A valid translation from DevicePath to a Target ID and LUN
|
||||
does not exist.
|
||||
@retval EFI_UNSUPPORTED This driver does not support the device path node type in
|
||||
DevicePath.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruGetTargetLun (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||
OUT UINT8 **Target,
|
||||
OUT UINT64 *Lun
|
||||
);
|
||||
|
||||
/**
|
||||
Resets a SCSI channel. This operation resets all the SCSI devices connected to the SCSI channel.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The SCSI channel was reset.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI channel.
|
||||
@retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI channel.
|
||||
@retval EFI_UNSUPPORTED The SCSI channel does not support a channel reset operation.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruResetChannel (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Resets a SCSI logical unit that is connected to a SCSI channel.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param Target The Target is an array of size TARGET_MAX_BYTE and it represents the
|
||||
target port ID of the SCSI device containing the SCSI logical unit to
|
||||
reset. Transport drivers may chose to utilize a subset of this array to suit
|
||||
the representation of their targets.
|
||||
@param Lun The LUN of the SCSI device to reset.
|
||||
|
||||
@retval EFI_SUCCESS The SCSI device specified by Target and Lun was reset.
|
||||
@retval EFI_INVALID_PARAMETER Target or Lun is NULL.
|
||||
@retval EFI_TIMEOUT A timeout occurred while attempting to reset the SCSI device
|
||||
specified by Target and Lun.
|
||||
@retval EFI_UNSUPPORTED The SCSI channel does not support a target reset operation.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to reset the SCSI device
|
||||
specified by Target and Lun.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruResetTargetLun (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 *Target,
|
||||
IN UINT64 Lun
|
||||
);
|
||||
|
||||
/**
|
||||
Used to retrieve the list of legal Target IDs for SCSI devices on a SCSI channel. These can either
|
||||
be the list SCSI devices that are actually present on the SCSI channel, or the list of legal Target IDs
|
||||
for the SCSI channel. Regardless, the caller of this function must probe the Target ID returned to
|
||||
see if a SCSI device is actually present at that location on the SCSI channel.
|
||||
|
||||
@param This A pointer to the EFI_EXT_SCSI_PASS_THRU_PROTOCOL instance.
|
||||
@param Target (TARGET_MAX_BYTES) of a SCSI device present on the SCSI channel.
|
||||
On output, a pointer to the Target ID (an array of
|
||||
TARGET_MAX_BYTES) of the next SCSI device present on a SCSI
|
||||
channel. An input value of 0xF(all bytes in the array are 0xF) in the
|
||||
Target array retrieves the Target ID of the first SCSI device present on a
|
||||
SCSI channel.
|
||||
|
||||
@retval EFI_SUCCESS The Target ID of the next SCSI device on the SCSI
|
||||
channel was returned in Target.
|
||||
@retval EFI_INVALID_PARAMETER Target or Lun is NULL.
|
||||
@retval EFI_TIMEOUT Target array is not all 0xF, and Target was not
|
||||
returned on a previous call to GetNextTarget().
|
||||
@retval EFI_NOT_FOUND There are no more SCSI devices on this SCSI channel.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
UfsPassThruGetNextTarget (
|
||||
IN EFI_EXT_SCSI_PASS_THRU_PROTOCOL *This,
|
||||
IN OUT UINT8 **Target
|
||||
);
|
||||
|
||||
/**
|
||||
Sends a UFS-supported SCSI Request Packet to a UFS device that is attached to the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
@param[in] Lun The LUN of the UFS device to send the SCSI Request Packet.
|
||||
@param[in, out] Packet A pointer to the SCSI Request Packet to send to a specified Lun of the
|
||||
UFS device.
|
||||
|
||||
@retval EFI_SUCCESS The SCSI Request Packet was sent by the host. For bi-directional
|
||||
commands, InTransferLength bytes were transferred from
|
||||
InDataBuffer. For write and bi-directional commands,
|
||||
OutTransferLength bytes were transferred by
|
||||
OutDataBuffer.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SCSI Request
|
||||
Packet.
|
||||
@retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the SCSI Request Packet to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsExecScsiCmds (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
|
||||
IN UINT8 Lun,
|
||||
IN OUT EFI_EXT_SCSI_PASS_THRU_SCSI_REQUEST_PACKET *Packet
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the NVME_CONTROLLER_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The NVM Express Controller is initialized successfully.
|
||||
@retval Others A device error occurred while initializing the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsControllerInit (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Stop the UFS host controller.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The Ufs Host Controller is stopped successfully.
|
||||
@retval Others A device error occurred while stopping the controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsControllerStop (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
/**
|
||||
Allocate common buffer for host and UFS bus master access simultaneously.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
@param[in] Size The length of buffer to be allocated.
|
||||
@param[out] CmdDescHost A pointer to store the base system memory address of the allocated range.
|
||||
@param[out] CmdDescPhyAddr The resulting map address for the UFS bus master to use to access the hosts CmdDescHost.
|
||||
@param[out] CmdDescMapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The common buffer was allocated successfully.
|
||||
@retval EFI_DEVICE_ERROR The allocation fails.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory resource is insufficient.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsAllocateAlignCommonBuffer (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
|
||||
IN UINTN Size,
|
||||
OUT VOID **CmdDescHost,
|
||||
OUT EFI_PHYSICAL_ADDRESS *CmdDescPhyAddr,
|
||||
OUT VOID **CmdDescMapping
|
||||
);
|
||||
|
||||
/**
|
||||
Set specified flag to 1 on a UFS device.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
@param[in] FlagId The ID of flag to be set.
|
||||
|
||||
@retval EFI_SUCCESS The flag was set successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to set the flag.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of setting the flag.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsSetFlag (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
|
||||
IN UINT8 FlagId
|
||||
);
|
||||
|
||||
/**
|
||||
Read or write specified device descriptor of a UFS device.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
@param[in] Read The boolean variable to show r/w direction.
|
||||
@param[in] DescId The ID of device descriptor.
|
||||
@param[in] Index The Index of device descriptor.
|
||||
@param[in] Selector The Selector of device descriptor.
|
||||
@param[in, out] Descriptor The buffer of device descriptor to be read or written.
|
||||
@param[in] DescSize The size of device descriptor buffer.
|
||||
|
||||
@retval EFI_SUCCESS The device descriptor was read/written successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to r/w the device descriptor.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the completion of r/w the device descriptor.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsRwDeviceDesc (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private,
|
||||
IN BOOLEAN Read,
|
||||
IN UINT8 DescId,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Selector,
|
||||
IN OUT VOID *Descriptor,
|
||||
IN UINT32 DescSize
|
||||
);
|
||||
|
||||
/**
|
||||
Sends NOP IN cmd to a UFS device for initialization process request.
|
||||
For more details, please refer to UFS 2.0 spec Figure 13.3.
|
||||
|
||||
@param[in] Private The pointer to the UFS_PASS_THRU_PRIVATE_DATA data structure.
|
||||
|
||||
@retval EFI_SUCCESS The NOP IN command was sent by the host. The NOP OUT response was
|
||||
received successfully.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to execute NOP IN command.
|
||||
@retval EFI_OUT_OF_RESOURCES The resource for transfer is not available.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the NOP IN command to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
UfsExecNopCmds (
|
||||
IN UFS_PASS_THRU_PRIVATE_DATA *Private
|
||||
);
|
||||
|
||||
extern GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gUfsPassThruComponentName;
|
||||
extern GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gUfsPassThruComponentName2;
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gUfsPassThruDriverBinding;
|
||||
|
||||
#endif
|
Binary file not shown.
|
@ -0,0 +1,63 @@
|
|||
## @file
|
||||
# Description file for the Universal Flash Storage (UFS) Pass Thru driver.
|
||||
#
|
||||
# Copyright (c) 2014 - 2015, Intel Corporation. All rights reserved.<BR>
|
||||
#
|
||||
# This program and the accompanying materials
|
||||
# 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.
|
||||
#
|
||||
#
|
||||
##
|
||||
|
||||
[Defines]
|
||||
INF_VERSION = 0x00010005
|
||||
BASE_NAME = UfsPassThruDxe
|
||||
MODULE_UNI_FILE = UfsPassThru.uni
|
||||
FILE_GUID = E7F1DFF9-DAB6-498A-9ADF-57F344EDDF57
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InitializeUfsPassThru
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gUfsPassThruDriverBinding
|
||||
# COMPONENT_NAME = gUfsPassThruComponentName
|
||||
#
|
||||
|
||||
[Sources]
|
||||
ComponentName.c
|
||||
UfsPassThru.c
|
||||
UfsPassThru.h
|
||||
UfsPassThruHci.c
|
||||
UfsPassThruHci.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
DevicePathLib
|
||||
IoLib
|
||||
TimerLib
|
||||
|
||||
[Protocols]
|
||||
gEfiExtScsiPassThruProtocolGuid ## BY_START
|
||||
gEdkiiUfsHostControllerProtocolGuid ## TO_START
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
UfsPassThruExtra.uni
|
Binary file not shown.
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,60 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
|
||||
This program and the accompanying materials
|
||||
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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EDKII_PEI_UFS_HOST_CONTROLLER_PPI_H_
|
||||
#define _EDKII_PEI_UFS_HOST_CONTROLLER_PPI_H_
|
||||
|
||||
///
|
||||
/// Global ID for the EDKII_UFS_HOST_CONTROLLER_PPI.
|
||||
///
|
||||
#define EDKII_UFS_HOST_CONTROLLER_PPI_GUID \
|
||||
{ \
|
||||
0xdc54b283, 0x1a77, 0x4cd6, { 0x83, 0xbb, 0xfd, 0xda, 0x46, 0x9a, 0x2e, 0xc6 } \
|
||||
}
|
||||
|
||||
///
|
||||
/// Forward declaration for the UFS_HOST_CONTROLLER_PPI.
|
||||
///
|
||||
typedef struct _EDKII_UFS_HOST_CONTROLLER_PPI EDKII_UFS_HOST_CONTROLLER_PPI;
|
||||
|
||||
/**
|
||||
Get the MMIO base address of UFS host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the UFS host controller.
|
||||
@param[out] MmioBar Pointer to the UFS host controller MMIO base address.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_GET_MMIO_BAR)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
OUT UINTN *MmioBar
|
||||
);
|
||||
|
||||
///
|
||||
/// This PPI contains a set of services to interact with the UFS host controller.
|
||||
///
|
||||
struct _EDKII_UFS_HOST_CONTROLLER_PPI {
|
||||
EDKII_UFS_HC_GET_MMIO_BAR GetUfsHcMmioBar;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEdkiiPeiUfsHostControllerPpiGuid;
|
||||
|
||||
#endif
|
|
@ -0,0 +1,205 @@
|
|||
/** @file
|
||||
|
||||
EDKII Universal Flash Storage Host Controller Protocol.
|
||||
|
||||
Copyright (c) 2014, Intel Corporation. All rights reserved.<BR>
|
||||
This program and the accompanying materials are licensed and made available under
|
||||
the terms and conditions of the BSD License that 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.
|
||||
|
||||
**/
|
||||
|
||||
|
||||
#ifndef __EDKII_UFS_HC_PROTOCOL_H__
|
||||
#define __EDKII_UFS_HC_PROTOCOL_H__
|
||||
|
||||
//
|
||||
// UFS Host Controller Protocol GUID value
|
||||
//
|
||||
#define EDKII_UFS_HOST_CONTROLLER_PROTOCOL_GUID \
|
||||
{ \
|
||||
0xebc01af5, 0x7a9, 0x489e, { 0xb7, 0xce, 0xdc, 0x8, 0x9e, 0x45, 0x9b, 0x2f } \
|
||||
}
|
||||
|
||||
//
|
||||
// Forward reference for pure ANSI compatability
|
||||
//
|
||||
typedef struct _EDKII_UFS_HOST_CONTROLLER_PROTOCOL EDKII_UFS_HOST_CONTROLLER_PROTOCOL;
|
||||
|
||||
|
||||
/**
|
||||
Get the MMIO base address of UFS host controller.
|
||||
|
||||
@param This The protocol instance pointer.
|
||||
@param MmioBar Pointer to the UFS host controller MMIO base address.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_GET_MMIO_BAR)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
OUT UINTN *MmioBar
|
||||
);
|
||||
|
||||
///
|
||||
/// *******************************************************
|
||||
/// EFI_UFS_HOST_CONTROLLER_OPERATION
|
||||
/// *******************************************************
|
||||
///
|
||||
typedef enum {
|
||||
///
|
||||
/// A read operation from system memory by a bus master.
|
||||
///
|
||||
EdkiiUfsHcOperationBusMasterRead,
|
||||
///
|
||||
/// A write operation from system memory by a bus master.
|
||||
///
|
||||
EdkiiUfsHcOperationBusMasterWrite,
|
||||
///
|
||||
/// Provides both read and write access to system memory by both the processor and a
|
||||
/// bus master. The buffer is coherent from both the processor's and the bus master's point of view.
|
||||
///
|
||||
EdkiiUfsHcOperationBusMasterCommonBuffer,
|
||||
EdkiiUfsHcOperationMaximum
|
||||
} EDKII_UFS_HOST_CONTROLLER_OPERATION;
|
||||
|
||||
/**
|
||||
Provides the UFS controller-specific addresses needed to access system memory.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Operation Indicates if the bus master is going to read or write to system memory.
|
||||
@param HostAddress The system memory address to map to the UFS controller.
|
||||
@param NumberOfBytes On input the number of bytes to map. On output the number of bytes
|
||||
that were mapped.
|
||||
@param DeviceAddress The resulting map address for the bus master UFS controller to use to
|
||||
access the hosts HostAddress.
|
||||
@param Mapping A resulting value to pass to Unmap().
|
||||
|
||||
@retval EFI_SUCCESS The range was mapped for the returned NumberOfBytes.
|
||||
@retval EFI_UNSUPPORTED The HostAddress cannot be mapped as a common buffer.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
|
||||
@retval EFI_DEVICE_ERROR The system hardware could not map the requested address.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_MAP)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EDKII_UFS_HOST_CONTROLLER_OPERATION Operation,
|
||||
IN VOID *HostAddress,
|
||||
IN OUT UINTN *NumberOfBytes,
|
||||
OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
|
||||
OUT VOID **Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Completes the Map() operation and releases any corresponding resources.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Mapping The mapping value returned from Map().
|
||||
|
||||
@retval EFI_SUCCESS The range was unmapped.
|
||||
@retval EFI_DEVICE_ERROR The data was not committed to the target system memory.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_UNMAP)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN VOID *Mapping
|
||||
);
|
||||
|
||||
/**
|
||||
Allocates pages that are suitable for an EfiUfsHcOperationBusMasterCommonBuffer
|
||||
mapping.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Type This parameter is not used and must be ignored.
|
||||
@param MemoryType The type of memory to allocate, EfiBootServicesData or
|
||||
EfiRuntimeServicesData.
|
||||
@param Pages The number of pages to allocate.
|
||||
@param HostAddress A pointer to store the base system memory address of the
|
||||
allocated range.
|
||||
@param Attributes The requested bit mask of attributes for the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were allocated.
|
||||
@retval EFI_UNSUPPORTED Attributes is unsupported. The only legal attribute bits are
|
||||
MEMORY_WRITE_COMBINE and MEMORY_CACHED.
|
||||
@retval EFI_INVALID_PARAMETER One or more parameters are invalid.
|
||||
@retval EFI_OUT_OF_RESOURCES The memory pages could not be allocated.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_ALLOCATE_BUFFER)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN EFI_ALLOCATE_TYPE Type,
|
||||
IN EFI_MEMORY_TYPE MemoryType,
|
||||
IN UINTN Pages,
|
||||
OUT VOID **HostAddress,
|
||||
IN UINT64 Attributes
|
||||
);
|
||||
|
||||
/**
|
||||
Frees memory that was allocated with AllocateBuffer().
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
@param Pages The number of pages to free.
|
||||
@param HostAddress The base system memory address of the allocated range.
|
||||
|
||||
@retval EFI_SUCCESS The requested memory pages were freed.
|
||||
@retval EFI_INVALID_PARAMETER The memory range specified by HostAddress and Pages
|
||||
was not allocated with AllocateBuffer().
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_FREE_BUFFER)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This,
|
||||
IN UINTN Pages,
|
||||
IN VOID *HostAddress
|
||||
);
|
||||
|
||||
/**
|
||||
Flushes all posted write transactions from the UFS bus to attached UFS device.
|
||||
|
||||
@param This A pointer to the EFI_UFS_HOST_CONTROLLER_PROTOCOL instance.
|
||||
|
||||
@retval EFI_SUCCESS The posted write transactions were flushed from the UFS bus
|
||||
to attached UFS device.
|
||||
@retval EFI_DEVICE_ERROR The posted write transactions were not flushed from the UFS
|
||||
bus to attached UFS device due to a hardware error.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_UFS_HC_FLUSH)(
|
||||
IN EDKII_UFS_HOST_CONTROLLER_PROTOCOL *This
|
||||
);
|
||||
|
||||
///
|
||||
/// UFS Host Controller Protocol structure.
|
||||
///
|
||||
struct _EDKII_UFS_HOST_CONTROLLER_PROTOCOL {
|
||||
EDKII_UFS_HC_GET_MMIO_BAR GetUfsHcMmioBar;
|
||||
EDKII_UFS_HC_ALLOCATE_BUFFER AllocateBuffer;
|
||||
EDKII_UFS_HC_FREE_BUFFER FreeBuffer;
|
||||
EDKII_UFS_HC_MAP Map;
|
||||
EDKII_UFS_HC_UNMAP Unmap;
|
||||
EDKII_UFS_HC_FLUSH Flush;
|
||||
};
|
||||
|
||||
///
|
||||
/// UFS Host Controller Protocol GUID variable.
|
||||
///
|
||||
extern EFI_GUID gEdkiiUfsHostControllerProtocolGuid;
|
||||
|
||||
#endif
|
|
@ -324,6 +324,9 @@
|
|||
## Include/Ppi/SerialPortPei.h
|
||||
gPeiSerialPortPpiGuid = { 0x490e9d85, 0x8aef, 0x4193, { 0x8e, 0x56, 0xf7, 0x34, 0xa9, 0xff, 0xac, 0x8b}}
|
||||
|
||||
## Include/Ppi/UfsHostController.h
|
||||
gEdkiiPeiUfsHostControllerPpiGuid = { 0xdc54b283, 0x1a77, 0x4cd6, { 0x83, 0xbb, 0xfd, 0xda, 0x46, 0x9a, 0x2e, 0xc6 }}
|
||||
|
||||
[Protocols]
|
||||
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
||||
# Include/Protocol/LoadPe32Image.h
|
||||
|
@ -401,6 +404,9 @@
|
|||
## Include/Protocol/FormBrowserEx2.h
|
||||
gEdkiiFormBrowserEx2ProtocolGuid = { 0xa770c357, 0xb693, 0x4e6d, { 0xa6, 0xcf, 0xd2, 0x1c, 0x72, 0x8e, 0x55, 0xb } }
|
||||
|
||||
## Include/Protocol/UfsHostController.h
|
||||
gEdkiiUfsHostControllerProtocolGuid = { 0xebc01af5, 0x7a9, 0x489e, { 0xb7, 0xce, 0xdc, 0x8, 0x9e, 0x45, 0x9b, 0x2f } }
|
||||
|
||||
#
|
||||
# [Error.gEfiMdeModulePkgTokenSpaceGuid]
|
||||
# 0x80000001 | Invalid value provided.
|
||||
|
@ -1214,6 +1220,12 @@
|
|||
# @Prompt Disk I/O - Number of Data Buffer block.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdDiskIoDataBufferBlockNum|64|UINT32|0x30001039
|
||||
|
||||
## This PCD specifies the PCI-based UFS host controller mmio base address.
|
||||
# Define the mmio base address of the pci-based UFS host controller. If there are multiple UFS
|
||||
# host controllers, their mmio base addresses are calculated one by one from this base address.
|
||||
# @Prompt Mmio base address of pci-based UFS host controller.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdUfsPciHostControllerMmioBase|0xd0000000|UINT32|0x10000061
|
||||
|
||||
[PcdsPatchableInModule]
|
||||
## Specify memory size with page number for PEI code when
|
||||
# Loading Module at Fixed Address feature is enabled.
|
||||
|
|
|
@ -203,6 +203,10 @@
|
|||
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
|
||||
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
|
||||
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
|
||||
MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
|
||||
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
|
||||
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
|
||||
MdeModulePkg/Bus/Ufs/UfsBlockIoPei/UfsBlockIoPei.inf
|
||||
MdeModulePkg/Bus/Pci/XhciDxe/XhciDxe.inf
|
||||
MdeModulePkg/Bus/Pci/EhciDxe/EhciDxe.inf
|
||||
MdeModulePkg/Bus/Pci/UhciDxe/UhciDxe.inf
|
||||
|
|
Binary file not shown.
Loading…
Reference in New Issue