mirror of https://github.com/acidanthera/audk.git
MdeModulePkg/SdMmc: Add EDKII SD/MMC stack
This stack includes: 1. Dxe phase support by: 1) SdMmcPciHcDxe driver to consume PciIo and produce SdMmcPassThru. 2) SdDxe driver to consume SdMmcPassThru to produce BlkIo1/BlkIo2. 3) EmmcDxe driver to consume SdMmcPassThru to produce BlkIo1/BlkIo2/SSP. 2. Pei phase support 1) SdBlockIoPei driver to consume SdMmcHostController Ppi and produce VirutalBlkIo1&2. 2) EmmcBlockIoPei driver to consume SdMmcHostController Ppi and produce VirutalBlkIo1&2. 3) SdMmcPciHcPei driver to produce SdMmcHostController Ppi. Contributed-under: TianoCore Contribution Agreement 1.0 Signed-off-by: Feng Tian <feng.tian@intel.com> Reviewed-by: Hao Wu <hao.a.wu@intel.com>
This commit is contained in:
parent
627373d7e7
commit
48555339be
|
@ -0,0 +1,211 @@
|
|||
/** @file
|
||||
UEFI Component Name(2) protocol implementation for SD/MMC host controller driver.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdMmcPciHcDxe.h"
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName = {
|
||||
SdMmcPciHcComponentNameGetDriverName,
|
||||
SdMmcPciHcComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciHcComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdMmcPciHcComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdMmcPciHcComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMmcPciHcDriverNameTable[] = {
|
||||
{ "eng;en", L"Edkii Sd/Mmc Host Controller Driver" },
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdMmcPciHcControllerNameTable[] = {
|
||||
{ "eng;en", L"Edkii Sd/Mmc 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
|
||||
SdMmcPciHcComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mSdMmcPciHcDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gSdMmcPciHcComponentName)
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
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 not a valid EFI_HANDLE.
|
||||
|
||||
@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
|
||||
SdMmcPciHcComponentNameGetControllerName (
|
||||
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 ControllerHandle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gSdMmcPciHcDriverBinding.DriverBindingHandle,
|
||||
&gEfiPciIoProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mSdMmcPciHcControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gSdMmcPciHcComponentName)
|
||||
);
|
||||
}
|
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,784 @@
|
|||
/** @file
|
||||
|
||||
Provides some data structure definitions used by the SD/MMC host controller driver.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_MMC_PCI_HC_DXE_H_
|
||||
#define _SD_MMC_PCI_HC_DXE_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
|
||||
#include <IndustryStandard/Pci.h>
|
||||
#include <IndustryStandard/Emmc.h>
|
||||
#include <IndustryStandard/Sd.h>
|
||||
|
||||
#include <Library/UefiDriverEntryPoint.h>
|
||||
#include <Library/DebugLib.h>
|
||||
#include <Library/UefiBootServicesTableLib.h>
|
||||
#include <Library/BaseMemoryLib.h>
|
||||
#include <Library/MemoryAllocationLib.h>
|
||||
#include <Library/UefiLib.h>
|
||||
#include <Library/DevicePathLib.h>
|
||||
|
||||
#include <Protocol/DevicePath.h>
|
||||
#include <Protocol/PciIo.h>
|
||||
#include <Protocol/DriverBinding.h>
|
||||
#include <Protocol/ComponentName.h>
|
||||
#include <Protocol/ComponentName2.h>
|
||||
#include <Protocol/SdMmcPassThru.h>
|
||||
|
||||
#include "SdMmcPciHci.h"
|
||||
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gSdMmcPciHcComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gSdMmcPciHcComponentName2;
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gSdMmcPciHcDriverBinding;
|
||||
|
||||
#define SD_MMC_HC_PRIVATE_SIGNATURE SIGNATURE_32 ('s', 'd', 't', 'f')
|
||||
|
||||
#define SD_MMC_HC_PRIVATE_FROM_THIS(a) \
|
||||
CR(a, SD_MMC_HC_PRIVATE_DATA, PassThru, SD_MMC_HC_PRIVATE_SIGNATURE)
|
||||
|
||||
//
|
||||
// Generic time out value, 1 microsecond as unit.
|
||||
//
|
||||
#define SD_MMC_HC_GENERIC_TIMEOUT 1 * 1000 * 1000
|
||||
|
||||
//
|
||||
// SD/MMC async transfer timer interval, set by experience.
|
||||
// The unit is 100us, takes 1ms as interval.
|
||||
//
|
||||
#define SD_MMC_HC_ASYNC_TIMER EFI_TIMER_PERIOD_MILLISECONDS(1)
|
||||
//
|
||||
// SD/MMC removable device enumeration timer interval, set by experience.
|
||||
// The unit is 100us, takes 100ms as interval.
|
||||
//
|
||||
#define SD_MMC_HC_ENUM_TIMER EFI_TIMER_PERIOD_MILLISECONDS(100)
|
||||
|
||||
typedef enum {
|
||||
UnknownCardType,
|
||||
SdCardType,
|
||||
SdioCardType,
|
||||
MmcCardType,
|
||||
EmmcCardType
|
||||
} SD_MMC_CARD_TYPE;
|
||||
|
||||
typedef enum {
|
||||
RemovableSlot,
|
||||
EmbeddedSlot,
|
||||
SharedBusSlot,
|
||||
UnknownSlot
|
||||
} EFI_SD_MMC_SLOT_TYPE;
|
||||
|
||||
typedef struct {
|
||||
BOOLEAN Enable;
|
||||
EFI_SD_MMC_SLOT_TYPE SlotType;
|
||||
BOOLEAN MediaPresent;
|
||||
SD_MMC_CARD_TYPE CardType;
|
||||
} SD_MMC_HC_SLOT;
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
|
||||
EFI_HANDLE ControllerHandle;
|
||||
EFI_PCI_IO_PROTOCOL *PciIo;
|
||||
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL PassThru;
|
||||
|
||||
UINT64 PciAttributes;
|
||||
//
|
||||
// The field is used to record the previous slot in GetNextSlot().
|
||||
//
|
||||
UINT8 PreviousSlot;
|
||||
//
|
||||
// For Non-blocking operation.
|
||||
//
|
||||
EFI_EVENT TimerEvent;
|
||||
//
|
||||
// For Sd removable device enumeration.
|
||||
//
|
||||
EFI_EVENT ConnectEvent;
|
||||
LIST_ENTRY Queue;
|
||||
|
||||
SD_MMC_HC_SLOT Slot[SD_MMC_HC_MAX_SLOT];
|
||||
SD_MMC_HC_SLOT_CAP Capability[SD_MMC_HC_MAX_SLOT];
|
||||
UINT64 MaxCurrent[SD_MMC_HC_MAX_SLOT];
|
||||
|
||||
UINT32 ControllerVersion;
|
||||
} SD_MMC_HC_PRIVATE_DATA;
|
||||
|
||||
#define SD_MMC_HC_TRB_SIG SIGNATURE_32 ('T', 'R', 'B', 'T')
|
||||
|
||||
//
|
||||
// TRB (Transfer Request Block) contains information for the cmd request.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY TrbList;
|
||||
|
||||
UINT8 Slot;
|
||||
UINT16 BlockSize;
|
||||
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
|
||||
VOID *Data;
|
||||
UINT32 DataLen;
|
||||
BOOLEAN Read;
|
||||
EFI_PHYSICAL_ADDRESS DataPhy;
|
||||
VOID *DataMap;
|
||||
SD_MMC_HC_TRANSFER_MODE Mode;
|
||||
|
||||
EFI_EVENT Event;
|
||||
BOOLEAN Started;
|
||||
UINT64 Timeout;
|
||||
|
||||
SD_MMC_HC_ADMA_DESC_LINE *AdmaDesc;
|
||||
EFI_PHYSICAL_ADDRESS AdmaDescPhy;
|
||||
VOID *AdmaMap;
|
||||
UINT32 AdmaPages;
|
||||
|
||||
SD_MMC_HC_PRIVATE_DATA *Private;
|
||||
} SD_MMC_HC_TRB;
|
||||
|
||||
#define SD_MMC_HC_TRB_FROM_THIS(a) \
|
||||
CR(a, SD_MMC_HC_TRB, TrbList, SD_MMC_HC_TRB_SIG)
|
||||
|
||||
//
|
||||
// Task for Non-blocking mode.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
UINT8 Slot;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet;
|
||||
BOOLEAN IsStart;
|
||||
EFI_EVENT Event;
|
||||
UINT64 RetryTimes;
|
||||
BOOLEAN InfiniteWait;
|
||||
VOID *Map;
|
||||
VOID *MapAddress;
|
||||
} SD_MMC_HC_QUEUE;
|
||||
|
||||
//
|
||||
// Prototypes
|
||||
//
|
||||
/**
|
||||
Execute card identification procedure.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS The card is identified correctly.
|
||||
@retval Others The card can't be identified.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(*CARD_TYPE_DETECT_ROUTINE) (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Sends SD command to an SD card that is attached to the SD controller.
|
||||
|
||||
The PassThru() function sends the SD command specified by Packet to the SD card
|
||||
specified by Slot.
|
||||
|
||||
If Packet is successfully sent to the SD card, then EFI_SUCCESS is returned.
|
||||
|
||||
If a device error occurs while sending the Packet, then EFI_DEVICE_ERROR is returned.
|
||||
|
||||
If Slot is not in a valid range for the SD controller, then EFI_INVALID_PARAMETER
|
||||
is returned.
|
||||
|
||||
If Packet defines a data command but both InDataBuffer and OutDataBuffer are NULL,
|
||||
EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in,out] Packet A pointer to the SD command data structure.
|
||||
@param[in] Event If Event is NULL, blocking I/O is performed. If Event is
|
||||
not NULL, then nonblocking I/O is performed, and Event
|
||||
will be signaled when the Packet completes.
|
||||
|
||||
@retval EFI_SUCCESS The SD Command Packet was sent by the host.
|
||||
@retval EFI_DEVICE_ERROR A device error occurred while attempting to send the SD
|
||||
command Packet.
|
||||
@retval EFI_INVALID_PARAMETER Packet, Slot, or the contents of the Packet is invalid.
|
||||
@retval EFI_INVALID_PARAMETER Packet defines a data command but both InDataBuffer and
|
||||
OutDataBuffer are NULL.
|
||||
@retval EFI_NO_MEDIA SD Device not present in the Slot.
|
||||
@retval EFI_UNSUPPORTED The command described by the SD Command Packet is not
|
||||
supported by the host controller.
|
||||
@retval EFI_BAD_BUFFER_SIZE The InTransferLength or OutTransferLength exceeds the
|
||||
limit supported by SD card ( i.e. if the number of bytes
|
||||
exceed the Last LBA).
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcPassThruPassThru (
|
||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 Slot,
|
||||
IN OUT EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,
|
||||
IN EFI_EVENT Event OPTIONAL
|
||||
);
|
||||
|
||||
/**
|
||||
Used to retrieve next slot numbers supported by the SD controller. The function
|
||||
returns information about all available slots (populated or not-populated).
|
||||
|
||||
The GetNextSlot() function retrieves the next slot number on an SD controller.
|
||||
If on input Slot is 0xFF, then the slot number of the first slot on the SD controller
|
||||
is returned.
|
||||
|
||||
If Slot is a slot number that was returned on a previous call to GetNextSlot(), then
|
||||
the slot number of the next slot on the SD controller is returned.
|
||||
|
||||
If Slot is not 0xFF and Slot was not returned on a previous call to GetNextSlot(),
|
||||
EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
If Slot is the slot number of the last slot on the SD controller, then EFI_NOT_FOUND
|
||||
is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
|
||||
@param[in,out] Slot On input, a pointer to a slot number on the SD controller.
|
||||
On output, a pointer to the next slot number on the SD controller.
|
||||
An input value of 0xFF retrieves the first slot number on the SD
|
||||
controller.
|
||||
|
||||
@retval EFI_SUCCESS The next slot number on the SD controller was returned in Slot.
|
||||
@retval EFI_NOT_FOUND There are no more slots on this SD controller.
|
||||
@retval EFI_INVALID_PARAMETER Slot is not 0xFF and Slot was not returned on a previous call
|
||||
to GetNextSlot().
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcPassThruGetNextSlot (
|
||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
|
||||
IN OUT UINT8 *Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Used to allocate and build a device path node for an SD card on the SD controller.
|
||||
|
||||
The BuildDevicePath() function allocates and builds a single device node for the SD
|
||||
card specified by Slot.
|
||||
|
||||
If the SD card specified by Slot is not present on the SD controller, then EFI_NOT_FOUND
|
||||
is returned.
|
||||
|
||||
If DevicePath is NULL, then EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
If there are not enough resources to allocate the device path node, then EFI_OUT_OF_RESOURCES
|
||||
is returned.
|
||||
|
||||
Otherwise, DevicePath is allocated with the boot service AllocatePool(), the contents of
|
||||
DevicePath are initialized to describe the SD card specified by Slot, and EFI_SUCCESS is
|
||||
returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SD_MMMC_PASS_THRU_PROTOCOL instance.
|
||||
@param[in] Slot Specifies the slot number of the SD card for which a device
|
||||
path node is to be allocated and built.
|
||||
@param[in,out] DevicePath A pointer to a single device path node that describes the SD
|
||||
card specified by Slot. 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 SD card specified by
|
||||
Slot was allocated and returned in DevicePath.
|
||||
@retval EFI_NOT_FOUND The SD card specified by Slot does not exist on the SD controller.
|
||||
@retval EFI_INVALID_PARAMETER DevicePath is NULL.
|
||||
@retval EFI_OUT_OF_RESOURCES There are not enough resources to allocate DevicePath.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcPassThruBuildDevicePath (
|
||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 Slot,
|
||||
IN OUT EFI_DEVICE_PATH_PROTOCOL **DevicePath
|
||||
);
|
||||
|
||||
/**
|
||||
This function retrieves an SD card slot number based on the input device path.
|
||||
|
||||
The GetSlotNumber() function retrieves slot number for the SD card specified by
|
||||
the DevicePath node. If DevicePath is NULL, EFI_INVALID_PARAMETER is returned.
|
||||
|
||||
If DevicePath is not a device path node type that the SD Pass Thru driver supports,
|
||||
EFI_UNSUPPORTED is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
|
||||
@param[in] DevicePath A pointer to the device path node that describes a SD
|
||||
card on the SD controller.
|
||||
@param[out] Slot On return, points to the slot number of an SD card on
|
||||
the SD controller.
|
||||
|
||||
@retval EFI_SUCCESS SD card slot number is returned in Slot.
|
||||
@retval EFI_INVALID_PARAMETER Slot or DevicePath is NULL.
|
||||
@retval EFI_UNSUPPORTED DevicePath is not a device path node type that the SD
|
||||
Pass Thru driver supports.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcPassThruGetSlotNumber (
|
||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *DevicePath,
|
||||
OUT UINT8 *Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Resets an SD card that is connected to the SD controller.
|
||||
|
||||
The ResetDevice() function resets the SD card specified by Slot.
|
||||
|
||||
If this SD controller does not support a device reset operation, EFI_UNSUPPORTED is
|
||||
returned.
|
||||
|
||||
If Slot is not in a valid slot number for this SD controller, EFI_INVALID_PARAMETER
|
||||
is returned.
|
||||
|
||||
If the device reset operation is completed, EFI_SUCCESS is returned.
|
||||
|
||||
@param[in] This A pointer to the EFI_SD_MMC_PASS_THRU_PROTOCOL instance.
|
||||
@param[in] Slot Specifies the slot number of the SD card to be reset.
|
||||
|
||||
@retval EFI_SUCCESS The SD card specified by Slot was reset.
|
||||
@retval EFI_UNSUPPORTED The SD controller does not support a device reset operation.
|
||||
@retval EFI_INVALID_PARAMETER Slot number is invalid.
|
||||
@retval EFI_NO_MEDIA SD Device not present in the Slot.
|
||||
@retval EFI_DEVICE_ERROR The reset command failed due to a device error
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcPassThruResetDevice (
|
||||
IN EFI_SD_MMC_PASS_THRU_PROTOCOL *This,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
//
|
||||
// Driver model protocol interfaces
|
||||
//
|
||||
/**
|
||||
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
|
||||
SdMmcPciHcDriverBindingSupported (
|
||||
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
|
||||
SdMmcPciHcDriverBindingStart (
|
||||
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
|
||||
SdMmcPciHcDriverBindingStop (
|
||||
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
|
||||
SdMmcPciHcComponentNameGetDriverName (
|
||||
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 not a valid EFI_HANDLE.
|
||||
|
||||
@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
|
||||
SdMmcPciHcComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle, OPTIONAL
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
/**
|
||||
Create a new TRB for the SD/MMC cmd request.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Packet A pointer to the SD command data structure.
|
||||
@param[in] Event If Event is NULL, blocking I/O is performed. If Event is
|
||||
not NULL, then nonblocking I/O is performed, and Event
|
||||
will be signaled when the Packet completes.
|
||||
|
||||
@return Created Trb or NULL.
|
||||
|
||||
**/
|
||||
SD_MMC_HC_TRB *
|
||||
SdMmcCreateTrb (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 Slot,
|
||||
IN EFI_SD_MMC_PASS_THRU_COMMAND_PACKET *Packet,
|
||||
IN EFI_EVENT Event
|
||||
);
|
||||
|
||||
/**
|
||||
Free the resource used by the TRB.
|
||||
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SdMmcFreeTrb (
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Check if the env is ready for execute specified TRB.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
@retval EFI_SUCCESS The env is ready for TRB execution.
|
||||
@retval EFI_NOT_READY The env is not ready for TRB execution.
|
||||
@retval Others Some erros happen.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcCheckTrbEnv (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Wait for the env to be ready for execute specified TRB.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
@retval EFI_SUCCESS The env is ready for TRB execution.
|
||||
@retval EFI_TIMEOUT The env is not ready for TRB execution in time.
|
||||
@retval Others Some erros happen.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcWaitTrbEnv (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Execute the specified TRB.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
@retval EFI_SUCCESS The TRB is sent to host controller successfully.
|
||||
@retval Others Some erros happen when sending this request to the host controller.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcExecTrb (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Check the TRB execution result.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
@retval EFI_SUCCESS The TRB is executed successfully.
|
||||
@retval EFI_NOT_READY The TRB is not completed for execution.
|
||||
@retval Others Some erros happen when executing this request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcCheckTrbResult (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Wait for the TRB execution result.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Trb The pointer to the SD_MMC_HC_TRB instance.
|
||||
|
||||
@retval EFI_SUCCESS The TRB is executed successfully.
|
||||
@retval Others Some erros happen when executing this request.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcWaitTrbResult (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN SD_MMC_HC_TRB *Trb
|
||||
);
|
||||
|
||||
/**
|
||||
Execute EMMC device identification procedure.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS There is a EMMC card.
|
||||
@retval Others There is not a EMMC card.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcIdentification (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Execute EMMC device identification procedure.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
|
||||
|
||||
@param[in] Private A pointer to the SD_MMC_HC_PRIVATE_DATA instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS There is a EMMC card.
|
||||
@retval Others There is not a EMMC card.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdCardIdentification (
|
||||
IN SD_MMC_HC_PRIVATE_DATA *Private,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,72 @@
|
|||
## @file
|
||||
# SdMmcPciHcDxe driver is used to manage those host controllers which comply with SD
|
||||
# Host Controller Simplified Specifiction version 3.0.
|
||||
#
|
||||
# It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending SD/MMC/eMMC cmds
|
||||
# to specified devices from upper layer.
|
||||
#
|
||||
# Copyright (c) 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 = SdMmcPciHcDxe
|
||||
MODULE_UNI_FILE = SdMmcPciHcDxe.uni
|
||||
FILE_GUID = 8E325979-3FE1-4927-AAE2-8F5C4BD2AF0D
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = InitializeSdMmcPciHcDxe
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gSdMmcPciHcDxeDriverBinding
|
||||
# COMPONENT_NAME = gSdMmcPciHcDxeComponentName
|
||||
# COMPONENT_NAME2 = gSdMmcPciHcDxeComponentName2
|
||||
#
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SdMmcPciHcDxe.h
|
||||
SdMmcPciHcDxe.c
|
||||
EmmcDevice.c
|
||||
SdDevice.c
|
||||
SdMmcPciHci.h
|
||||
SdMmcPciHci.c
|
||||
ComponentName.c
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DevicePathLib
|
||||
UefiBootServicesTableLib
|
||||
UefiRuntimeServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
|
||||
[Protocols]
|
||||
gEfiDevicePathProtocolGuid ## TO_START
|
||||
gEfiPciIoProtocolGuid ## TO_START
|
||||
gEfiSdMmcPassThruProtocolGuid ## BY_START
|
||||
|
||||
# [Event]
|
||||
# EVENT_TYPE_PERIODIC_TIMER ## SOMETIMES_CONSUMES
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
SdMmcPciHcDxeExtra.uni
|
|
@ -0,0 +1,23 @@
|
|||
// /** @file
|
||||
// SdMmcPciHcDxe driver is used to manage those host controllers which comply with SD
|
||||
// Host Controller Simplified Specifiction version 3.0.
|
||||
//
|
||||
// It will produce EFI_SD_MMC_PASS_THRU_PROTOCOL to allow sending SD/MMC/eMMC cmds
|
||||
// to specified devices from upper layer.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "SD/MMC Pci Host Controller driver to manage SD/MMC host controllers"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This driver follows the UEFI driver model and produces SD/MMC Pass Thru protocol for upper layer bus driver."
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// /** @file
|
||||
// SdMmcPciHcDxe Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"SD/MMC Pci Host Controller Driver"
|
||||
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,546 @@
|
|||
/** @file
|
||||
|
||||
Provides some data structure definitions used by the SD/MMC host controller driver.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_MMC_PCI_HCI_H_
|
||||
#define _SD_MMC_PCI_HCI_H_
|
||||
|
||||
//
|
||||
// SD Host Controller SlotInfo Register Offset
|
||||
//
|
||||
#define SD_MMC_HC_SLOT_OFFSET 0x40
|
||||
|
||||
#define SD_MMC_HC_MAX_SLOT 6
|
||||
|
||||
//
|
||||
// SD Host Controller MMIO Register Offset
|
||||
//
|
||||
#define SD_MMC_HC_SDMA_ADDR 0x00
|
||||
#define SD_MMC_HC_ARG2 0x00
|
||||
#define SD_MMC_HC_BLK_SIZE 0x04
|
||||
#define SD_MMC_HC_BLK_COUNT 0x06
|
||||
#define SD_MMC_HC_ARG1 0x08
|
||||
#define SD_MMC_HC_TRANS_MOD 0x0C
|
||||
#define SD_MMC_HC_COMMAND 0x0E
|
||||
#define SD_MMC_HC_RESPONSE 0x10
|
||||
#define SD_MMC_HC_BUF_DAT_PORT 0x20
|
||||
#define SD_MMC_HC_PRESENT_STATE 0x24
|
||||
#define SD_MMC_HC_HOST_CTRL1 0x28
|
||||
#define SD_MMC_HC_POWER_CTRL 0x29
|
||||
#define SD_MMC_HC_BLK_GAP_CTRL 0x2A
|
||||
#define SD_MMC_HC_WAKEUP_CTRL 0x2B
|
||||
#define SD_MMC_HC_CLOCK_CTRL 0x2C
|
||||
#define SD_MMC_HC_TIMEOUT_CTRL 0x2E
|
||||
#define SD_MMC_HC_SW_RST 0x2F
|
||||
#define SD_MMC_HC_NOR_INT_STS 0x30
|
||||
#define SD_MMC_HC_ERR_INT_STS 0x32
|
||||
#define SD_MMC_HC_NOR_INT_STS_EN 0x34
|
||||
#define SD_MMC_HC_ERR_INT_STS_EN 0x36
|
||||
#define SD_MMC_HC_NOR_INT_SIG_EN 0x38
|
||||
#define SD_MMC_HC_ERR_INT_SIG_EN 0x3A
|
||||
#define SD_MMC_HC_AUTO_CMD_ERR_STS 0x3C
|
||||
#define SD_MMC_HC_HOST_CTRL2 0x3E
|
||||
#define SD_MMC_HC_CAP 0x40
|
||||
#define SD_MMC_HC_MAX_CURRENT_CAP 0x48
|
||||
#define SD_MMC_HC_FORCE_EVT_AUTO_CMD 0x50
|
||||
#define SD_MMC_HC_FORCE_EVT_ERR_INT 0x52
|
||||
#define SD_MMC_HC_ADMA_ERR_STS 0x54
|
||||
#define SD_MMC_HC_ADMA_SYS_ADDR 0x58
|
||||
#define SD_MMC_HC_PRESET_VAL 0x60
|
||||
#define SD_MMC_HC_SHARED_BUS_CTRL 0xE0
|
||||
#define SD_MMC_HC_SLOT_INT_STS 0xFC
|
||||
#define SD_MMC_HC_CTRL_VER 0xFE
|
||||
|
||||
//
|
||||
// The transfer modes supported by SD Host Controller
|
||||
// Simplified Spec 3.0 Table 1-2
|
||||
//
|
||||
typedef enum {
|
||||
SdMmcNoData,
|
||||
SdMmcPioMode,
|
||||
SdMmcSdmaMode,
|
||||
SdMmcAdmaMode
|
||||
} SD_MMC_HC_TRANSFER_MODE;
|
||||
|
||||
//
|
||||
// The maximum data length of each descriptor line
|
||||
//
|
||||
#define ADMA_MAX_DATA_PER_LINE 0x10000
|
||||
|
||||
typedef struct {
|
||||
UINT32 Valid:1;
|
||||
UINT32 End:1;
|
||||
UINT32 Int:1;
|
||||
UINT32 Reserved:1;
|
||||
UINT32 Act:2;
|
||||
UINT32 Reserved1:10;
|
||||
UINT32 Length:16;
|
||||
UINT32 Address;
|
||||
} SD_MMC_HC_ADMA_DESC_LINE;
|
||||
|
||||
#define SD_MMC_SDMA_BOUNDARY 512 * 1024
|
||||
#define SD_MMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1))
|
||||
|
||||
typedef struct {
|
||||
UINT8 FirstBar:3; // bit 0:2
|
||||
UINT8 Reserved:1; // bit 3
|
||||
UINT8 SlotNum:3; // bit 4:6
|
||||
UINT8 Reserved1:1; // bit 7
|
||||
} SD_MMC_HC_SLOT_INFO;
|
||||
|
||||
typedef struct {
|
||||
UINT32 TimeoutFreq:6; // bit 0:5
|
||||
UINT32 Reserved:1; // bit 6
|
||||
UINT32 TimeoutUnit:1; // bit 7
|
||||
UINT32 BaseClkFreq:8; // bit 8:15
|
||||
UINT32 MaxBlkLen:2; // bit 16:17
|
||||
UINT32 BusWidth8:1; // bit 18
|
||||
UINT32 Adma2:1; // bit 19
|
||||
UINT32 Reserved2:1; // bit 20
|
||||
UINT32 HighSpeed:1; // bit 21
|
||||
UINT32 Sdma:1; // bit 22
|
||||
UINT32 SuspRes:1; // bit 23
|
||||
UINT32 Voltage33:1; // bit 24
|
||||
UINT32 Voltage30:1; // bit 25
|
||||
UINT32 Voltage18:1; // bit 26
|
||||
UINT32 Reserved3:1; // bit 27
|
||||
UINT32 SysBus64:1; // bit 28
|
||||
UINT32 AsyncInt:1; // bit 29
|
||||
UINT32 SlotType:2; // bit 30:31
|
||||
UINT32 Sdr50:1; // bit 32
|
||||
UINT32 Sdr104:1; // bit 33
|
||||
UINT32 Ddr50:1; // bit 34
|
||||
UINT32 Reserved4:1; // bit 35
|
||||
UINT32 DriverTypeA:1; // bit 36
|
||||
UINT32 DriverTypeC:1; // bit 37
|
||||
UINT32 DriverTypeD:1; // bit 38
|
||||
UINT32 DriverType4:1; // bit 39
|
||||
UINT32 TimerCount:4; // bit 40:43
|
||||
UINT32 Reserved5:1; // bit 44
|
||||
UINT32 TuningSDR50:1; // bit 45
|
||||
UINT32 RetuningMod:2; // bit 46:47
|
||||
UINT32 ClkMultiplier:8; // bit 48:55
|
||||
UINT32 Reserved6:7; // bit 56:62
|
||||
UINT32 Hs400:1; // bit 63
|
||||
} SD_MMC_HC_SLOT_CAP;
|
||||
|
||||
/**
|
||||
Dump the content of SD/MMC host controller's Capability Register.
|
||||
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Capability The buffer to store the capability data.
|
||||
|
||||
**/
|
||||
VOID
|
||||
DumpCapabilityReg (
|
||||
IN UINT8 Slot,
|
||||
IN SD_MMC_HC_SLOT_CAP *Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Read SlotInfo register from SD/MMC host controller pci config space.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[out] FirstBar The buffer to store the first BAR value.
|
||||
@param[out] SlotNum The buffer to store the supported slot number.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcHcGetSlotInfo (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
OUT UINT8 *FirstBar,
|
||||
OUT UINT8 *SlotNum
|
||||
);
|
||||
|
||||
/**
|
||||
Read/Write specified SD/MMC host controller mmio register.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] BarIndex The BAR index of the standard PCI Configuration
|
||||
header to use as the base address for the memory
|
||||
operation to perform.
|
||||
@param[in] Offset The offset within the selected BAR to start the
|
||||
memory operation.
|
||||
@param[in] Read A boolean to indicate it's read or write operation.
|
||||
@param[in] Count The width of the mmio register in bytes.
|
||||
Must be 1, 2 , 4 or 8 bytes.
|
||||
@param[in, out] Data For read operations, the destination buffer to store
|
||||
the results. For write operations, the source buffer
|
||||
to write data from. The caller is responsible for
|
||||
having ownership of the data buffer and ensuring its
|
||||
size not less than Count bytes.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The PciIo or Data is NULL or the Count is not valid.
|
||||
@retval EFI_SUCCESS The read/write operation succeeds.
|
||||
@retval Others The read/write operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcHcRwMmio (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 BarIndex,
|
||||
IN UINT32 Offset,
|
||||
IN BOOLEAN Read,
|
||||
IN UINT8 Count,
|
||||
IN OUT VOID *Data
|
||||
);
|
||||
|
||||
/**
|
||||
Do OR operation with the value of the specified SD/MMC host controller mmio register.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] BarIndex The BAR index of the standard PCI Configuration
|
||||
header to use as the base address for the memory
|
||||
operation to perform.
|
||||
@param[in] Offset The offset within the selected BAR to start the
|
||||
memory operation.
|
||||
@param[in] Count The width of the mmio register in bytes.
|
||||
Must be 1, 2 , 4 or 8 bytes.
|
||||
@param[in] OrData The pointer to the data used to do OR operation.
|
||||
The caller is responsible for having ownership of
|
||||
the data buffer and ensuring its size not less than
|
||||
Count bytes.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The PciIo or OrData is NULL or the Count is not valid.
|
||||
@retval EFI_SUCCESS The OR operation succeeds.
|
||||
@retval Others The OR operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcHcOrMmio (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 BarIndex,
|
||||
IN UINT32 Offset,
|
||||
IN UINT8 Count,
|
||||
IN VOID *OrData
|
||||
);
|
||||
|
||||
/**
|
||||
Do AND operation with the value of the specified SD/MMC host controller mmio register.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] BarIndex The BAR index of the standard PCI Configuration
|
||||
header to use as the base address for the memory
|
||||
operation to perform.
|
||||
@param[in] Offset The offset within the selected BAR to start the
|
||||
memory operation.
|
||||
@param[in] Count The width of the mmio register in bytes.
|
||||
Must be 1, 2 , 4 or 8 bytes.
|
||||
@param[in] AndData The pointer to the data used to do AND operation.
|
||||
The caller is responsible for having ownership of
|
||||
the data buffer and ensuring its size not less than
|
||||
Count bytes.
|
||||
|
||||
@retval EFI_INVALID_PARAMETER The PciIo or AndData is NULL or the Count is not valid.
|
||||
@retval EFI_SUCCESS The AND operation succeeds.
|
||||
@retval Others The AND operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcHcAndMmio (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 BarIndex,
|
||||
IN UINT32 Offset,
|
||||
IN UINT8 Count,
|
||||
IN VOID *AndData
|
||||
);
|
||||
|
||||
/**
|
||||
Wait for the value of the specified MMIO register set to the test value.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] BarIndex The BAR index of the standard PCI Configuration
|
||||
header to use as the base address for the memory
|
||||
operation to perform.
|
||||
@param[in] Offset The offset within the selected BAR to start the
|
||||
memory operation.
|
||||
@param[in] Count The width of the mmio register in bytes.
|
||||
Must be 1, 2, 4 or 8 bytes.
|
||||
@param[in] MaskValue The mask value of memory.
|
||||
@param[in] TestValue The test value of memory.
|
||||
@param[in] Timeout The time out value for wait memory set, uses 1
|
||||
microsecond as a unit.
|
||||
|
||||
@retval EFI_TIMEOUT The MMIO register hasn't expected value in timeout
|
||||
range.
|
||||
@retval EFI_SUCCESS The MMIO register has expected value.
|
||||
@retval Others The MMIO operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdMmcHcWaitMmioSet (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 BarIndex,
|
||||
IN UINT32 Offset,
|
||||
IN UINT8 Count,
|
||||
IN UINT64 MaskValue,
|
||||
IN UINT64 TestValue,
|
||||
IN UINT64 Timeout
|
||||
);
|
||||
|
||||
/**
|
||||
Software reset the specified SD/MMC host controller.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS The software reset executes successfully.
|
||||
@retval Others The software reset fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcReset (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Set all interrupt status bits in Normal and Error Interrupt Status Enable
|
||||
register.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcEnableInterrupt (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Get the capability data from the specified slot.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[out] Capability The buffer to store the capability data.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcGetCapability (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
OUT SD_MMC_HC_SLOT_CAP *Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Get the maximum current capability data from the specified slot.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[out] MaxCurrent The buffer to store the maximum current capability data.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcGetMaxCurrent (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
OUT UINT64 *MaxCurrent
|
||||
);
|
||||
|
||||
/**
|
||||
Detect whether there is a SD/MMC card attached at the specified SD/MMC host controller
|
||||
slot.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[out] MediaPresent The pointer to the media present boolean value.
|
||||
|
||||
@retval EFI_SUCCESS There is no media change happened.
|
||||
@retval EFI_MEDIA_CHANGED There is media change happened.
|
||||
@retval Others The detection fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcCardDetect (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
OUT BOOLEAN *MediaPresent
|
||||
);
|
||||
|
||||
/**
|
||||
Stop SD/MMC card clock.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.2.2 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS Succeed to stop SD/MMC clock.
|
||||
@retval Others Fail to stop SD/MMC clock.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcStopClock (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
SD/MMC card clock supply.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.2.1 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] ClockFreq The max clock frequency to be set. The unit is KHz.
|
||||
@param[in] Capability The capability of the slot.
|
||||
|
||||
@retval EFI_SUCCESS The clock is supplied successfully.
|
||||
@retval Others The clock isn't supplied successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcClockSupply (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN UINT64 ClockFreq,
|
||||
IN SD_MMC_HC_SLOT_CAP Capability
|
||||
);
|
||||
|
||||
/**
|
||||
SD/MMC bus power control.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] PowerCtrl The value setting to the power control register.
|
||||
|
||||
@retval TRUE There is a SD/MMC card attached.
|
||||
@retval FALSE There is no a SD/MMC card attached.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcPowerControl (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN UINT8 PowerCtrl
|
||||
);
|
||||
|
||||
/**
|
||||
Set the SD/MMC bus width.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.4 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] BusWidth The bus width used by the SD/MMC device, it must be 1, 4 or 8.
|
||||
|
||||
@retval EFI_SUCCESS The bus width is set successfully.
|
||||
@retval Others The bus width isn't set successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcSetBusWidth (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN UINT16 BusWidth
|
||||
);
|
||||
|
||||
/**
|
||||
Supply SD/MMC card with lowest clock frequency at initialization.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Capability The capability of the slot.
|
||||
|
||||
@retval EFI_SUCCESS The clock is supplied successfully.
|
||||
@retval Others The clock isn't supplied successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcInitClockFreq (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN SD_MMC_HC_SLOT_CAP Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Supply SD/MMC card with maximum voltage at initialization.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.3 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Capability The capability of the slot.
|
||||
|
||||
@retval EFI_SUCCESS The voltage is supplied successfully.
|
||||
@retval Others The voltage isn't supplied successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcInitPowerVoltage (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN SD_MMC_HC_SLOT_CAP Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Initialize the Timeout Control register with most conservative value at initialization.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 2.2.15 for details.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS The timeout control register is configured successfully.
|
||||
@retval Others The timeout control register isn't configured successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcInitTimeoutCtrl (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Initial SD/MMC host controller with lowest clock frequency, max power and max timeout value
|
||||
at initialization.
|
||||
|
||||
@param[in] PciIo The PCI IO protocol instance.
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Capability The capability of the slot.
|
||||
|
||||
@retval EFI_SUCCESS The host controller is initialized successfully.
|
||||
@retval Others The host controller isn't initialized successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdMmcHcInitHost (
|
||||
IN EFI_PCI_IO_PROTOCOL *PciIo,
|
||||
IN UINT8 Slot,
|
||||
IN SD_MMC_HC_SLOT_CAP Capability
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,212 @@
|
|||
/** @file
|
||||
SdMmcPciHcPei driver is used to provide platform-dependent info, mainly SD/MMC
|
||||
host controller MMIO base, to upper layer SD/MMC drivers.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdMmcPciHcPei.h"
|
||||
|
||||
EDKII_SD_MMC_HOST_CONTROLLER_PPI mSdMmcHostControllerPpi = { GetSdMmcHcMmioBar };
|
||||
|
||||
EFI_PEI_PPI_DESCRIPTOR mPpiList = {
|
||||
(EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST),
|
||||
&gEdkiiPeiSdMmcHostControllerPpiGuid,
|
||||
&mSdMmcHostControllerPpi
|
||||
};
|
||||
|
||||
/**
|
||||
Get the MMIO base address of SD/MMC host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the SD/MMC host controller.
|
||||
@param[in,out] MmioBar The pointer to store the array of available
|
||||
SD/MMC host controller slot MMIO base addresses.
|
||||
The entry number of the array is specified by BarNum.
|
||||
@param[out] BarNum The pointer to store the supported bar number.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetSdMmcHcMmioBar (
|
||||
IN EDKII_SD_MMC_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
IN OUT UINTN **MmioBar,
|
||||
OUT UINT8 *BarNum
|
||||
)
|
||||
{
|
||||
SD_MMC_HC_PEI_PRIVATE_DATA *Private;
|
||||
|
||||
if ((This == NULL) || (MmioBar == NULL) || (BarNum == NULL)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Private = SD_MMC_HC_PEI_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
if (ControllerId >= Private->TotalSdMmcHcs) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
*MmioBar = &Private->MmioBar[ControllerId].MmioBarAddr[0];
|
||||
*BarNum = (UINT8)Private->MmioBar[ControllerId].SlotNum;
|
||||
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
|
||||
InitializeSdMmcHcPeim (
|
||||
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;
|
||||
UINT64 MmioSize;
|
||||
UINT8 SubClass;
|
||||
UINT8 BaseClass;
|
||||
UINT8 SlotInfo;
|
||||
UINT8 SlotNum;
|
||||
UINT8 FirstBar;
|
||||
UINT8 Index;
|
||||
UINT8 Slot;
|
||||
UINT32 BarAddr;
|
||||
SD_MMC_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 expose this in S3 boot path, because it is only for recovery.
|
||||
///
|
||||
if (BootMode == BOOT_ON_S3_RESUME) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
Private = (SD_MMC_HC_PEI_PRIVATE_DATA *) AllocateZeroPool (sizeof (SD_MMC_HC_PEI_PRIVATE_DATA));
|
||||
if (Private == NULL) {
|
||||
DEBUG ((EFI_D_ERROR, "Failed to allocate memory for SD_MMC_HC_PEI_PRIVATE_DATA! \n"));
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
Private->Signature = SD_MMC_HC_PEI_SIGNATURE;
|
||||
Private->SdMmcHostControllerPpi = mSdMmcHostControllerPpi;
|
||||
Private->PpiList = mPpiList;
|
||||
Private->PpiList.Ppi = &Private->SdMmcHostControllerPpi;
|
||||
|
||||
BarAddr = PcdGet32 (PcdSdMmcPciHostControllerMmioBase);
|
||||
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 == PCI_SUBCLASS_SD_HOST_CONTROLLER) && (BaseClass == PCI_CLASS_SYSTEM_PERIPHERAL)) {
|
||||
//
|
||||
// Get the SD/MMC Pci host controller's Slot Info.
|
||||
//
|
||||
SlotInfo = PciRead8 (PCI_LIB_ADDRESS (Bus, Device, Function, SD_MMC_HC_PEI_SLOT_OFFSET));
|
||||
FirstBar = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).FirstBar;
|
||||
SlotNum = (*(SD_MMC_HC_PEI_SLOT_INFO*)&SlotInfo).SlotNum + 1;
|
||||
ASSERT ((FirstBar + SlotNum) < MAX_SD_MMC_SLOTS);
|
||||
|
||||
for (Index = 0, Slot = FirstBar; Slot < (FirstBar + SlotNum); Index++, Slot++) {
|
||||
//
|
||||
// Get the SD/MMC 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 + 4 * Slot), 0xFFFFFFFF);
|
||||
Size = PciRead32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot));
|
||||
|
||||
switch (Size & 0x07) {
|
||||
case 0x0:
|
||||
//
|
||||
// Memory space: anywhere in 32 bit address space
|
||||
//
|
||||
MmioSize = (~(Size & 0xFFFFFFF0)) + 1;
|
||||
break;
|
||||
case 0x4:
|
||||
//
|
||||
// Memory space: anywhere in 64 bit address space
|
||||
//
|
||||
MmioSize = Size & 0xFFFFFFF0;
|
||||
PciWrite32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4), 0xFFFFFFFF);
|
||||
Size = PciRead32 (PCI_LIB_ADDRESS(Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4));
|
||||
//
|
||||
// Fix the length to support some spefic 64 bit BAR
|
||||
//
|
||||
Size |= ((UINT32)(-1) << HighBitSet32 (Size));
|
||||
//
|
||||
// Calculate the size of 64bit bar
|
||||
//
|
||||
MmioSize |= LShiftU64 ((UINT64) Size, 32);
|
||||
MmioSize = (~(MmioSize)) + 1;
|
||||
//
|
||||
// Clean the high 32bits of this 64bit BAR to 0 as we only allow a 32bit BAR.
|
||||
//
|
||||
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot + 4), 0);
|
||||
break;
|
||||
default:
|
||||
//
|
||||
// Unknown BAR type
|
||||
//
|
||||
ASSERT (FALSE);
|
||||
continue;
|
||||
};
|
||||
//
|
||||
// Assign resource to the SdMmc Pci host controller's MMIO BAR.
|
||||
// Enable the SdMmc Pci host controller by setting BME and MSE bits of PCI_CMD register.
|
||||
//
|
||||
PciWrite32 (PCI_LIB_ADDRESS (Bus, Device, Function, PCI_BASE_ADDRESSREG_OFFSET + 4 * Slot), BarAddr);
|
||||
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->MmioBar[Private->TotalSdMmcHcs].SlotNum++;
|
||||
Private->MmioBar[Private->TotalSdMmcHcs].MmioBarAddr[Index] = BarAddr;
|
||||
BarAddr += (UINT32)MmioSize;
|
||||
}
|
||||
Private->TotalSdMmcHcs++;
|
||||
ASSERT (Private->TotalSdMmcHcs < MAX_SD_MMC_HCS);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
///
|
||||
/// Install SdMmc Host Controller PPI
|
||||
///
|
||||
Status = PeiServicesInstallPpi (&Private->PpiList);
|
||||
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
return Status;
|
||||
}
|
|
@ -0,0 +1,86 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_MMC_PCI_HOST_CONTROLLER_PEI_H_
|
||||
#define _SD_MMC_PCI_HOST_CONTROLLER_PEI_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Ppi/MasterBootMode.h>
|
||||
#include <Ppi/SdMmcHostController.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 SD_MMC_HC_PEI_SIGNATURE SIGNATURE_32 ('S', 'D', 'M', 'C')
|
||||
|
||||
#define MAX_SD_MMC_HCS 8
|
||||
#define MAX_SD_MMC_SLOTS 6
|
||||
|
||||
//
|
||||
// SD Host Controller SlotInfo Register Offset
|
||||
//
|
||||
#define SD_MMC_HC_PEI_SLOT_OFFSET 0x40
|
||||
|
||||
typedef struct {
|
||||
UINT8 FirstBar:3; // bit 0:2
|
||||
UINT8 Reserved:1; // bit 3
|
||||
UINT8 SlotNum:3; // bit 4:6
|
||||
UINT8 Reserved1:1; // bit 7
|
||||
} SD_MMC_HC_PEI_SLOT_INFO;
|
||||
|
||||
typedef struct {
|
||||
UINTN SlotNum;
|
||||
UINTN MmioBarAddr[MAX_SD_MMC_SLOTS];
|
||||
} SD_MMC_HC_PEI_BAR;
|
||||
|
||||
typedef struct {
|
||||
UINTN Signature;
|
||||
EDKII_SD_MMC_HOST_CONTROLLER_PPI SdMmcHostControllerPpi;
|
||||
EFI_PEI_PPI_DESCRIPTOR PpiList;
|
||||
UINTN TotalSdMmcHcs;
|
||||
SD_MMC_HC_PEI_BAR MmioBar[MAX_SD_MMC_HCS];
|
||||
} SD_MMC_HC_PEI_PRIVATE_DATA;
|
||||
|
||||
#define SD_MMC_HC_PEI_PRIVATE_DATA_FROM_THIS(a) CR (a, SD_MMC_HC_PEI_PRIVATE_DATA, SdMmcHostControllerPpi, SD_MMC_HC_PEI_SIGNATURE)
|
||||
|
||||
/**
|
||||
Get the MMIO base address of SD/MMC host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the SD/MMC host controller.
|
||||
@param[in,out] MmioBar The pointer to store the array of available
|
||||
SD/MMC host controller slot MMIO base addresses.
|
||||
The entry number of the array is specified by BarNum.
|
||||
@param[out] BarNum The pointer to store the supported bar number.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
GetSdMmcHcMmioBar (
|
||||
IN EDKII_SD_MMC_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
IN OUT UINTN **MmioBar,
|
||||
OUT UINT8 *BarNum
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,56 @@
|
|||
## @file
|
||||
# Component Description File For SD/MMC Pci Host Controller Pei Module.
|
||||
#
|
||||
# Copyright (c) 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 = SdMmcPciHcPei
|
||||
MODULE_UNI_FILE = SdMmcPciHcPei.uni
|
||||
FILE_GUID = 1BB737EF-427A-4144-8B3B-B76EF38515E6
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InitializeSdMmcHcPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SdMmcPciHcPei.c
|
||||
SdMmcPciHcPei.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
PciLib
|
||||
DebugLib
|
||||
PeiServicesLib
|
||||
MemoryAllocationLib
|
||||
PeimEntryPoint
|
||||
|
||||
[Pcd]
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSdMmcPciHostControllerMmioBase ## CONSUMES
|
||||
|
||||
[Ppis]
|
||||
gEdkiiPeiSdMmcHostControllerPpiGuid ## PRODUCES
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMasterBootModePpiGuid AND gEfiPeiMemoryDiscoveredPpiGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
SdMmcPciHcPeiExtra.uni
|
|
@ -0,0 +1,22 @@
|
|||
// /** @file
|
||||
// The SdMmcPciHcPei driver is used by upper layer to retrieve mmio base address
|
||||
// of managed pci-based SD/MMC host controller at PEI phase.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Providing interface for upper layer to retrieve mmio base address of managed pci-based SD/MMC host controller at PEI phase."
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "It implements the interface of getting mmio base address of managed pci-based SD/MMC host controller at PEI phase."
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// SdMmcPciHcPei Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"SD/MMC PCI-Based HC Module for Recovery"
|
||||
|
||||
|
|
@ -0,0 +1,807 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "EmmcBlockIoPei.h"
|
||||
|
||||
//
|
||||
// Template for EMMC HC Slot Data.
|
||||
//
|
||||
EMMC_PEIM_HC_SLOT gEmmcHcSlotTemplate = {
|
||||
EMMC_PEIM_SLOT_SIG, // Signature
|
||||
{ // Media
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
{
|
||||
MSG_EMMC_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
}
|
||||
},
|
||||
0, // MediaNum
|
||||
{ // PartitionType
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown,
|
||||
EmmcPartitionUnknown
|
||||
},
|
||||
0, // EmmcHcBase
|
||||
{ // Capability
|
||||
0,
|
||||
},
|
||||
{ // Csd
|
||||
0,
|
||||
},
|
||||
{ // ExtCsd
|
||||
{0},
|
||||
},
|
||||
TRUE, // SectorAddressing
|
||||
NULL // Private
|
||||
};
|
||||
|
||||
//
|
||||
// Template for EMMC HC Private Data.
|
||||
//
|
||||
EMMC_PEIM_HC_PRIVATE_DATA gEmmcHcPrivateTemplate = {
|
||||
EMMC_PEIM_SIG, // Signature
|
||||
NULL, // Pool
|
||||
{ // BlkIoPpi
|
||||
EmmcBlockIoPeimGetDeviceNo,
|
||||
EmmcBlockIoPeimGetMediaInfo,
|
||||
EmmcBlockIoPeimReadBlocks
|
||||
},
|
||||
{ // BlkIo2Ppi
|
||||
EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,
|
||||
EmmcBlockIoPeimGetDeviceNo2,
|
||||
EmmcBlockIoPeimGetMediaInfo2,
|
||||
EmmcBlockIoPeimReadBlocks2
|
||||
},
|
||||
{ // BlkIoPpiList
|
||||
EFI_PEI_PPI_DESCRIPTOR_PPI,
|
||||
&gEfiPeiVirtualBlockIoPpiGuid,
|
||||
NULL
|
||||
},
|
||||
{ // BlkIo2PpiList
|
||||
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
||||
&gEfiPeiVirtualBlockIo2PpiGuid,
|
||||
NULL
|
||||
},
|
||||
{ // Slot
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
}
|
||||
},
|
||||
0, // SlotNum
|
||||
0 // TotalBlkIoDevices
|
||||
};
|
||||
/**
|
||||
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
|
||||
EmmcBlockIoPeimGetDeviceNo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
*NumberBlockDevices = Private->TotalBlkIoDevices;
|
||||
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
|
||||
EmmcBlockIoPeimGetMediaInfo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
UINT8 SlotNum;
|
||||
UINT8 MediaNum;
|
||||
UINT8 Location;
|
||||
BOOLEAN Found;
|
||||
|
||||
Found = FALSE;
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Location = 0;
|
||||
MediaNum = 0;
|
||||
for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {
|
||||
for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {
|
||||
Location ++;
|
||||
if (Location == DeviceIndex) {
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
MediaInfo->DeviceType = EMMC;
|
||||
MediaInfo->MediaPresent = TRUE;
|
||||
MediaInfo->LastBlock = (UINTN)Private->Slot[SlotNum].Media[MediaNum].LastBlock;
|
||||
MediaInfo->BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;
|
||||
|
||||
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
|
||||
EmmcBlockIoPeimReadBlocks (
|
||||
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;
|
||||
UINT32 BlockSize;
|
||||
UINTN NumberOfBlocks;
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
UINT8 SlotNum;
|
||||
UINT8 MediaNum;
|
||||
UINT8 Location;
|
||||
UINT8 PartitionConfig;
|
||||
UINTN Remaining;
|
||||
UINT32 MaxBlock;
|
||||
BOOLEAN Found;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Found = FALSE;
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Check parameters
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BufferSize == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
Location = 0;
|
||||
MediaNum = 0;
|
||||
for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {
|
||||
for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {
|
||||
Location ++;
|
||||
if (Location == DeviceIndex) {
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
BlockSize = Private->Slot[SlotNum].Media[MediaNum].BlockSize;
|
||||
if (BufferSize % BlockSize != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (StartLBA > Private->Slot[SlotNum].Media[MediaNum].LastBlock) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NumberOfBlocks = BufferSize / BlockSize;
|
||||
|
||||
//
|
||||
// Check if needs to switch partition access.
|
||||
//
|
||||
PartitionConfig = Private->Slot[SlotNum].ExtCsd.PartitionConfig;
|
||||
if ((PartitionConfig & 0x7) != Private->Slot[SlotNum].PartitionType[MediaNum]) {
|
||||
PartitionConfig &= (UINT8)~0x7;
|
||||
PartitionConfig |= Private->Slot[SlotNum].PartitionType[MediaNum];
|
||||
Status = EmmcPeimSwitch (
|
||||
&Private->Slot[SlotNum],
|
||||
0x3,
|
||||
OFFSET_OF (EMMC_EXT_CSD, PartitionConfig),
|
||||
PartitionConfig,
|
||||
0x0
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
Private->Slot[SlotNum].ExtCsd.PartitionConfig = PartitionConfig;
|
||||
}
|
||||
//
|
||||
// Start to execute data transfer. The max block number in single cmd is 65535 blocks.
|
||||
//
|
||||
Remaining = NumberOfBlocks;
|
||||
MaxBlock = 0xFFFF;
|
||||
|
||||
while (Remaining > 0) {
|
||||
if (Remaining <= MaxBlock) {
|
||||
NumberOfBlocks = Remaining;
|
||||
} else {
|
||||
NumberOfBlocks = MaxBlock;
|
||||
}
|
||||
|
||||
Status = EmmcPeimSetBlkCount (&Private->Slot[SlotNum], (UINT16)NumberOfBlocks);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
BufferSize = NumberOfBlocks * BlockSize;
|
||||
Status = EmmcPeimRwMultiBlocks (&Private->Slot[SlotNum], StartLBA, BlockSize, Buffer, BufferSize, TRUE);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
StartLBA += NumberOfBlocks;
|
||||
Buffer = (UINT8*)Buffer + BufferSize;
|
||||
Remaining -= NumberOfBlocks;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
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_IO2_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcBlockIoPeimGetDeviceNo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
*NumberBlockDevices = Private->TotalBlkIoDevices;
|
||||
|
||||
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_IO2_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
|
||||
EmmcBlockIoPeimGetMediaInfo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EFI_PEI_BLOCK_IO_MEDIA Media;
|
||||
UINT8 SlotNum;
|
||||
UINT8 MediaNum;
|
||||
UINT8 Location;
|
||||
BOOLEAN Found;
|
||||
|
||||
Found = FALSE;
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
|
||||
Status = EmmcBlockIoPeimGetMediaInfo (
|
||||
PeiServices,
|
||||
&Private->BlkIoPpi,
|
||||
DeviceIndex,
|
||||
&Media
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
Location = 0;
|
||||
MediaNum = 0;
|
||||
for (SlotNum = 0; SlotNum < Private->SlotNum; SlotNum++) {
|
||||
for (MediaNum = 0; MediaNum < Private->Slot[SlotNum].MediaNum; MediaNum++) {
|
||||
Location ++;
|
||||
if (Location == DeviceIndex) {
|
||||
Found = TRUE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (Found) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
CopyMem (MediaInfo, &(Private->Slot[SlotNum].Media[MediaNum]), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));
|
||||
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_IO2_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
|
||||
EmmcBlockIoPeimReadBlocks2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
IN EFI_PEI_LBA StartLBA,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Private = GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
|
||||
Status = EmmcBlockIoPeimReadBlocks (
|
||||
PeiServices,
|
||||
&Private->BlkIoPpi,
|
||||
DeviceIndex,
|
||||
StartLBA,
|
||||
BufferSize,
|
||||
Buffer
|
||||
);
|
||||
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
|
||||
InitializeEmmcBlockIoPeim (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;
|
||||
UINT32 Index;
|
||||
UINT32 PartitionIndex;
|
||||
UINTN *MmioBase;
|
||||
UINT8 BarNum;
|
||||
UINT8 SlotNum;
|
||||
UINT8 MediaNum;
|
||||
UINT8 Controller;
|
||||
UINT64 Capacity;
|
||||
EMMC_EXT_CSD *ExtCsd;
|
||||
EMMC_HC_SLOT_CAP Capability;
|
||||
EMMC_PEIM_HC_SLOT *Slot;
|
||||
UINT32 SecCount;
|
||||
UINT32 GpSizeMult;
|
||||
|
||||
//
|
||||
// Shadow this PEIM to run from memory
|
||||
//
|
||||
if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// locate Emmc host controller PPI
|
||||
//
|
||||
Status = PeiServicesLocatePpi (
|
||||
&gEdkiiPeiSdMmcHostControllerPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **) &SdMmcHcPpi
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Controller = 0;
|
||||
MmioBase = NULL;
|
||||
while (TRUE) {
|
||||
Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);
|
||||
//
|
||||
// When status is error, meant no controller is found
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (BarNum == 0) {
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Private = AllocateCopyPool (sizeof (EMMC_PEIM_HC_PRIVATE_DATA), &gEmmcHcPrivateTemplate);
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
Private->BlkIoPpiList.Ppi = (VOID*)&Private->BlkIoPpi;
|
||||
Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;
|
||||
//
|
||||
// Initialize the memory pool which will be used in all transactions.
|
||||
//
|
||||
Status = EmmcPeimInitMemPool (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < BarNum; Index++) {
|
||||
Status = EmmcPeimHcGetCapability (MmioBase[Index], &Capability);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
if (Capability.SlotType != 0x1) {
|
||||
DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = EmmcPeimHcReset (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
Status = EmmcPeimHcCardDetect (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
Status = EmmcPeimHcInitHost (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SlotNum = Private->SlotNum;
|
||||
Slot = &Private->Slot[SlotNum];
|
||||
CopyMem (Slot, &gEmmcHcSlotTemplate, sizeof (EMMC_PEIM_HC_SLOT));
|
||||
Slot->Private = Private;
|
||||
Slot->EmmcHcBase = MmioBase[Index];
|
||||
CopyMem (&Slot->Capability, &Capability, sizeof (Capability));
|
||||
|
||||
Status = EmmcPeimIdentification (Slot);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
ExtCsd = &Slot->ExtCsd;
|
||||
if (ExtCsd->ExtCsdRev < 5) {
|
||||
DEBUG ((EFI_D_ERROR, "The EMMC device version is too low, we don't support!!!\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
continue;
|
||||
}
|
||||
if ((ExtCsd->PartitioningSupport & BIT0) != BIT0) {
|
||||
DEBUG ((EFI_D_ERROR, "The EMMC device doesn't support Partition Feature!!!\n"));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
for (PartitionIndex = 0; PartitionIndex < EMMC_PEIM_MAX_PARTITIONS; PartitionIndex++) {
|
||||
switch (PartitionIndex) {
|
||||
case EmmcPartitionUserData:
|
||||
SecCount = *(UINT32*)&ExtCsd->SecCount;
|
||||
Capacity = MultU64x32 ((UINT64)SecCount, 0x200);
|
||||
break;
|
||||
case EmmcPartitionBoot1:
|
||||
case EmmcPartitionBoot2:
|
||||
Capacity = ExtCsd->BootSizeMult * SIZE_128KB;
|
||||
break;
|
||||
case EmmcPartitionRPMB:
|
||||
Capacity = ExtCsd->RpmbSizeMult * SIZE_128KB;
|
||||
break;
|
||||
case EmmcPartitionGP1:
|
||||
GpSizeMult = (ExtCsd->GpSizeMult[0] | (ExtCsd->GpSizeMult[1] << 8) | (ExtCsd->GpSizeMult[2] << 16));
|
||||
Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
|
||||
break;
|
||||
case EmmcPartitionGP2:
|
||||
GpSizeMult = (ExtCsd->GpSizeMult[3] | (ExtCsd->GpSizeMult[4] << 8) | (ExtCsd->GpSizeMult[5] << 16));
|
||||
Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
|
||||
break;
|
||||
case EmmcPartitionGP3:
|
||||
GpSizeMult = (ExtCsd->GpSizeMult[6] | (ExtCsd->GpSizeMult[7] << 8) | (ExtCsd->GpSizeMult[8] << 16));
|
||||
Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
|
||||
break;
|
||||
case EmmcPartitionGP4:
|
||||
GpSizeMult = (ExtCsd->GpSizeMult[9] | (ExtCsd->GpSizeMult[10] << 8) | (ExtCsd->GpSizeMult[11] << 16));
|
||||
Capacity = MultU64x32 (MultU64x32 (MultU64x32 ((UINT64)GpSizeMult, ExtCsd->HcWpGrpSize), ExtCsd->HcEraseGrpSize), SIZE_512KB);
|
||||
break;
|
||||
default:
|
||||
ASSERT (FALSE);
|
||||
continue;
|
||||
}
|
||||
|
||||
MediaNum = Slot->MediaNum;
|
||||
if (Capacity != 0) {
|
||||
Slot->Media[MediaNum].LastBlock = DivU64x32 (Capacity, Slot->Media[MediaNum].BlockSize) - 1;
|
||||
Slot->PartitionType[MediaNum] = PartitionIndex;
|
||||
Private->TotalBlkIoDevices++;
|
||||
Slot->MediaNum++;
|
||||
}
|
||||
}
|
||||
Private->SlotNum++;
|
||||
}
|
||||
Controller++;
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
PeiServicesInstallPpi (&Private->BlkIoPpiList);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,381 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EMMC_BLOCK_IO_PEI_H_
|
||||
#define _EMMC_BLOCK_IO_PEI_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Ppi/SdMmcHostController.h>
|
||||
#include <Ppi/BlockIo.h>
|
||||
#include <Ppi/BlockIo2.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/Emmc.h>
|
||||
|
||||
typedef struct _EMMC_PEIM_HC_PRIVATE_DATA EMMC_PEIM_HC_PRIVATE_DATA;
|
||||
typedef struct _EMMC_PEIM_HC_SLOT EMMC_PEIM_HC_SLOT;
|
||||
typedef struct _EMMC_TRB EMMC_TRB;
|
||||
|
||||
#include "EmmcHci.h"
|
||||
#include "EmmcHcMem.h"
|
||||
|
||||
#define EMMC_PEIM_SIG SIGNATURE_32 ('E', 'M', 'C', 'P')
|
||||
#define EMMC_PEIM_SLOT_SIG SIGNATURE_32 ('E', 'M', 'C', 'S')
|
||||
|
||||
#define EMMC_PEIM_MAX_SLOTS 6
|
||||
#define EMMC_PEIM_MAX_PARTITIONS 8
|
||||
|
||||
struct _EMMC_PEIM_HC_SLOT {
|
||||
UINT32 Signature;
|
||||
EFI_PEI_BLOCK_IO2_MEDIA Media[EMMC_PEIM_MAX_PARTITIONS];
|
||||
UINT8 MediaNum;
|
||||
EMMC_PARTITION_TYPE PartitionType[EMMC_PEIM_MAX_PARTITIONS];
|
||||
|
||||
UINTN EmmcHcBase;
|
||||
EMMC_HC_SLOT_CAP Capability;
|
||||
EMMC_CSD Csd;
|
||||
EMMC_EXT_CSD ExtCsd;
|
||||
BOOLEAN SectorAddressing;
|
||||
EMMC_PEIM_HC_PRIVATE_DATA *Private;
|
||||
};
|
||||
|
||||
struct _EMMC_PEIM_HC_PRIVATE_DATA {
|
||||
UINT32 Signature;
|
||||
EMMC_PEIM_MEM_POOL *Pool;
|
||||
EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;
|
||||
EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi;
|
||||
EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;
|
||||
EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList;
|
||||
EMMC_PEIM_HC_SLOT Slot[EMMC_PEIM_MAX_SLOTS];
|
||||
UINT8 SlotNum;
|
||||
UINT8 TotalBlkIoDevices;
|
||||
};
|
||||
|
||||
#define EMMC_TIMEOUT MultU64x32((UINT64)(3), 1000000)
|
||||
#define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, EMMC_PEIM_HC_PRIVATE_DATA, BlkIoPpi, EMMC_PEIM_SIG)
|
||||
#define GET_EMMC_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, EMMC_PEIM_HC_PRIVATE_DATA, BlkIo2Ppi, EMMC_PEIM_SIG)
|
||||
|
||||
struct _EMMC_TRB {
|
||||
EMMC_PEIM_HC_SLOT *Slot;
|
||||
UINT16 BlockSize;
|
||||
|
||||
EMMC_COMMAND_PACKET *Packet;
|
||||
VOID *Data;
|
||||
UINT32 DataLen;
|
||||
BOOLEAN Read;
|
||||
EMMC_HC_TRANSFER_MODE Mode;
|
||||
|
||||
UINT64 Timeout;
|
||||
|
||||
EMMC_HC_ADMA_DESC_LINE *AdmaDesc;
|
||||
UINTN AdmaDescSize;
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
EmmcBlockIoPeimGetDeviceNo (
|
||||
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
|
||||
EmmcBlockIoPeimGetMediaInfo (
|
||||
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
|
||||
EmmcBlockIoPeimReadBlocks (
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
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_IO2_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcBlockIoPeimGetDeviceNo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_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_IO2_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
|
||||
EmmcBlockIoPeimGetMediaInfo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO2_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_IO2_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
|
||||
EmmcBlockIoPeimReadBlocks2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_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 Emmc Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimInitMemPool (
|
||||
IN EMMC_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 *
|
||||
EmmcPeimAllocateMem (
|
||||
IN EMMC_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
|
||||
EmmcPeimFreeMem (
|
||||
IN EMMC_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
## @file
|
||||
# Description file for the Embedded MMC (eMMC) Peim driver.
|
||||
#
|
||||
# Copyright (c) 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 = EmmcBlockIoPei
|
||||
MODULE_UNI_FILE = EmmcBlockIoPei.uni
|
||||
FILE_GUID = 7F06A90F-AE0D-4887-82C0-FEC7F4F68B29
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InitializeEmmcBlockIoPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
EmmcBlockIoPei.c
|
||||
EmmcBlockIoPei.h
|
||||
EmmcHci.c
|
||||
EmmcHci.h
|
||||
EmmcHcMem.c
|
||||
EmmcHcMem.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
IoLib
|
||||
TimerLib
|
||||
BaseMemoryLib
|
||||
PeimEntryPoint
|
||||
PeiServicesLib
|
||||
DebugLib
|
||||
|
||||
[Ppis]
|
||||
gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES
|
||||
gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES
|
||||
gEdkiiPeiSdMmcHostControllerPpiGuid ## CONSUMES
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiSdMmcHostControllerPpiGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
EmmcBlockIoPeiExtra.uni
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// The EmmcBlockIoPei driver is used to support recovery from EMMC device.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Support recovery from EMMC devices"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "The EmmcBlockIoPei driver is used to support recovery from EMMC device."
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// EmmcBlockIoPei Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"EMMC BlockIo Peim for Recovery"
|
||||
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "EmmcBlockIoPei.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.
|
||||
|
||||
**/
|
||||
EMMC_PEIM_MEM_BLOCK *
|
||||
EmmcPeimAllocMemBlock (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_MEM_BLOCK *Block;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
|
||||
TempPtr = NULL;
|
||||
Block = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof(EMMC_PEIM_MEM_BLOCK), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof(EMMC_PEIM_MEM_BLOCK));
|
||||
|
||||
//
|
||||
// each bit in the bit array represents EMMC_PEIM_MEM_UNIT
|
||||
// bytes of memory in the memory block.
|
||||
//
|
||||
ASSERT (EMMC_PEIM_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
|
||||
|
||||
Block = (EMMC_PEIM_MEM_BLOCK*)(UINTN)TempPtr;
|
||||
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
|
||||
Block->BitsLen = Block->BufLen / (EMMC_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
|
||||
EmmcPeimFreeMemBlock (
|
||||
IN EMMC_PEIM_MEM_POOL *Pool,
|
||||
IN EMMC_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 *
|
||||
EmmcPeimAllocMemFromBlock (
|
||||
IN EMMC_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 (!EMMC_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit)) {
|
||||
Available++;
|
||||
|
||||
if (Available >= Units) {
|
||||
break;
|
||||
}
|
||||
|
||||
EMMC_PEIM_NEXT_BIT (Byte, Bit);
|
||||
|
||||
} else {
|
||||
EMMC_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 (!EMMC_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) EMMC_PEIM_MEM_BIT (Bit));
|
||||
EMMC_PEIM_NEXT_BIT (Byte, Bit);
|
||||
}
|
||||
|
||||
return Block->Buf + (StartByte * 8 + StartBit) * EMMC_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
|
||||
EmmcPeimInsertMemBlockToPool (
|
||||
IN EMMC_PEIM_MEM_BLOCK *Head,
|
||||
IN EMMC_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
|
||||
EmmcPeimIsMemBlockEmpty (
|
||||
IN EMMC_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
|
||||
EmmcPeimUnlinkMemBlock (
|
||||
IN EMMC_PEIM_MEM_BLOCK *Head,
|
||||
IN EMMC_PEIM_MEM_BLOCK *BlockToUnlink
|
||||
)
|
||||
{
|
||||
EMMC_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 Emmc Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimInitMemPool (
|
||||
IN EMMC_PEIM_HC_PRIVATE_DATA *Private
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_MEM_POOL *Pool;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
|
||||
TempPtr = NULL;
|
||||
Pool = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof (EMMC_PEIM_MEM_POOL), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof (EMMC_PEIM_MEM_POOL));
|
||||
|
||||
Pool = (EMMC_PEIM_MEM_POOL *)((UINTN)TempPtr);
|
||||
|
||||
Pool->Head = EmmcPeimAllocMemBlock (EMMC_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
|
||||
EmmcPeimFreeMemPool (
|
||||
IN EMMC_PEIM_MEM_POOL *Pool
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_MEM_BLOCK *Block;
|
||||
|
||||
ASSERT (Pool->Head != NULL);
|
||||
|
||||
//
|
||||
// Unlink all the memory blocks from the pool, then free them.
|
||||
// EmmcPeimUnlinkMemBlock can't be used to unlink and free the
|
||||
// first block.
|
||||
//
|
||||
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
|
||||
EmmcPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
EmmcPeimFreeMemBlock (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 *
|
||||
EmmcPeimAllocateMem (
|
||||
IN EMMC_PEIM_MEM_POOL *Pool,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_MEM_BLOCK *Head;
|
||||
EMMC_PEIM_MEM_BLOCK *Block;
|
||||
EMMC_PEIM_MEM_BLOCK *NewBlock;
|
||||
VOID *Mem;
|
||||
UINTN AllocSize;
|
||||
UINTN Pages;
|
||||
|
||||
Mem = NULL;
|
||||
AllocSize = EMMC_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 = EmmcPeimAllocMemFromBlock (Block, AllocSize / EMMC_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 (EMMC_PEIM_MEM_DEFAULT_PAGES)) {
|
||||
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
|
||||
} else {
|
||||
Pages = EMMC_PEIM_MEM_DEFAULT_PAGES;
|
||||
}
|
||||
|
||||
NewBlock = EmmcPeimAllocMemBlock (Pages);
|
||||
if (NewBlock == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the new memory block to the pool, then allocate memory from it
|
||||
//
|
||||
EmmcPeimInsertMemBlockToPool (Head, NewBlock);
|
||||
Mem = EmmcPeimAllocMemFromBlock (NewBlock, AllocSize / EMMC_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
|
||||
EmmcPeimFreeMem (
|
||||
IN EMMC_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
EMMC_PEIM_MEM_BLOCK *Head;
|
||||
EMMC_PEIM_MEM_BLOCK *Block;
|
||||
UINT8 *ToFree;
|
||||
UINTN AllocSize;
|
||||
UINTN Byte;
|
||||
UINTN Bit;
|
||||
UINTN Count;
|
||||
|
||||
Head = Pool->Head;
|
||||
AllocSize = EMMC_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) / EMMC_PEIM_MEM_UNIT) / 8;
|
||||
Bit = ((ToFree - Block->Buf) / EMMC_PEIM_MEM_UNIT) % 8;
|
||||
|
||||
//
|
||||
// reset associated bits in bit arry
|
||||
//
|
||||
for (Count = 0; Count < (AllocSize / EMMC_PEIM_MEM_UNIT); Count++) {
|
||||
ASSERT (EMMC_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ EMMC_PEIM_MEM_BIT (Bit));
|
||||
EMMC_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) && EmmcPeimIsMemBlockEmpty (Block)) {
|
||||
EmmcPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EMMC_PEIM_MEM_H_
|
||||
#define _EMMC_PEIM_MEM_H_
|
||||
|
||||
#define EMMC_PEIM_MEM_BIT(a) ((UINTN)(1 << (a)))
|
||||
|
||||
#define EMMC_PEIM_MEM_BIT_IS_SET(Data, Bit) \
|
||||
((BOOLEAN)(((Data) & EMMC_PEIM_MEM_BIT(Bit)) == EMMC_PEIM_MEM_BIT(Bit)))
|
||||
|
||||
typedef struct _EMMC_PEIM_MEM_BLOCK EMMC_PEIM_MEM_BLOCK;
|
||||
|
||||
struct _EMMC_PEIM_MEM_BLOCK {
|
||||
UINT8 *Bits; // Bit array to record which unit is allocated
|
||||
UINTN BitsLen;
|
||||
UINT8 *Buf;
|
||||
UINTN BufLen; // Memory size in bytes
|
||||
EMMC_PEIM_MEM_BLOCK *Next;
|
||||
};
|
||||
|
||||
typedef struct _EMMC_PEIM_MEM_POOL {
|
||||
EMMC_PEIM_MEM_BLOCK *Head;
|
||||
} EMMC_PEIM_MEM_POOL;
|
||||
|
||||
//
|
||||
// Memory allocation unit, note that the value must meet EMMC spec alignment requirement.
|
||||
//
|
||||
#define EMMC_PEIM_MEM_UNIT 128
|
||||
|
||||
#define EMMC_PEIM_MEM_UNIT_MASK (EMMC_PEIM_MEM_UNIT - 1)
|
||||
#define EMMC_PEIM_MEM_DEFAULT_PAGES 16
|
||||
|
||||
#define EMMC_PEIM_MEM_ROUND(Len) (((Len) + EMMC_PEIM_MEM_UNIT_MASK) & (~EMMC_PEIM_MEM_UNIT_MASK))
|
||||
|
||||
//
|
||||
// Advance the byte and bit to the next bit, adjust byte accordingly.
|
||||
//
|
||||
#define EMMC_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
|
@ -0,0 +1,345 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EMMC_HCI_H_
|
||||
#define _EMMC_HCI_H_
|
||||
|
||||
//
|
||||
// EMMC Host Controller MMIO Register Offset
|
||||
//
|
||||
#define EMMC_HC_SDMA_ADDR 0x00
|
||||
#define EMMC_HC_ARG2 0x00
|
||||
#define EMMC_HC_BLK_SIZE 0x04
|
||||
#define EMMC_HC_BLK_COUNT 0x06
|
||||
#define EMMC_HC_ARG1 0x08
|
||||
#define EMMC_HC_TRANS_MOD 0x0C
|
||||
#define EMMC_HC_COMMAND 0x0E
|
||||
#define EMMC_HC_RESPONSE 0x10
|
||||
#define EMMC_HC_BUF_DAT_PORT 0x20
|
||||
#define EMMC_HC_PRESENT_STATE 0x24
|
||||
#define EMMC_HC_HOST_CTRL1 0x28
|
||||
#define EMMC_HC_POWER_CTRL 0x29
|
||||
#define EMMC_HC_BLK_GAP_CTRL 0x2A
|
||||
#define EMMC_HC_WAKEUP_CTRL 0x2B
|
||||
#define EMMC_HC_CLOCK_CTRL 0x2C
|
||||
#define EMMC_HC_TIMEOUT_CTRL 0x2E
|
||||
#define EMMC_HC_SW_RST 0x2F
|
||||
#define EMMC_HC_NOR_INT_STS 0x30
|
||||
#define EMMC_HC_ERR_INT_STS 0x32
|
||||
#define EMMC_HC_NOR_INT_STS_EN 0x34
|
||||
#define EMMC_HC_ERR_INT_STS_EN 0x36
|
||||
#define EMMC_HC_NOR_INT_SIG_EN 0x38
|
||||
#define EMMC_HC_ERR_INT_SIG_EN 0x3A
|
||||
#define EMMC_HC_AUTO_CMD_ERR_STS 0x3C
|
||||
#define EMMC_HC_HOST_CTRL2 0x3E
|
||||
#define EMMC_HC_CAP 0x40
|
||||
#define EMMC_HC_MAX_CURRENT_CAP 0x48
|
||||
#define EMMC_HC_FORCE_EVT_AUTO_CMD 0x50
|
||||
#define EMMC_HC_FORCE_EVT_ERR_INT 0x52
|
||||
#define EMMC_HC_ADMA_ERR_STS 0x54
|
||||
#define EMMC_HC_ADMA_SYS_ADDR 0x58
|
||||
#define EMMC_HC_PRESET_VAL 0x60
|
||||
#define EMMC_HC_SHARED_BUS_CTRL 0xE0
|
||||
#define EMMC_HC_SLOT_INT_STS 0xFC
|
||||
#define EMMC_HC_CTRL_VER 0xFE
|
||||
|
||||
//
|
||||
// The transfer modes supported by SD Host Controller
|
||||
// Simplified Spec 3.0 Table 1-2
|
||||
//
|
||||
typedef enum {
|
||||
EmmcNoData,
|
||||
EmmcPioMode,
|
||||
EmmcSdmaMode,
|
||||
EmmcAdmaMode
|
||||
} EMMC_HC_TRANSFER_MODE;
|
||||
|
||||
//
|
||||
// The maximum data length of each descriptor line
|
||||
//
|
||||
#define ADMA_MAX_DATA_PER_LINE 0x10000
|
||||
#define EMMC_SDMA_BOUNDARY 512 * 1024
|
||||
#define EMMC_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1))
|
||||
|
||||
typedef enum {
|
||||
EmmcCommandTypeBc, // Broadcast commands, no response
|
||||
EmmcCommandTypeBcr, // Broadcast commands with response
|
||||
EmmcCommandTypeAc, // Addressed(point-to-point) commands
|
||||
EmmcCommandTypeAdtc // Addressed(point-to-point) data transfer commands
|
||||
} EMMC_COMMAND_TYPE;
|
||||
|
||||
typedef enum {
|
||||
EmmcResponceTypeR1,
|
||||
EmmcResponceTypeR1b,
|
||||
EmmcResponceTypeR2,
|
||||
EmmcResponceTypeR3,
|
||||
EmmcResponceTypeR4,
|
||||
EmmcResponceTypeR5,
|
||||
EmmcResponceTypeR5b,
|
||||
EmmcResponceTypeR6,
|
||||
EmmcResponceTypeR7
|
||||
} EMMC_RESPONSE_TYPE;
|
||||
|
||||
typedef struct _EMMC_COMMAND_BLOCK {
|
||||
UINT16 CommandIndex;
|
||||
UINT32 CommandArgument;
|
||||
UINT32 CommandType; // One of the EMMC_COMMAND_TYPE values
|
||||
UINT32 ResponseType; // One of the EMMC_RESPONSE_TYPE values
|
||||
} EMMC_COMMAND_BLOCK;
|
||||
|
||||
typedef struct _EMMC_STATUS_BLOCK {
|
||||
UINT32 Resp0;
|
||||
UINT32 Resp1;
|
||||
UINT32 Resp2;
|
||||
UINT32 Resp3;
|
||||
} EMMC_STATUS_BLOCK;
|
||||
|
||||
typedef struct _EMMC_COMMAND_PACKET {
|
||||
UINT64 Timeout;
|
||||
EMMC_COMMAND_BLOCK *EmmcCmdBlk;
|
||||
EMMC_STATUS_BLOCK *EmmcStatusBlk;
|
||||
VOID *InDataBuffer;
|
||||
VOID *OutDataBuffer;
|
||||
UINT32 InTransferLength;
|
||||
UINT32 OutTransferLength;
|
||||
} EMMC_COMMAND_PACKET;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct {
|
||||
UINT32 Valid:1;
|
||||
UINT32 End:1;
|
||||
UINT32 Int:1;
|
||||
UINT32 Reserved:1;
|
||||
UINT32 Act:2;
|
||||
UINT32 Reserved1:10;
|
||||
UINT32 Length:16;
|
||||
UINT32 Address;
|
||||
} EMMC_HC_ADMA_DESC_LINE;
|
||||
|
||||
typedef struct {
|
||||
UINT32 TimeoutFreq:6; // bit 0:5
|
||||
UINT32 Reserved:1; // bit 6
|
||||
UINT32 TimeoutUnit:1; // bit 7
|
||||
UINT32 BaseClkFreq:8; // bit 8:15
|
||||
UINT32 MaxBlkLen:2; // bit 16:17
|
||||
UINT32 BusWidth8:1; // bit 18
|
||||
UINT32 Adma2:1; // bit 19
|
||||
UINT32 Reserved2:1; // bit 20
|
||||
UINT32 HighSpeed:1; // bit 21
|
||||
UINT32 Sdma:1; // bit 22
|
||||
UINT32 SuspRes:1; // bit 23
|
||||
UINT32 Voltage33:1; // bit 24
|
||||
UINT32 Voltage30:1; // bit 25
|
||||
UINT32 Voltage18:1; // bit 26
|
||||
UINT32 Reserved3:1; // bit 27
|
||||
UINT32 SysBus64:1; // bit 28
|
||||
UINT32 AsyncInt:1; // bit 29
|
||||
UINT32 SlotType:2; // bit 30:31
|
||||
UINT32 Sdr50:1; // bit 32
|
||||
UINT32 Sdr104:1; // bit 33
|
||||
UINT32 Ddr50:1; // bit 34
|
||||
UINT32 Reserved4:1; // bit 35
|
||||
UINT32 DriverTypeA:1; // bit 36
|
||||
UINT32 DriverTypeC:1; // bit 37
|
||||
UINT32 DriverTypeD:1; // bit 38
|
||||
UINT32 DriverType4:1; // bit 39
|
||||
UINT32 TimerCount:4; // bit 40:43
|
||||
UINT32 Reserved5:1; // bit 44
|
||||
UINT32 TuningSDR50:1; // bit 45
|
||||
UINT32 RetuningMod:2; // bit 46:47
|
||||
UINT32 ClkMultiplier:8; // bit 48:55
|
||||
UINT32 Reserved6:7; // bit 56:62
|
||||
UINT32 Hs400:1; // bit 63
|
||||
} EMMC_HC_SLOT_CAP;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
Software reset the specified EMMC host controller and enable all interrupts.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The software reset executes successfully.
|
||||
@retval Others The software reset fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimHcReset (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Set all interrupt status bits in Normal and Error Interrupt Status Enable
|
||||
register.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimHcEnableInterrupt (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Get the capability data from the specified slot.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
@param[out] Capability The buffer to store the capability data.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimHcGetCapability (
|
||||
IN UINTN Bar,
|
||||
OUT EMMC_HC_SLOT_CAP *Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Detect whether there is a EMMC card attached at the specified EMMC host controller
|
||||
slot.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS There is a EMMC card attached.
|
||||
@retval EFI_NO_MEDIA There is not a EMMC card attached.
|
||||
@retval Others The detection fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimHcCardDetect (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Initial EMMC host controller with lowest clock frequency, max power and max timeout value
|
||||
at initialization.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The host controller is initialized successfully.
|
||||
@retval Others The host controller isn't initialized successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimHcInitHost (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SWITCH to the EMMC device to switch the mode of operation of the
|
||||
selected Device or modifies the EXT_CSD registers.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Emmc card to send the command to.
|
||||
@param[in] Access The access mode of SWTICH command.
|
||||
@param[in] Index The offset of the field to be access.
|
||||
@param[in] Value The value to be set to the specified field of EXT_CSD register.
|
||||
@param[in] CmdSet The value of CmdSet field of EXT_CSD register.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimSwitch (
|
||||
IN EMMC_PEIM_HC_SLOT *Slot,
|
||||
IN UINT8 Access,
|
||||
IN UINT8 Index,
|
||||
IN UINT8 Value,
|
||||
IN UINT8 CmdSet
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SET_BLOCK_COUNT to the addressed EMMC device to set the number of
|
||||
blocks for the following block read/write cmd.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Emmc card to send the command to.
|
||||
@param[in] BlockCount The number of the logical block to access.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimSetBlkCount (
|
||||
IN EMMC_PEIM_HC_SLOT *Slot,
|
||||
IN UINT16 BlockCount
|
||||
);
|
||||
|
||||
/**
|
||||
Send command READ_MULTIPLE_BLOCK/WRITE_MULTIPLE_BLOCK to the addressed EMMC device
|
||||
to read/write the specified number of blocks.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.10.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Emmc card to send the command to.
|
||||
@param[in] Lba The logical block address of starting access.
|
||||
@param[in] BlockSize The block size of specified EMMC device partition.
|
||||
@param[in] Buffer The pointer to the transfer buffer.
|
||||
@param[in] BufferSize The size of transfer buffer.
|
||||
@param[in] IsRead Boolean to show the operation direction.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimRwMultiBlocks (
|
||||
IN EMMC_PEIM_HC_SLOT *Slot,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINT32 BlockSize,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead
|
||||
);
|
||||
|
||||
/**
|
||||
Execute EMMC device identification procedure.
|
||||
|
||||
Refer to EMMC Electrical Standard Spec 5.1 Section 6.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Emmc card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS There is a EMMC card.
|
||||
@retval Others There is not a EMMC card.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcPeimIdentification (
|
||||
IN EMMC_PEIM_HC_SLOT *Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Free the resource used by the TRB.
|
||||
|
||||
@param[in] Trb The pointer to the EMMC_TRB instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EmmcPeimFreeTrb (
|
||||
IN EMMC_TRB *Trb
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,241 @@
|
|||
/** @file
|
||||
UEFI Component Name(2) protocol implementation for EmmcDxe driver.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "EmmcDxe.h"
|
||||
|
||||
//
|
||||
// Driver name table
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mEmmcDxeDriverNameTable[] = {
|
||||
{ "eng;en", L"Edkii Emmc Device Driver" },
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// Controller name table
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mEmmcDxeControllerNameTable[] = {
|
||||
{ "eng;en", L"Edkii Emmc Host Controller" },
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gEmmcDxeComponentName = {
|
||||
EmmcDxeComponentNameGetDriverName,
|
||||
EmmcDxeComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gEmmcDxeComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) EmmcDxeComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) EmmcDxeComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
EmmcDxeComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mEmmcDxeDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gEmmcDxeComponentName)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
EmmcDxeComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
EMMC_DEVICE *Device;
|
||||
EMMC_PARTITION *Partition;
|
||||
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
|
||||
|
||||
//
|
||||
// Make sure this driver is currently managing ControllHandle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gEmmcDxeDriverBinding.DriverBindingHandle,
|
||||
&gEfiSdMmcPassThruProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ControllerNameTable = mEmmcDxeControllerNameTable;
|
||||
if (ChildHandle != NULL) {
|
||||
Status = EfiTestChildHandle (
|
||||
ControllerHandle,
|
||||
ChildHandle,
|
||||
&gEfiSdMmcPassThruProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get the child context
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlockIo,
|
||||
gEmmcDxeDriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Partition = EMMC_PARTITION_DATA_FROM_BLKIO (BlockIo);
|
||||
Device = Partition->Device;
|
||||
ControllerNameTable = Device->ControllerNameTable;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
ControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gEmmcDxeComponentName)
|
||||
);}
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,466 @@
|
|||
/** @file
|
||||
Header file for EmmcDxe Driver.
|
||||
|
||||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EMMC_BLOCK_IO_H_
|
||||
#define _EMMC_BLOCK_IO_H_
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit 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 performing the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the write request is for.
|
||||
@param Lba The starting logical block address to be written. The caller is
|
||||
responsible for writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Event is not NULL.
|
||||
The data was read correctly from the device if
|
||||
the Event is NULL.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing
|
||||
the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
);
|
||||
|
||||
/**
|
||||
Send a security protocol command to a device that receives data and/or the result
|
||||
of one or more commands sent by SendData.
|
||||
|
||||
The ReceiveData function sends a security protocol command to the given MediaId.
|
||||
The security protocol command sent is defined by SecurityProtocolId and contains
|
||||
the security protocol specific data SecurityProtocolSpecificData. The function
|
||||
returns the data from the security protocol command in PayloadBuffer.
|
||||
|
||||
For devices supporting the SCSI command set, the security protocol command is sent
|
||||
using the SECURITY PROTOCOL IN command defined in SPC-4.
|
||||
|
||||
For devices supporting the ATA command set, the security protocol command is sent
|
||||
using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
|
||||
is non-zero.
|
||||
|
||||
If the PayloadBufferSize is zero, the security protocol command is sent using the
|
||||
Trusted Non-Data command defined in ATA8-ACS.
|
||||
|
||||
If PayloadBufferSize is too small to store the available data from the security
|
||||
protocol command, the function shall copy PayloadBufferSize bytes into the
|
||||
PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
|
||||
|
||||
If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
|
||||
the function shall return EFI_INVALID_PARAMETER.
|
||||
|
||||
If the given MediaId does not support security protocol commands, the function shall
|
||||
return EFI_UNSUPPORTED. If there is no media in the device, the function returns
|
||||
EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
|
||||
the function returns EFI_MEDIA_CHANGED.
|
||||
|
||||
If the security protocol fails to complete within the Timeout period, the function
|
||||
shall return EFI_TIMEOUT.
|
||||
|
||||
If the security protocol command completes without an error, the function shall
|
||||
return EFI_SUCCESS. If the security protocol command completes with an error, the
|
||||
function shall return EFI_DEVICE_ERROR.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId ID of the medium to receive data from.
|
||||
@param[in] Timeout The timeout, in 100ns units, to use for the execution
|
||||
of the security protocol command. A Timeout value of 0
|
||||
means that this function will wait indefinitely for the
|
||||
security protocol command to execute. If Timeout is greater
|
||||
than zero, then this function will return EFI_TIMEOUT
|
||||
if the time required to execute the receive data command
|
||||
is greater than Timeout.
|
||||
@param[in] SecurityProtocolId The value of the "Security Protocol" parameter of
|
||||
the security protocol command to be sent.
|
||||
@param[in] SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
|
||||
of the security protocol command to be sent.
|
||||
@param[in] PayloadBufferSize Size in bytes of the payload data buffer.
|
||||
@param[out] PayloadBuffer A pointer to a destination buffer to store the security
|
||||
protocol command specific payload data for the security
|
||||
protocol command. The caller is responsible for having
|
||||
either implicit or explicit ownership of the buffer.
|
||||
@param[out] PayloadTransferSize A pointer to a buffer to store the size in bytes of the
|
||||
data written to the payload data buffer.
|
||||
@param[in] IsRead Indicates it is a read or write operation.
|
||||
|
||||
@retval EFI_SUCCESS The security protocol command completed successfully.
|
||||
@retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
|
||||
data from the device. The PayloadBuffer contains the truncated data.
|
||||
@retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
|
||||
@retval EFI_DEVICE_ERROR The security protocol command completed with an error.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
|
||||
PayloadBufferSize is non-zero.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the security
|
||||
protocol command to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcSecurityProtocolInOut (
|
||||
IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN UINT64 Timeout,
|
||||
IN UINT8 SecurityProtocolId,
|
||||
IN UINT16 SecurityProtocolSpecificData,
|
||||
IN UINTN PayloadBufferSize,
|
||||
OUT VOID *PayloadBuffer,
|
||||
OUT UINTN *PayloadTransferSize,
|
||||
IN BOOLEAN IsRead
|
||||
);
|
||||
|
||||
/**
|
||||
Send a security protocol command to a device that receives data and/or the result
|
||||
of one or more commands sent by SendData.
|
||||
|
||||
The ReceiveData function sends a security protocol command to the given MediaId.
|
||||
The security protocol command sent is defined by SecurityProtocolId and contains
|
||||
the security protocol specific data SecurityProtocolSpecificData. The function
|
||||
returns the data from the security protocol command in PayloadBuffer.
|
||||
|
||||
For devices supporting the SCSI command set, the security protocol command is sent
|
||||
using the SECURITY PROTOCOL IN command defined in SPC-4.
|
||||
|
||||
For devices supporting the ATA command set, the security protocol command is sent
|
||||
using one of the TRUSTED RECEIVE commands defined in ATA8-ACS if PayloadBufferSize
|
||||
is non-zero.
|
||||
|
||||
If the PayloadBufferSize is zero, the security protocol command is sent using the
|
||||
Trusted Non-Data command defined in ATA8-ACS.
|
||||
|
||||
If PayloadBufferSize is too small to store the available data from the security
|
||||
protocol command, the function shall copy PayloadBufferSize bytes into the
|
||||
PayloadBuffer and return EFI_WARN_BUFFER_TOO_SMALL.
|
||||
|
||||
If PayloadBuffer or PayloadTransferSize is NULL and PayloadBufferSize is non-zero,
|
||||
the function shall return EFI_INVALID_PARAMETER.
|
||||
|
||||
If the given MediaId does not support security protocol commands, the function shall
|
||||
return EFI_UNSUPPORTED. If there is no media in the device, the function returns
|
||||
EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the device,
|
||||
the function returns EFI_MEDIA_CHANGED.
|
||||
|
||||
If the security protocol fails to complete within the Timeout period, the function
|
||||
shall return EFI_TIMEOUT.
|
||||
|
||||
If the security protocol command completes without an error, the function shall
|
||||
return EFI_SUCCESS. If the security protocol command completes with an error, the
|
||||
function shall return EFI_DEVICE_ERROR.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId ID of the medium to receive data from.
|
||||
@param Timeout The timeout, in 100ns units, to use for the execution
|
||||
of the security protocol command. A Timeout value of 0
|
||||
means that this function will wait indefinitely for the
|
||||
security protocol command to execute. If Timeout is greater
|
||||
than zero, then this function will return EFI_TIMEOUT
|
||||
if the time required to execute the receive data command
|
||||
is greater than Timeout.
|
||||
@param SecurityProtocolId The value of the "Security Protocol" parameter of
|
||||
the security protocol command to be sent.
|
||||
@param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
|
||||
of the security protocol command to be sent.
|
||||
@param PayloadBufferSize Size in bytes of the payload data buffer.
|
||||
@param PayloadBuffer A pointer to a destination buffer to store the security
|
||||
protocol command specific payload data for the security
|
||||
protocol command. The caller is responsible for having
|
||||
either implicit or explicit ownership of the buffer.
|
||||
@param PayloadTransferSize A pointer to a buffer to store the size in bytes of the
|
||||
data written to the payload data buffer.
|
||||
|
||||
@retval EFI_SUCCESS The security protocol command completed successfully.
|
||||
@retval EFI_WARN_BUFFER_TOO_SMALL The PayloadBufferSize was too small to store the available
|
||||
data from the device. The PayloadBuffer contains the truncated data.
|
||||
@retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
|
||||
@retval EFI_DEVICE_ERROR The security protocol command completed with an error.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_INVALID_PARAMETER The PayloadBuffer or PayloadTransferSize is NULL and
|
||||
PayloadBufferSize is non-zero.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the security
|
||||
protocol command to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcSecurityProtocolIn (
|
||||
IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN UINT64 Timeout,
|
||||
IN UINT8 SecurityProtocolId,
|
||||
IN UINT16 SecurityProtocolSpecificData,
|
||||
IN UINTN PayloadBufferSize,
|
||||
OUT VOID *PayloadBuffer,
|
||||
OUT UINTN *PayloadTransferSize
|
||||
);
|
||||
|
||||
/**
|
||||
Send a security protocol command to a device.
|
||||
|
||||
The SendData function sends a security protocol command containing the payload
|
||||
PayloadBuffer to the given MediaId. The security protocol command sent is
|
||||
defined by SecurityProtocolId and contains the security protocol specific data
|
||||
SecurityProtocolSpecificData. If the underlying protocol command requires a
|
||||
specific padding for the command payload, the SendData function shall add padding
|
||||
bytes to the command payload to satisfy the padding requirements.
|
||||
|
||||
For devices supporting the SCSI command set, the security protocol command is sent
|
||||
using the SECURITY PROTOCOL OUT command defined in SPC-4.
|
||||
|
||||
For devices supporting the ATA command set, the security protocol command is sent
|
||||
using one of the TRUSTED SEND commands defined in ATA8-ACS if PayloadBufferSize
|
||||
is non-zero. If the PayloadBufferSize is zero, the security protocol command is
|
||||
sent using the Trusted Non-Data command defined in ATA8-ACS.
|
||||
|
||||
If PayloadBuffer is NULL and PayloadBufferSize is non-zero, the function shall
|
||||
return EFI_INVALID_PARAMETER.
|
||||
|
||||
If the given MediaId does not support security protocol commands, the function
|
||||
shall return EFI_UNSUPPORTED. If there is no media in the device, the function
|
||||
returns EFI_NO_MEDIA. If the MediaId is not the ID for the current media in the
|
||||
device, the function returns EFI_MEDIA_CHANGED.
|
||||
|
||||
If the security protocol fails to complete within the Timeout period, the function
|
||||
shall return EFI_TIMEOUT.
|
||||
|
||||
If the security protocol command completes without an error, the function shall return
|
||||
EFI_SUCCESS. If the security protocol command completes with an error, the function
|
||||
shall return EFI_DEVICE_ERROR.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId ID of the medium to receive data from.
|
||||
@param Timeout The timeout, in 100ns units, to use for the execution
|
||||
of the security protocol command. A Timeout value of 0
|
||||
means that this function will wait indefinitely for the
|
||||
security protocol command to execute. If Timeout is greater
|
||||
than zero, then this function will return EFI_TIMEOUT
|
||||
if the time required to execute the receive data command
|
||||
is greater than Timeout.
|
||||
@param SecurityProtocolId The value of the "Security Protocol" parameter of
|
||||
the security protocol command to be sent.
|
||||
@param SecurityProtocolSpecificData The value of the "Security Protocol Specific" parameter
|
||||
of the security protocol command to be sent.
|
||||
@param PayloadBufferSize Size in bytes of the payload data buffer.
|
||||
@param PayloadBuffer A pointer to a destination buffer to store the security
|
||||
protocol command specific payload data for the security
|
||||
protocol command.
|
||||
|
||||
@retval EFI_SUCCESS The security protocol command completed successfully.
|
||||
@retval EFI_UNSUPPORTED The given MediaId does not support security protocol commands.
|
||||
@retval EFI_DEVICE_ERROR The security protocol command completed with an error.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_INVALID_PARAMETER The PayloadBuffer is NULL and PayloadBufferSize is non-zero.
|
||||
@retval EFI_TIMEOUT A timeout occurred while waiting for the security
|
||||
protocol command to execute.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
EmmcSecurityProtocolOut (
|
||||
IN EFI_STORAGE_SECURITY_COMMAND_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN UINT64 Timeout,
|
||||
IN UINT8 SecurityProtocolId,
|
||||
IN UINT16 SecurityProtocolSpecificData,
|
||||
IN UINTN PayloadBufferSize,
|
||||
IN VOID *PayloadBuffer
|
||||
);
|
||||
|
||||
#endif
|
||||
|
File diff suppressed because it is too large
Load Diff
|
@ -0,0 +1,495 @@
|
|||
/** @file
|
||||
Header file for EmmcDxe Driver.
|
||||
|
||||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EMMC_DXE_H_
|
||||
#define _EMMC_DXE_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <IndustryStandard/Emmc.h>
|
||||
|
||||
#include <Protocol/SdMmcPassThru.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
#include <Protocol/StorageSecurityCommand.h>
|
||||
|
||||
#include <Protocol/DevicePath.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/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include "EmmcBlockIo.h"
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gEmmcDxeDriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gEmmcDxeComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gEmmcDxeComponentName2;
|
||||
|
||||
#define EMMC_PARTITION_SIGNATURE SIGNATURE_32 ('E', 'm', 'm', 'P')
|
||||
|
||||
#define EMMC_PARTITION_DATA_FROM_BLKIO(a) \
|
||||
CR(a, EMMC_PARTITION, BlockIo, EMMC_PARTITION_SIGNATURE)
|
||||
|
||||
#define EMMC_PARTITION_DATA_FROM_BLKIO2(a) \
|
||||
CR(a, EMMC_PARTITION, BlockIo2, EMMC_PARTITION_SIGNATURE)
|
||||
|
||||
#define EMMC_PARTITION_DATA_FROM_SSP(a) \
|
||||
CR(a, EMMC_PARTITION, StorageSecurity, EMMC_PARTITION_SIGNATURE)
|
||||
|
||||
//
|
||||
// Take 2.5 seconds as generic time out value, 1 microsecond as unit.
|
||||
//
|
||||
#define EMMC_GENERIC_TIMEOUT 2500 * 1000
|
||||
|
||||
#define EMMC_REQUEST_SIGNATURE SIGNATURE_32 ('E', 'm', 'R', 'e')
|
||||
|
||||
typedef struct _EMMC_DEVICE EMMC_DEVICE;
|
||||
typedef struct _EMMC_DRIVER_PRIVATE_DATA EMMC_DRIVER_PRIVATE_DATA;
|
||||
|
||||
//
|
||||
// Asynchronous I/O request.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
BOOLEAN IsEnd;
|
||||
|
||||
EFI_BLOCK_IO2_TOKEN *Token;
|
||||
EFI_EVENT Event;
|
||||
} EMMC_REQUEST;
|
||||
|
||||
#define EMMC_REQUEST_FROM_LINK(a) \
|
||||
CR(a, EMMC_REQUEST, Link, EMMC_REQUEST_SIGNATURE)
|
||||
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
BOOLEAN Enable;
|
||||
EMMC_PARTITION_TYPE PartitionType;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA BlockMedia;
|
||||
EFI_STORAGE_SECURITY_COMMAND_PROTOCOL StorageSecurity;
|
||||
|
||||
LIST_ENTRY Queue;
|
||||
|
||||
EMMC_DEVICE *Device;
|
||||
} EMMC_PARTITION;
|
||||
|
||||
//
|
||||
// Up to 6 slots per EMMC PCI host controller
|
||||
//
|
||||
#define EMMC_MAX_DEVICES 6
|
||||
//
|
||||
// Up to 8 partitions per EMMC device.
|
||||
//
|
||||
#define EMMC_MAX_PARTITIONS 8
|
||||
#define EMMC_MODEL_NAME_MAX_LEN 32
|
||||
|
||||
struct _EMMC_DEVICE {
|
||||
EFI_HANDLE Handle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
UINT8 Slot;
|
||||
BOOLEAN SectorAddressing;
|
||||
|
||||
EMMC_PARTITION Partition[EMMC_MAX_PARTITIONS];
|
||||
EMMC_CSD Csd;
|
||||
EMMC_CID Cid;
|
||||
EMMC_EXT_CSD ExtCsd;
|
||||
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
|
||||
//
|
||||
// The model name consists of three fields in CID register
|
||||
// 1) OEM/Application ID (2 bytes)
|
||||
// 2) Product Name (5 bytes)
|
||||
// 3) Product Serial Number (4 bytes)
|
||||
// The delimiters of these fields are whitespace.
|
||||
//
|
||||
CHAR16 ModelName[EMMC_MODEL_NAME_MAX_LEN];
|
||||
EMMC_DRIVER_PRIVATE_DATA *Private;
|
||||
} ;
|
||||
|
||||
//
|
||||
// EMMC DXE driver private data structure
|
||||
//
|
||||
struct _EMMC_DRIVER_PRIVATE_DATA {
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_HANDLE Controller;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
EFI_HANDLE DriverBindingHandle;
|
||||
|
||||
EMMC_DEVICE Device[EMMC_MAX_DEVICES];
|
||||
} ;
|
||||
|
||||
/**
|
||||
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
|
||||
EmmcDxeDriverBindingSupported (
|
||||
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
|
||||
EmmcDxeDriverBindingStart (
|
||||
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
|
||||
EmmcDxeDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
EmmcDxeComponentNameGetDriverName (
|
||||
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
|
||||
EmmcDxeComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SELECT to the device to select/deselect the device.
|
||||
|
||||
@param[in] Device A pointer to the EMMC_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcSelect (
|
||||
IN EMMC_DEVICE *Device,
|
||||
IN UINT16 Rca
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_STATUS to the device to get device status.
|
||||
|
||||
@param[in] Device A pointer to the EMMC_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] DevStatus The buffer to store the device status.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcSendStatus (
|
||||
IN EMMC_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT UINT32 *DevStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_CSD to the device to get the CSD register data.
|
||||
|
||||
@param[in] Device A pointer to the EMMC_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Csd The buffer to store the EMMC_CSD register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcGetCsd (
|
||||
IN EMMC_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT EMMC_CSD *Csd
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_CID to the device to get the CID register data.
|
||||
|
||||
@param[in] Device A pointer to the EMMC_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Csd The buffer to store the EMMC_CSD register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcGetCid (
|
||||
IN EMMC_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT EMMC_CID *Cid
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_EXT_CSD to the device to get the EXT_CSD register data.
|
||||
|
||||
@param[in] Device A pointer to the EMMC_DEVICE instance.
|
||||
@param[out] ExtCsd The buffer to store the EXT_CSD register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EmmcGetExtCsd (
|
||||
IN EMMC_DEVICE *Device,
|
||||
OUT EMMC_EXT_CSD *ExtCsd
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,66 @@
|
|||
## @file
|
||||
# EmmcDxe driver is used to manage the EMMC device.
|
||||
#
|
||||
# It produces BlockIo, BlockIo2 and StorageSecurity protocols to allow upper layer
|
||||
# access the EMMC device.
|
||||
#
|
||||
# Copyright (c) 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 = EmmcDxe
|
||||
MODULE_UNI_FILE = EmmcDxe.uni
|
||||
FILE_GUID = 2145F72F-E6F1-4440-A828-59DC9AAB5F89
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = InitializeEmmcDxe
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gEmmcDxeDriverBinding
|
||||
# COMPONENT_NAME = gEmmcDxeComponentName
|
||||
# COMPONENT_NAME2 = gEmmcDxeComponentName2
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
ComponentName.c
|
||||
EmmcDxe.c
|
||||
EmmcDxe.h
|
||||
EmmcBlockIo.c
|
||||
EmmcBlockIo.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DevicePathLib
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSdMmcPassThruProtocolGuid ## TO_START
|
||||
gEfiBlockIoProtocolGuid ## BY_START
|
||||
gEfiBlockIo2ProtocolGuid ## BY_START
|
||||
gEfiStorageSecurityCommandProtocolGuid ## SOMETIMES_PRODUCES
|
||||
## TO_START
|
||||
## BY_START
|
||||
gEfiDevicePathProtocolGuid
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// /** @file
|
||||
// EMMC device driver to manage the EMMC device and provide interface for upper layer
|
||||
// access.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "EMMC device driver to manage the EMMC device and provide interface for upper layer access"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This driver follows the UEFI driver model and layers on the SdMmcPassThru protocol. It installs BlockIo/BlockIo2/StorageSecurity protocols for the EMMC device partitions."
|
||||
|
|
@ -0,0 +1,19 @@
|
|||
// /** @file
|
||||
// EmmcDxe Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"EMMC Device Driver"
|
||||
|
||||
|
|
@ -0,0 +1,617 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdBlockIoPei.h"
|
||||
|
||||
//
|
||||
// Template for SD HC Slot Data.
|
||||
//
|
||||
SD_PEIM_HC_SLOT gSdHcSlotTemplate = {
|
||||
SD_PEIM_SLOT_SIG, // Signature
|
||||
{ // Media
|
||||
MSG_SD_DP,
|
||||
FALSE,
|
||||
TRUE,
|
||||
FALSE,
|
||||
0x200,
|
||||
0
|
||||
},
|
||||
0, // SdHcBase
|
||||
{ // Capability
|
||||
0,
|
||||
},
|
||||
{ // Csd
|
||||
0,
|
||||
},
|
||||
TRUE, // SectorAddressing
|
||||
NULL // Private
|
||||
};
|
||||
|
||||
//
|
||||
// Template for SD HC Private Data.
|
||||
//
|
||||
SD_PEIM_HC_PRIVATE_DATA gSdHcPrivateTemplate = {
|
||||
SD_PEIM_SIG, // Signature
|
||||
NULL, // Pool
|
||||
{ // BlkIoPpi
|
||||
SdBlockIoPeimGetDeviceNo,
|
||||
SdBlockIoPeimGetMediaInfo,
|
||||
SdBlockIoPeimReadBlocks
|
||||
},
|
||||
{ // BlkIo2Ppi
|
||||
EFI_PEI_RECOVERY_BLOCK_IO2_PPI_REVISION,
|
||||
SdBlockIoPeimGetDeviceNo2,
|
||||
SdBlockIoPeimGetMediaInfo2,
|
||||
SdBlockIoPeimReadBlocks2
|
||||
},
|
||||
{ // BlkIoPpiList
|
||||
EFI_PEI_PPI_DESCRIPTOR_PPI,
|
||||
&gEfiPeiVirtualBlockIoPpiGuid,
|
||||
NULL
|
||||
},
|
||||
{ // BlkIo2PpiList
|
||||
EFI_PEI_PPI_DESCRIPTOR_PPI | EFI_PEI_PPI_DESCRIPTOR_TERMINATE_LIST,
|
||||
&gEfiPeiVirtualBlockIo2PpiGuid,
|
||||
NULL
|
||||
},
|
||||
{ // Slot
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
},
|
||||
{
|
||||
0,
|
||||
}
|
||||
},
|
||||
0, // SlotNum
|
||||
0 // TotalBlkIoDevices
|
||||
};
|
||||
/**
|
||||
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
|
||||
SdBlockIoPeimGetDeviceNo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
)
|
||||
{
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
*NumberBlockDevices = Private->TotalBlkIoDevices;
|
||||
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
|
||||
SdBlockIoPeimGetMediaInfo (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO_MEDIA *MediaInfo
|
||||
)
|
||||
{
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
MediaInfo->DeviceType = SD;
|
||||
MediaInfo->MediaPresent = TRUE;
|
||||
MediaInfo->LastBlock = (UINTN)Private->Slot[DeviceIndex - 1].Media.LastBlock;
|
||||
MediaInfo->BlockSize = Private->Slot[DeviceIndex - 1].Media.BlockSize;
|
||||
|
||||
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
|
||||
SdBlockIoPeimReadBlocks (
|
||||
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;
|
||||
UINT32 BlockSize;
|
||||
UINTN NumberOfBlocks;
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
UINTN Remaining;
|
||||
UINT32 MaxBlock;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS (This);
|
||||
|
||||
//
|
||||
// Check parameters
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BufferSize == 0) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if ((DeviceIndex == 0) || (DeviceIndex > Private->TotalBlkIoDevices)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
BlockSize = Private->Slot[DeviceIndex - 1].Media.BlockSize;
|
||||
if (BufferSize % BlockSize != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
if (StartLBA > Private->Slot[DeviceIndex - 1].Media.LastBlock) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
NumberOfBlocks = BufferSize / BlockSize;
|
||||
|
||||
//
|
||||
// Start to execute data transfer. The max block number in single cmd is 65535 blocks.
|
||||
//
|
||||
Remaining = NumberOfBlocks;
|
||||
MaxBlock = 0xFFFF;
|
||||
|
||||
while (Remaining > 0) {
|
||||
if (Remaining <= MaxBlock) {
|
||||
NumberOfBlocks = Remaining;
|
||||
} else {
|
||||
NumberOfBlocks = MaxBlock;
|
||||
}
|
||||
|
||||
BufferSize = NumberOfBlocks * BlockSize;
|
||||
if (NumberOfBlocks != 1) {
|
||||
Status = SdPeimRwMultiBlocks (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);
|
||||
} else {
|
||||
Status = SdPeimRwSingleBlock (&Private->Slot[DeviceIndex - 1], StartLBA, BlockSize, Buffer, BufferSize, TRUE);
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
StartLBA += NumberOfBlocks;
|
||||
Buffer = (UINT8*)Buffer + BufferSize;
|
||||
Remaining -= NumberOfBlocks;
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
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_IO2_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdBlockIoPeimGetDeviceNo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
OUT UINTN *NumberBlockDevices
|
||||
)
|
||||
{
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
*NumberBlockDevices = Private->TotalBlkIoDevices;
|
||||
|
||||
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_IO2_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
|
||||
SdBlockIoPeimGetMediaInfo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO2_MEDIA *MediaInfo
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EFI_PEI_BLOCK_IO_MEDIA Media;
|
||||
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
|
||||
Status = SdBlockIoPeimGetMediaInfo (
|
||||
PeiServices,
|
||||
&Private->BlkIoPpi,
|
||||
DeviceIndex,
|
||||
&Media
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
CopyMem (MediaInfo, &(Private->Slot[DeviceIndex - 1].Media), sizeof (EFI_PEI_BLOCK_IO2_MEDIA));
|
||||
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_IO2_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
|
||||
SdBlockIoPeimReadBlocks2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
IN EFI_PEI_LBA StartLBA,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Private = GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2 (This);
|
||||
|
||||
Status = SdBlockIoPeimReadBlocks (
|
||||
PeiServices,
|
||||
&Private->BlkIoPpi,
|
||||
DeviceIndex,
|
||||
StartLBA,
|
||||
BufferSize,
|
||||
Buffer
|
||||
);
|
||||
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
|
||||
InitializeSdBlockIoPeim (
|
||||
IN EFI_PEI_FILE_HANDLE FileHandle,
|
||||
IN CONST EFI_PEI_SERVICES **PeiServices
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
EDKII_SD_MMC_HOST_CONTROLLER_PPI *SdMmcHcPpi;
|
||||
UINT32 Index;
|
||||
UINTN *MmioBase;
|
||||
UINT8 BarNum;
|
||||
UINT8 SlotNum;
|
||||
UINT8 Controller;
|
||||
UINT64 Capacity;
|
||||
SD_HC_SLOT_CAP Capability;
|
||||
SD_PEIM_HC_SLOT *Slot;
|
||||
SD_CSD *Csd;
|
||||
SD_CSD2 *Csd2;
|
||||
UINT32 CSize;
|
||||
UINT32 CSizeMul;
|
||||
UINT32 ReadBlLen;
|
||||
|
||||
//
|
||||
// Shadow this PEIM to run from memory
|
||||
//
|
||||
if (!EFI_ERROR (PeiServicesRegisterForShadow (FileHandle))) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// locate Sd host controller PPI
|
||||
//
|
||||
Status = PeiServicesLocatePpi (
|
||||
&gEdkiiPeiSdMmcHostControllerPpiGuid,
|
||||
0,
|
||||
NULL,
|
||||
(VOID **) &SdMmcHcPpi
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
Controller = 0;
|
||||
MmioBase = NULL;
|
||||
while (TRUE) {
|
||||
Status = SdMmcHcPpi->GetSdMmcHcMmioBar (SdMmcHcPpi, Controller, &MmioBase, &BarNum);
|
||||
//
|
||||
// When status is error, meant no controller is found
|
||||
//
|
||||
if (EFI_ERROR (Status)) {
|
||||
break;
|
||||
}
|
||||
|
||||
if (BarNum == 0) {
|
||||
Controller++;
|
||||
continue;
|
||||
}
|
||||
|
||||
Private = AllocateCopyPool (sizeof (SD_PEIM_HC_PRIVATE_DATA), &gSdHcPrivateTemplate);
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
Private->BlkIoPpiList.Ppi = (VOID*)&Private->BlkIoPpi;
|
||||
Private->BlkIo2PpiList.Ppi = (VOID*)&Private->BlkIo2Ppi;
|
||||
//
|
||||
// Initialize the memory pool which will be used in all transactions.
|
||||
//
|
||||
Status = SdPeimInitMemPool (Private);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
break;
|
||||
}
|
||||
|
||||
for (Index = 0; Index < BarNum; Index++) {
|
||||
Status = SdPeimHcGetCapability (MmioBase[Index], &Capability);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
if (Capability.SlotType != 0x1) {
|
||||
DEBUG ((EFI_D_INFO, "The slot at 0x%x is not embedded slot type\n", MmioBase[Index]));
|
||||
Status = EFI_UNSUPPORTED;
|
||||
continue;
|
||||
}
|
||||
|
||||
Status = SdPeimHcReset (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
Status = SdPeimHcCardDetect (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
Status = SdPeimHcInitHost (MmioBase[Index]);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
SlotNum = Private->SlotNum;
|
||||
Slot = &Private->Slot[SlotNum];
|
||||
CopyMem (Slot, &gSdHcSlotTemplate, sizeof (SD_PEIM_HC_SLOT));
|
||||
Slot->Private = Private;
|
||||
Slot->SdHcBase = MmioBase[Index];
|
||||
CopyMem (&Slot->Capability, &Capability, sizeof (Capability));
|
||||
|
||||
Status = SdPeimIdentification (Slot);
|
||||
if (EFI_ERROR (Status)) {
|
||||
continue;
|
||||
}
|
||||
|
||||
Csd = &Slot->Csd;
|
||||
if (Csd->CsdStructure == 0) {
|
||||
Slot->SectorAddressing = FALSE;
|
||||
CSize = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;
|
||||
CSizeMul = (1 << (Csd->CSizeMul + 2));
|
||||
ReadBlLen = (1 << (Csd->ReadBlLen));
|
||||
Capacity = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);
|
||||
} else {
|
||||
Slot->SectorAddressing = TRUE;
|
||||
Csd2 = (SD_CSD2*)(VOID*)Csd;
|
||||
CSize = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;
|
||||
Capacity = MultU64x32 ((UINT64)CSize, SIZE_512KB);
|
||||
}
|
||||
|
||||
Slot->Media.LastBlock = DivU64x32 (Capacity, Slot->Media.BlockSize) - 1;
|
||||
|
||||
Private->TotalBlkIoDevices++;
|
||||
Private->SlotNum++;
|
||||
}
|
||||
|
||||
Controller++;
|
||||
if (!EFI_ERROR (Status)) {
|
||||
PeiServicesInstallPpi (&Private->BlkIoPpiList);
|
||||
}
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
|
@ -0,0 +1,377 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_BLOCK_IO_PEI_H_
|
||||
#define _SD_BLOCK_IO_PEI_H_
|
||||
|
||||
#include <PiPei.h>
|
||||
|
||||
#include <Ppi/SdMmcHostController.h>
|
||||
#include <Ppi/BlockIo.h>
|
||||
#include <Ppi/BlockIo2.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/Sd.h>
|
||||
|
||||
typedef struct _SD_PEIM_HC_PRIVATE_DATA SD_PEIM_HC_PRIVATE_DATA;
|
||||
typedef struct _SD_PEIM_HC_SLOT SD_PEIM_HC_SLOT;
|
||||
typedef struct _SD_TRB SD_TRB;
|
||||
|
||||
#include "SdHci.h"
|
||||
#include "SdHcMem.h"
|
||||
|
||||
#define SD_PEIM_SIG SIGNATURE_32 ('S', 'D', 'C', 'P')
|
||||
#define SD_PEIM_SLOT_SIG SIGNATURE_32 ('S', 'D', 'C', 'S')
|
||||
|
||||
#define SD_PEIM_MAX_SLOTS 6
|
||||
|
||||
struct _SD_PEIM_HC_SLOT {
|
||||
UINT32 Signature;
|
||||
EFI_PEI_BLOCK_IO2_MEDIA Media;
|
||||
|
||||
UINTN SdHcBase;
|
||||
SD_HC_SLOT_CAP Capability;
|
||||
SD_CSD Csd;
|
||||
BOOLEAN SectorAddressing;
|
||||
SD_PEIM_HC_PRIVATE_DATA *Private;
|
||||
};
|
||||
|
||||
struct _SD_PEIM_HC_PRIVATE_DATA {
|
||||
UINT32 Signature;
|
||||
SD_PEIM_MEM_POOL *Pool;
|
||||
EFI_PEI_RECOVERY_BLOCK_IO_PPI BlkIoPpi;
|
||||
EFI_PEI_RECOVERY_BLOCK_IO2_PPI BlkIo2Ppi;
|
||||
EFI_PEI_PPI_DESCRIPTOR BlkIoPpiList;
|
||||
EFI_PEI_PPI_DESCRIPTOR BlkIo2PpiList;
|
||||
SD_PEIM_HC_SLOT Slot[SD_PEIM_MAX_SLOTS];
|
||||
UINT8 SlotNum;
|
||||
UINT8 TotalBlkIoDevices;
|
||||
};
|
||||
|
||||
#define SD_TIMEOUT MultU64x32((UINT64)(3), 1000000)
|
||||
#define GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS(a) CR (a, SD_PEIM_HC_PRIVATE_DATA, BlkIoPpi, SD_PEIM_SIG)
|
||||
#define GET_SD_PEIM_HC_PRIVATE_DATA_FROM_THIS2(a) CR (a, SD_PEIM_HC_PRIVATE_DATA, BlkIo2Ppi, SD_PEIM_SIG)
|
||||
|
||||
struct _SD_TRB {
|
||||
SD_PEIM_HC_SLOT *Slot;
|
||||
UINT16 BlockSize;
|
||||
|
||||
SD_COMMAND_PACKET *Packet;
|
||||
VOID *Data;
|
||||
UINT32 DataLen;
|
||||
BOOLEAN Read;
|
||||
SD_HC_TRANSFER_MODE Mode;
|
||||
|
||||
UINT64 Timeout;
|
||||
|
||||
SD_HC_ADMA_DESC_LINE *AdmaDesc;
|
||||
UINTN AdmaDescSize;
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
SdBlockIoPeimGetDeviceNo (
|
||||
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
|
||||
SdBlockIoPeimGetMediaInfo (
|
||||
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
|
||||
SdBlockIoPeimReadBlocks (
|
||||
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
|
||||
);
|
||||
|
||||
/**
|
||||
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_IO2_PPI
|
||||
instance.
|
||||
@param[out] NumberBlockDevices The number of block I/O devices discovered.
|
||||
|
||||
@retval EFI_SUCCESS The operation performed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdBlockIoPeimGetDeviceNo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_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_IO2_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
|
||||
SdBlockIoPeimGetMediaInfo2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_PPI *This,
|
||||
IN UINTN DeviceIndex,
|
||||
OUT EFI_PEI_BLOCK_IO2_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_IO2_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
|
||||
SdBlockIoPeimReadBlocks2 (
|
||||
IN EFI_PEI_SERVICES **PeiServices,
|
||||
IN EFI_PEI_RECOVERY_BLOCK_IO2_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 Sd Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimInitMemPool (
|
||||
IN SD_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 *
|
||||
SdPeimAllocateMem (
|
||||
IN SD_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
|
||||
SdPeimFreeMem (
|
||||
IN SD_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
);
|
||||
|
||||
#endif
|
|
@ -0,0 +1,62 @@
|
|||
## @file
|
||||
# Description file for the SD memory card Peim driver.
|
||||
#
|
||||
# Copyright (c) 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 = SdBlockIoPei
|
||||
MODULE_UNI_FILE = SdBlockIoPei.uni
|
||||
FILE_GUID = 17851FBF-45C4-4ff7-A2A0-C3B12D63C27E
|
||||
MODULE_TYPE = PEIM
|
||||
VERSION_STRING = 1.0
|
||||
|
||||
ENTRY_POINT = InitializeSdBlockIoPeim
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
|
||||
[Sources]
|
||||
SdBlockIoPei.c
|
||||
SdBlockIoPei.h
|
||||
SdHci.c
|
||||
SdHci.h
|
||||
SdHcMem.c
|
||||
SdHcMem.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
MdeModulePkg/MdeModulePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
IoLib
|
||||
TimerLib
|
||||
BaseMemoryLib
|
||||
PeimEntryPoint
|
||||
PeiServicesLib
|
||||
DebugLib
|
||||
|
||||
[Ppis]
|
||||
gEfiPeiVirtualBlockIoPpiGuid ## PRODUCES
|
||||
gEfiPeiVirtualBlockIo2PpiGuid ## PRODUCES
|
||||
gEdkiiPeiSdMmcHostControllerPpiGuid ## CONSUMES
|
||||
|
||||
[Depex]
|
||||
gEfiPeiMemoryDiscoveredPpiGuid AND gEdkiiPeiSdMmcHostControllerPpiGuid
|
||||
|
||||
[UserExtensions.TianoCore."ExtraFiles"]
|
||||
SdBlockIoPeiExtra.uni
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// The SdBlockIoPei driver is used to support recovery from SD memory card device.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "Support recovery from SD memory card devices"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "The SdBlockIoPei driver is used to support recovery from SD memory card device."
|
||||
|
|
@ -0,0 +1,21 @@
|
|||
// /** @file
|
||||
// SdBlockIoPei Localized Strings and Content
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
#string STR_PROPERTIES_MODULE_NAME
|
||||
#language en-US
|
||||
"SD BlockIo Peim for Recovery"
|
||||
|
||||
|
|
@ -0,0 +1,455 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdBlockIoPei.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.
|
||||
|
||||
**/
|
||||
SD_PEIM_MEM_BLOCK *
|
||||
SdPeimAllocMemBlock (
|
||||
IN UINTN Pages
|
||||
)
|
||||
{
|
||||
SD_PEIM_MEM_BLOCK *Block;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
EFI_PHYSICAL_ADDRESS Address;
|
||||
|
||||
TempPtr = NULL;
|
||||
Block = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof(SD_PEIM_MEM_BLOCK), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof(SD_PEIM_MEM_BLOCK));
|
||||
|
||||
//
|
||||
// each bit in the bit array represents SD_PEIM_MEM_UNIT
|
||||
// bytes of memory in the memory block.
|
||||
//
|
||||
ASSERT (SD_PEIM_MEM_UNIT * 8 <= EFI_PAGE_SIZE);
|
||||
|
||||
Block = (SD_PEIM_MEM_BLOCK*)(UINTN)TempPtr;
|
||||
Block->BufLen = EFI_PAGES_TO_SIZE (Pages);
|
||||
Block->BitsLen = Block->BufLen / (SD_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
|
||||
SdPeimFreeMemBlock (
|
||||
IN SD_PEIM_MEM_POOL *Pool,
|
||||
IN SD_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 *
|
||||
SdPeimAllocMemFromBlock (
|
||||
IN SD_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 (!SD_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit)) {
|
||||
Available++;
|
||||
|
||||
if (Available >= Units) {
|
||||
break;
|
||||
}
|
||||
|
||||
SD_PEIM_NEXT_BIT (Byte, Bit);
|
||||
|
||||
} else {
|
||||
SD_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 (!SD_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] | (UINT8) SD_PEIM_MEM_BIT (Bit));
|
||||
SD_PEIM_NEXT_BIT (Byte, Bit);
|
||||
}
|
||||
|
||||
return Block->Buf + (StartByte * 8 + StartBit) * SD_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
|
||||
SdPeimInsertMemBlockToPool (
|
||||
IN SD_PEIM_MEM_BLOCK *Head,
|
||||
IN SD_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
|
||||
SdPeimIsMemBlockEmpty (
|
||||
IN SD_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
|
||||
SdPeimUnlinkMemBlock (
|
||||
IN SD_PEIM_MEM_BLOCK *Head,
|
||||
IN SD_PEIM_MEM_BLOCK *BlockToUnlink
|
||||
)
|
||||
{
|
||||
SD_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 Sd Peim driver private data.
|
||||
|
||||
@retval EFI_SUCCESS The memory pool is initialized.
|
||||
@retval Others Fail to init the memory pool.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimInitMemPool (
|
||||
IN SD_PEIM_HC_PRIVATE_DATA *Private
|
||||
)
|
||||
{
|
||||
SD_PEIM_MEM_POOL *Pool;
|
||||
EFI_STATUS Status;
|
||||
VOID *TempPtr;
|
||||
|
||||
TempPtr = NULL;
|
||||
Pool = NULL;
|
||||
|
||||
Status = PeiServicesAllocatePool (sizeof (SD_PEIM_MEM_POOL), &TempPtr);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_OUT_OF_RESOURCES;
|
||||
}
|
||||
|
||||
ZeroMem ((VOID*)(UINTN)TempPtr, sizeof (SD_PEIM_MEM_POOL));
|
||||
|
||||
Pool = (SD_PEIM_MEM_POOL *)((UINTN)TempPtr);
|
||||
|
||||
Pool->Head = SdPeimAllocMemBlock (SD_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
|
||||
SdPeimFreeMemPool (
|
||||
IN SD_PEIM_MEM_POOL *Pool
|
||||
)
|
||||
{
|
||||
SD_PEIM_MEM_BLOCK *Block;
|
||||
|
||||
ASSERT (Pool->Head != NULL);
|
||||
|
||||
//
|
||||
// Unlink all the memory blocks from the pool, then free them.
|
||||
// SdPeimUnlinkMemBlock can't be used to unlink and free the
|
||||
// first block.
|
||||
//
|
||||
for (Block = Pool->Head->Next; Block != NULL; Block = Pool->Head->Next) {
|
||||
SdPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
SdPeimFreeMemBlock (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 *
|
||||
SdPeimAllocateMem (
|
||||
IN SD_PEIM_MEM_POOL *Pool,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
SD_PEIM_MEM_BLOCK *Head;
|
||||
SD_PEIM_MEM_BLOCK *Block;
|
||||
SD_PEIM_MEM_BLOCK *NewBlock;
|
||||
VOID *Mem;
|
||||
UINTN AllocSize;
|
||||
UINTN Pages;
|
||||
|
||||
Mem = NULL;
|
||||
AllocSize = SD_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 = SdPeimAllocMemFromBlock (Block, AllocSize / SD_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 (SD_PEIM_MEM_DEFAULT_PAGES)) {
|
||||
Pages = EFI_SIZE_TO_PAGES (AllocSize) + 1;
|
||||
} else {
|
||||
Pages = SD_PEIM_MEM_DEFAULT_PAGES;
|
||||
}
|
||||
|
||||
NewBlock = SdPeimAllocMemBlock (Pages);
|
||||
if (NewBlock == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
//
|
||||
// Add the new memory block to the pool, then allocate memory from it
|
||||
//
|
||||
SdPeimInsertMemBlockToPool (Head, NewBlock);
|
||||
Mem = SdPeimAllocMemFromBlock (NewBlock, AllocSize / SD_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
|
||||
SdPeimFreeMem (
|
||||
IN SD_PEIM_MEM_POOL *Pool,
|
||||
IN VOID *Mem,
|
||||
IN UINTN Size
|
||||
)
|
||||
{
|
||||
SD_PEIM_MEM_BLOCK *Head;
|
||||
SD_PEIM_MEM_BLOCK *Block;
|
||||
UINT8 *ToFree;
|
||||
UINTN AllocSize;
|
||||
UINTN Byte;
|
||||
UINTN Bit;
|
||||
UINTN Count;
|
||||
|
||||
Head = Pool->Head;
|
||||
AllocSize = SD_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) / SD_PEIM_MEM_UNIT) / 8;
|
||||
Bit = ((ToFree - Block->Buf) / SD_PEIM_MEM_UNIT) % 8;
|
||||
|
||||
//
|
||||
// reset associated bits in bit arry
|
||||
//
|
||||
for (Count = 0; Count < (AllocSize / SD_PEIM_MEM_UNIT); Count++) {
|
||||
ASSERT (SD_PEIM_MEM_BIT_IS_SET (Block->Bits[Byte], Bit));
|
||||
|
||||
Block->Bits[Byte] = (UINT8) (Block->Bits[Byte] ^ SD_PEIM_MEM_BIT (Bit));
|
||||
SD_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) && SdPeimIsMemBlockEmpty (Block)) {
|
||||
SdPeimFreeMemBlock (Pool, Block);
|
||||
}
|
||||
|
||||
return ;
|
||||
}
|
|
@ -0,0 +1,61 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_PEIM_MEM_H_
|
||||
#define _SD_PEIM_MEM_H_
|
||||
|
||||
#define SD_PEIM_MEM_BIT(a) ((UINTN)(1 << (a)))
|
||||
|
||||
#define SD_PEIM_MEM_BIT_IS_SET(Data, Bit) \
|
||||
((BOOLEAN)(((Data) & SD_PEIM_MEM_BIT(Bit)) == SD_PEIM_MEM_BIT(Bit)))
|
||||
|
||||
typedef struct _SD_PEIM_MEM_BLOCK SD_PEIM_MEM_BLOCK;
|
||||
|
||||
struct _SD_PEIM_MEM_BLOCK {
|
||||
UINT8 *Bits; // Bit array to record which unit is allocated
|
||||
UINTN BitsLen;
|
||||
UINT8 *Buf;
|
||||
UINTN BufLen; // Memory size in bytes
|
||||
SD_PEIM_MEM_BLOCK *Next;
|
||||
};
|
||||
|
||||
typedef struct _SD_PEIM_MEM_POOL {
|
||||
SD_PEIM_MEM_BLOCK *Head;
|
||||
} SD_PEIM_MEM_POOL;
|
||||
|
||||
//
|
||||
// Memory allocation unit, note that the value must meet SD spec alignment requirement.
|
||||
//
|
||||
#define SD_PEIM_MEM_UNIT 128
|
||||
|
||||
#define SD_PEIM_MEM_UNIT_MASK (SD_PEIM_MEM_UNIT - 1)
|
||||
#define SD_PEIM_MEM_DEFAULT_PAGES 16
|
||||
|
||||
#define SD_PEIM_MEM_ROUND(Len) (((Len) + SD_PEIM_MEM_UNIT_MASK) & (~SD_PEIM_MEM_UNIT_MASK))
|
||||
|
||||
//
|
||||
// Advance the byte and bit to the next bit, adjust byte accordingly.
|
||||
//
|
||||
#define SD_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
|
@ -0,0 +1,354 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_HCI_H_
|
||||
#define _SD_HCI_H_
|
||||
|
||||
//
|
||||
// SD Host Controller MMIO Register Offset
|
||||
//
|
||||
#define SD_HC_SDMA_ADDR 0x00
|
||||
#define SD_HC_ARG2 0x00
|
||||
#define SD_HC_BLK_SIZE 0x04
|
||||
#define SD_HC_BLK_COUNT 0x06
|
||||
#define SD_HC_ARG1 0x08
|
||||
#define SD_HC_TRANS_MOD 0x0C
|
||||
#define SD_HC_COMMAND 0x0E
|
||||
#define SD_HC_RESPONSE 0x10
|
||||
#define SD_HC_BUF_DAT_PORT 0x20
|
||||
#define SD_HC_PRESENT_STATE 0x24
|
||||
#define SD_HC_HOST_CTRL1 0x28
|
||||
#define SD_HC_POWER_CTRL 0x29
|
||||
#define SD_HC_BLK_GAP_CTRL 0x2A
|
||||
#define SD_HC_WAKEUP_CTRL 0x2B
|
||||
#define SD_HC_CLOCK_CTRL 0x2C
|
||||
#define SD_HC_TIMEOUT_CTRL 0x2E
|
||||
#define SD_HC_SW_RST 0x2F
|
||||
#define SD_HC_NOR_INT_STS 0x30
|
||||
#define SD_HC_ERR_INT_STS 0x32
|
||||
#define SD_HC_NOR_INT_STS_EN 0x34
|
||||
#define SD_HC_ERR_INT_STS_EN 0x36
|
||||
#define SD_HC_NOR_INT_SIG_EN 0x38
|
||||
#define SD_HC_ERR_INT_SIG_EN 0x3A
|
||||
#define SD_HC_AUTO_CMD_ERR_STS 0x3C
|
||||
#define SD_HC_HOST_CTRL2 0x3E
|
||||
#define SD_HC_CAP 0x40
|
||||
#define SD_HC_MAX_CURRENT_CAP 0x48
|
||||
#define SD_HC_FORCE_EVT_AUTO_CMD 0x50
|
||||
#define SD_HC_FORCE_EVT_ERR_INT 0x52
|
||||
#define SD_HC_ADMA_ERR_STS 0x54
|
||||
#define SD_HC_ADMA_SYS_ADDR 0x58
|
||||
#define SD_HC_PRESET_VAL 0x60
|
||||
#define SD_HC_SHARED_BUS_CTRL 0xE0
|
||||
#define SD_HC_SLOT_INT_STS 0xFC
|
||||
#define SD_HC_CTRL_VER 0xFE
|
||||
|
||||
//
|
||||
// The transfer modes supported by SD Host Controller
|
||||
// Simplified Spec 3.0 Table 1-2
|
||||
//
|
||||
typedef enum {
|
||||
SdNoData,
|
||||
SdPioMode,
|
||||
SdSdmaMode,
|
||||
SdAdmaMode
|
||||
} SD_HC_TRANSFER_MODE;
|
||||
|
||||
//
|
||||
// The maximum data length of each descriptor line
|
||||
//
|
||||
#define ADMA_MAX_DATA_PER_LINE 0x10000
|
||||
#define SD_SDMA_BOUNDARY 512 * 1024
|
||||
#define SD_SDMA_ROUND_UP(x, n) (((x) + n) & ~(n - 1))
|
||||
|
||||
typedef enum {
|
||||
SdCommandTypeBc, // Broadcast commands, no response
|
||||
SdCommandTypeBcr, // Broadcast commands with response
|
||||
SdCommandTypeAc, // Addressed(point-to-point) commands
|
||||
SdCommandTypeAdtc // Addressed(point-to-point) data transfer commands
|
||||
} SD_COMMAND_TYPE;
|
||||
|
||||
typedef enum {
|
||||
SdResponseTypeR1,
|
||||
SdResponseTypeR1b,
|
||||
SdResponseTypeR2,
|
||||
SdResponseTypeR3,
|
||||
SdResponseTypeR4,
|
||||
SdResponseTypeR5,
|
||||
SdResponseTypeR5b,
|
||||
SdResponseTypeR6,
|
||||
SdResponseTypeR7
|
||||
} SD_RESPONSE_TYPE;
|
||||
|
||||
typedef struct _SD_COMMAND_BLOCK {
|
||||
UINT16 CommandIndex;
|
||||
UINT32 CommandArgument;
|
||||
UINT32 CommandType; // One of the SD_COMMAND_TYPE values
|
||||
UINT32 ResponseType; // One of the SD_RESPONSE_TYPE values
|
||||
} SD_COMMAND_BLOCK;
|
||||
|
||||
typedef struct _SD_STATUS_BLOCK {
|
||||
UINT32 Resp0;
|
||||
UINT32 Resp1;
|
||||
UINT32 Resp2;
|
||||
UINT32 Resp3;
|
||||
} SD_STATUS_BLOCK;
|
||||
|
||||
typedef struct _SD_COMMAND_PACKET {
|
||||
UINT64 Timeout;
|
||||
SD_COMMAND_BLOCK *SdCmdBlk;
|
||||
SD_STATUS_BLOCK *SdStatusBlk;
|
||||
VOID *InDataBuffer;
|
||||
VOID *OutDataBuffer;
|
||||
UINT32 InTransferLength;
|
||||
UINT32 OutTransferLength;
|
||||
} SD_COMMAND_PACKET;
|
||||
|
||||
#pragma pack(1)
|
||||
|
||||
typedef struct {
|
||||
UINT32 Valid:1;
|
||||
UINT32 End:1;
|
||||
UINT32 Int:1;
|
||||
UINT32 Reserved:1;
|
||||
UINT32 Act:2;
|
||||
UINT32 Reserved1:10;
|
||||
UINT32 Length:16;
|
||||
UINT32 Address;
|
||||
} SD_HC_ADMA_DESC_LINE;
|
||||
|
||||
typedef struct {
|
||||
UINT32 TimeoutFreq:6; // bit 0:5
|
||||
UINT32 Reserved:1; // bit 6
|
||||
UINT32 TimeoutUnit:1; // bit 7
|
||||
UINT32 BaseClkFreq:8; // bit 8:15
|
||||
UINT32 MaxBlkLen:2; // bit 16:17
|
||||
UINT32 BusWidth8:1; // bit 18
|
||||
UINT32 Adma2:1; // bit 19
|
||||
UINT32 Reserved2:1; // bit 20
|
||||
UINT32 HighSpeed:1; // bit 21
|
||||
UINT32 Sdma:1; // bit 22
|
||||
UINT32 SuspRes:1; // bit 23
|
||||
UINT32 Voltage33:1; // bit 24
|
||||
UINT32 Voltage30:1; // bit 25
|
||||
UINT32 Voltage18:1; // bit 26
|
||||
UINT32 Reserved3:1; // bit 27
|
||||
UINT32 SysBus64:1; // bit 28
|
||||
UINT32 AsyncInt:1; // bit 29
|
||||
UINT32 SlotType:2; // bit 30:31
|
||||
UINT32 Sdr50:1; // bit 32
|
||||
UINT32 Sdr104:1; // bit 33
|
||||
UINT32 Ddr50:1; // bit 34
|
||||
UINT32 Reserved4:1; // bit 35
|
||||
UINT32 DriverTypeA:1; // bit 36
|
||||
UINT32 DriverTypeC:1; // bit 37
|
||||
UINT32 DriverTypeD:1; // bit 38
|
||||
UINT32 DriverType4:1; // bit 39
|
||||
UINT32 TimerCount:4; // bit 40:43
|
||||
UINT32 Reserved5:1; // bit 44
|
||||
UINT32 TuningSDR50:1; // bit 45
|
||||
UINT32 RetuningMod:2; // bit 46:47
|
||||
UINT32 ClkMultiplier:8; // bit 48:55
|
||||
UINT32 Reserved6:7; // bit 56:62
|
||||
UINT32 Hs400:1; // bit 63
|
||||
} SD_HC_SLOT_CAP;
|
||||
|
||||
#pragma pack()
|
||||
|
||||
/**
|
||||
Software reset the specified SD host controller and enable all interrupts.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The software reset executes successfully.
|
||||
@retval Others The software reset fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimHcReset (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Set all interrupt status bits in Normal and Error Interrupt Status Enable
|
||||
register.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimHcEnableInterrupt (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Get the capability data from the specified slot.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
@param[out] Capability The buffer to store the capability data.
|
||||
|
||||
@retval EFI_SUCCESS The operation executes successfully.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimHcGetCapability (
|
||||
IN UINTN Bar,
|
||||
OUT SD_HC_SLOT_CAP *Capability
|
||||
);
|
||||
|
||||
/**
|
||||
Detect whether there is a SD card attached at the specified SD host controller
|
||||
slot.
|
||||
|
||||
Refer to SD Host Controller Simplified spec 3.0 Section 3.1 for details.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS There is a SD card attached.
|
||||
@retval EFI_NO_MEDIA There is not a SD card attached.
|
||||
@retval Others The detection fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimHcCardDetect (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Initial SD host controller with lowest clock frequency, max power and max timeout value
|
||||
at initialization.
|
||||
|
||||
@param[in] Bar The mmio base address of the slot to be accessed.
|
||||
|
||||
@retval EFI_SUCCESS The host controller is initialized successfully.
|
||||
@retval Others The host controller isn't initialized successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimHcInitHost (
|
||||
IN UINTN Bar
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SWITCH_FUNC to the SD device to check switchable function or switch card function.
|
||||
|
||||
Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
|
||||
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] AccessMode The value for access mode group.
|
||||
@param[in] CommandSystem The value for command set group.
|
||||
@param[in] DriveStrength The value for drive length group.
|
||||
@param[in] PowerLimit The value for power limit group.
|
||||
@param[in] Mode Switch or check function.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimSwitch (
|
||||
IN SD_PEIM_HC_SLOT *Slot,
|
||||
IN UINT8 AccessMode,
|
||||
IN UINT8 CommandSystem,
|
||||
IN UINT8 DriveStrength,
|
||||
IN UINT8 PowerLimit,
|
||||
IN BOOLEAN Mode
|
||||
);
|
||||
|
||||
/**
|
||||
Send command READ_SINGLE_BLOCK/WRITE_SINGLE_BLOCK to the addressed SD device
|
||||
to read/write the specified number of blocks.
|
||||
|
||||
Refer to SD Physical Layer Simplified Spec 4.1 Section 4.7 for details.
|
||||
|
||||
@param[in] Slot The slot number of the SD card to send the command to.
|
||||
@param[in] Lba The logical block address of starting access.
|
||||
@param[in] BlockSize The block size of specified SD device partition.
|
||||
@param[in] Buffer The pointer to the transfer buffer.
|
||||
@param[in] BufferSize The size of transfer buffer.
|
||||
@param[in] IsRead Boolean to show the operation direction.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimRwSingleBlock (
|
||||
IN SD_PEIM_HC_SLOT *Slot,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINT32 BlockSize,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead
|
||||
);
|
||||
|
||||
/**
|
||||
Send command READ_MULTIPLE_BLOCK/WRITE_MULTIPLE_BLOCK to the addressed SD device
|
||||
to read/write the specified number of blocks.
|
||||
|
||||
Refer to SD Electrical Standard Spec 5.1 Section 6.10.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Sd card to send the command to.
|
||||
@param[in] Lba The logical block address of starting access.
|
||||
@param[in] BlockSize The block size of specified SD device partition.
|
||||
@param[in] Buffer The pointer to the transfer buffer.
|
||||
@param[in] BufferSize The size of transfer buffer.
|
||||
@param[in] IsRead Boolean to show the operation direction.
|
||||
|
||||
@retval EFI_SUCCESS The operation is done correctly.
|
||||
@retval Others The operation fails.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimRwMultiBlocks (
|
||||
IN SD_PEIM_HC_SLOT *Slot,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINT32 BlockSize,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead
|
||||
);
|
||||
|
||||
/**
|
||||
Execute SD device identification procedure.
|
||||
|
||||
Refer to SD Electrical Standard Spec 5.1 Section 6.4 for details.
|
||||
|
||||
@param[in] Slot The slot number of the Sd card to send the command to.
|
||||
|
||||
@retval EFI_SUCCESS There is a SD card.
|
||||
@retval Others There is not a SD card.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdPeimIdentification (
|
||||
IN SD_PEIM_HC_SLOT *Slot
|
||||
);
|
||||
|
||||
/**
|
||||
Free the resource used by the TRB.
|
||||
|
||||
@param[in] Trb The pointer to the SD_TRB instance.
|
||||
|
||||
**/
|
||||
VOID
|
||||
SdPeimFreeTrb (
|
||||
IN SD_TRB *Trb
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,240 @@
|
|||
/** @file
|
||||
UEFI Component Name(2) protocol implementation for SdDxe driver.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdDxe.h"
|
||||
|
||||
//
|
||||
// Driver name table
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdDxeDriverNameTable[] = {
|
||||
{ "eng;en", L"Edkii Sd Memory Card Device Driver" },
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// Controller name table
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_UNICODE_STRING_TABLE mSdDxeControllerNameTable[] = {
|
||||
{ "eng;en", L"Edkii Sd Host Controller" },
|
||||
{ NULL , NULL }
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME_PROTOCOL gSdDxeComponentName = {
|
||||
SdDxeComponentNameGetDriverName,
|
||||
SdDxeComponentNameGetControllerName,
|
||||
"eng"
|
||||
};
|
||||
|
||||
//
|
||||
// EFI Component Name 2 Protocol
|
||||
//
|
||||
GLOBAL_REMOVE_IF_UNREFERENCED EFI_COMPONENT_NAME2_PROTOCOL gSdDxeComponentName2 = {
|
||||
(EFI_COMPONENT_NAME2_GET_DRIVER_NAME) SdDxeComponentNameGetDriverName,
|
||||
(EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME) SdDxeComponentNameGetControllerName,
|
||||
"en"
|
||||
};
|
||||
|
||||
/**
|
||||
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
|
||||
SdDxeComponentNameGetDriverName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **DriverName
|
||||
)
|
||||
{
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
mSdDxeDriverNameTable,
|
||||
DriverName,
|
||||
(BOOLEAN)(This == &gSdDxeComponentName)
|
||||
);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
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
|
||||
SdDxeComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
SD_DEVICE *Device;
|
||||
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
|
||||
|
||||
//
|
||||
// Make sure this driver is currently managing ControllHandle
|
||||
//
|
||||
Status = EfiTestManagedDevice (
|
||||
ControllerHandle,
|
||||
gSdDxeDriverBinding.DriverBindingHandle,
|
||||
&gEfiSdMmcPassThruProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
ControllerNameTable = mSdDxeControllerNameTable;
|
||||
if (ChildHandle != NULL) {
|
||||
Status = EfiTestChildHandle (
|
||||
ControllerHandle,
|
||||
ChildHandle,
|
||||
&gEfiSdMmcPassThruProtocolGuid
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
//
|
||||
// Get the child context
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandle,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlockIo,
|
||||
gSdDxeDriverBinding.DriverBindingHandle,
|
||||
ChildHandle,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_UNSUPPORTED;
|
||||
}
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO (BlockIo);
|
||||
ControllerNameTable = Device->ControllerNameTable;
|
||||
}
|
||||
|
||||
return LookupUnicodeString2 (
|
||||
Language,
|
||||
This->SupportedLanguages,
|
||||
ControllerNameTable,
|
||||
ControllerName,
|
||||
(BOOLEAN)(This == &gSdDxeComponentName)
|
||||
);
|
||||
}
|
||||
|
|
@ -0,0 +1,971 @@
|
|||
/** @file
|
||||
The helper functions for BlockIo and BlockIo2 protocol.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#include "SdDxe.h"
|
||||
|
||||
/**
|
||||
Nonblocking I/O callback funtion when the event is signaled.
|
||||
|
||||
@param[in] Event The Event this notify function registered to.
|
||||
@param[in] Context Pointer to the context data registered to the
|
||||
Event.
|
||||
|
||||
**/
|
||||
VOID
|
||||
EFIAPI
|
||||
AsyncIoCallback (
|
||||
IN EFI_EVENT Event,
|
||||
IN VOID *Context
|
||||
)
|
||||
{
|
||||
SD_REQUEST *Request;
|
||||
|
||||
gBS->CloseEvent (Event);
|
||||
|
||||
Request = (SD_REQUEST *) Context;
|
||||
|
||||
DEBUG_CODE_BEGIN ();
|
||||
DEBUG ((EFI_D_INFO, "Sd Async Request: CmdIndex[%d] Arg[%08x] %r\n",
|
||||
Request->SdMmcCmdBlk.CommandIndex, Request->SdMmcCmdBlk.CommandArgument,
|
||||
Request->Packet.TransactionStatus));
|
||||
DEBUG_CODE_END ();
|
||||
|
||||
if (EFI_ERROR (Request->Packet.TransactionStatus)) {
|
||||
Request->Token->TransactionStatus = Request->Packet.TransactionStatus;
|
||||
}
|
||||
|
||||
RemoveEntryList (&Request->Link);
|
||||
|
||||
if (Request->IsEnd) {
|
||||
gBS->SignalEvent (Request->Token->Event);
|
||||
}
|
||||
|
||||
FreePool (Request);
|
||||
}
|
||||
|
||||
/**
|
||||
Send command SET_RELATIVE_ADDRESS to the device to set the device address.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[out] Rca The relative device address to assign.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSetRca (
|
||||
IN SD_DEVICE *Device,
|
||||
OUT UINT16 *Rca
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||
ZeroMem (&Packet, sizeof (Packet));
|
||||
Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
|
||||
Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
|
||||
Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
SdMmcCmdBlk.CommandIndex = SD_SET_RELATIVE_ADDR;
|
||||
SdMmcCmdBlk.CommandType = SdMmcCommandTypeBcr;
|
||||
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR6;
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_INFO, "Set RCA succeeds with Resp0 = 0x%x\n", SdMmcStatusBlk.Resp0));
|
||||
*Rca = (UINT16)(SdMmcStatusBlk.Resp0 >> 16);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send command SELECT to the device to select/deselect the device.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSelect (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||
ZeroMem (&Packet, sizeof (Packet));
|
||||
Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
|
||||
Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
|
||||
Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
SdMmcCmdBlk.CommandIndex = SD_SELECT_DESELECT_CARD;
|
||||
SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
|
||||
SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send command SEND_STATUS to the device to get device status.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] DevStatus The buffer to store the device status.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSendStatus (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT UINT32 *DevStatus
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||
ZeroMem (&Packet, sizeof (Packet));
|
||||
Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
|
||||
Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
|
||||
Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
SdMmcCmdBlk.CommandIndex = SD_SEND_STATUS;
|
||||
SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
CopyMem (DevStatus, &SdMmcStatusBlk.Resp0, sizeof (UINT32));
|
||||
}
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send command SEND_CSD to the device to get the CSD register data.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Csd The buffer to store the SD_CSD register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdGetCsd (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT SD_CSD *Csd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||
ZeroMem (&Packet, sizeof (Packet));
|
||||
ZeroMem (Csd, sizeof (SD_CSD));
|
||||
|
||||
Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
|
||||
Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
|
||||
Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
SdMmcCmdBlk.CommandIndex = SD_SEND_CSD;
|
||||
SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
|
||||
SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
|
||||
//
|
||||
CopyMem (((UINT8*)Csd) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CSD) - 1);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Send command SEND_CID to the device to get the CID register data.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Cid The buffer to store the SD_CID register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdGetCid (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT SD_CID *Cid
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
ZeroMem (&SdMmcCmdBlk, sizeof (SdMmcCmdBlk));
|
||||
ZeroMem (&SdMmcStatusBlk, sizeof (SdMmcStatusBlk));
|
||||
ZeroMem (&Packet, sizeof (Packet));
|
||||
ZeroMem (Cid, sizeof (SD_CID));
|
||||
|
||||
Packet.SdMmcCmdBlk = &SdMmcCmdBlk;
|
||||
Packet.SdMmcStatusBlk = &SdMmcStatusBlk;
|
||||
Packet.Timeout = SD_GENERIC_TIMEOUT;
|
||||
|
||||
SdMmcCmdBlk.CommandIndex = SD_SEND_CID;
|
||||
SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
|
||||
SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR2;
|
||||
SdMmcCmdBlk.CommandArgument = (UINT32)Rca << 16;
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &Packet, NULL);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
//
|
||||
// For details, refer to SD Host Controller Simplified Spec 3.0 Table 2-12.
|
||||
//
|
||||
CopyMem (((UINT8*)Cid) + 1, &SdMmcStatusBlk.Resp0, sizeof (SD_CID) - 1);
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Read/write single block through sync or async I/O request.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Lba The starting logical block address to be read/written.
|
||||
The caller is responsible for reading/writing to only
|
||||
legitimate locations.
|
||||
@param[in] Buffer A pointer to the destination/source buffer for the data.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] IsRead Indicates it is a read or write operation.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdRwSingleBlock (
|
||||
IN SD_DEVICE *Device,
|
||||
IN EFI_LBA Lba,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
SD_REQUEST *RwSingleBlkReq;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
RwSingleBlkReq = NULL;
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
RwSingleBlkReq = AllocateZeroPool (sizeof (SD_REQUEST));
|
||||
if (RwSingleBlkReq == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
RwSingleBlkReq->Signature = SD_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Device->Queue, &RwSingleBlkReq->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
RwSingleBlkReq->Packet.SdMmcCmdBlk = &RwSingleBlkReq->SdMmcCmdBlk;
|
||||
RwSingleBlkReq->Packet.SdMmcStatusBlk = &RwSingleBlkReq->SdMmcStatusBlk;
|
||||
//
|
||||
// Calculate timeout value through the below formula.
|
||||
// Timeout = (transfer size) / (2MB/s).
|
||||
// Taking 2MB/s as divisor as it's the lowest transfer speed
|
||||
// above class 2.
|
||||
// Refer to SD Physical Layer Simplified spec section 3.4 for details.
|
||||
//
|
||||
RwSingleBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
|
||||
|
||||
if (IsRead) {
|
||||
RwSingleBlkReq->Packet.InDataBuffer = Buffer;
|
||||
RwSingleBlkReq->Packet.InTransferLength = (UINT32)BufferSize;
|
||||
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_SINGLE_BLOCK;
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
|
||||
RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
} else {
|
||||
RwSingleBlkReq->Packet.OutDataBuffer = Buffer;
|
||||
RwSingleBlkReq->Packet.OutTransferLength = (UINT32)BufferSize;
|
||||
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_SINGLE_BLOCK;
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
|
||||
RwSingleBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
}
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba;
|
||||
} else {
|
||||
RwSingleBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
RwSingleBlkReq->IsEnd = IsEnd;
|
||||
RwSingleBlkReq->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
RwSingleBlkReq,
|
||||
&RwSingleBlkReq->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
RwSingleBlkReq->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &RwSingleBlkReq->Packet, RwSingleBlkReq->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (RwSingleBlkReq != NULL)) {
|
||||
RemoveEntryList (&RwSingleBlkReq->Link);
|
||||
if (RwSingleBlkReq->Event != NULL) {
|
||||
gBS->CloseEvent (RwSingleBlkReq->Event);
|
||||
}
|
||||
FreePool (RwSingleBlkReq);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (RwSingleBlkReq != NULL) {
|
||||
RemoveEntryList (&RwSingleBlkReq->Link);
|
||||
FreePool (RwSingleBlkReq);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Read/write multiple blocks through sync or async I/O request.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Lba The starting logical block address to be read/written.
|
||||
The caller is responsible for reading/writing to only
|
||||
legitimate locations.
|
||||
@param[in] Buffer A pointer to the destination/source buffer for the data.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] IsRead Indicates it is a read or write operation.
|
||||
@param[in] Token A pointer to the token associated with the transaction.
|
||||
@param[in] IsEnd A boolean to show whether it's the last cmd in a series of cmds.
|
||||
This parameter is only meaningful in async I/O request.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdRwMultiBlocks (
|
||||
IN SD_DEVICE *Device,
|
||||
IN EFI_LBA Lba,
|
||||
IN VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead,
|
||||
IN EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN BOOLEAN IsEnd
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_REQUEST *RwMultiBlkReq;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
RwMultiBlkReq = NULL;
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
|
||||
RwMultiBlkReq = AllocateZeroPool (sizeof (SD_REQUEST));
|
||||
if (RwMultiBlkReq == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
RwMultiBlkReq->Signature = SD_REQUEST_SIGNATURE;
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
InsertTailList (&Device->Queue, &RwMultiBlkReq->Link);
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
RwMultiBlkReq->Packet.SdMmcCmdBlk = &RwMultiBlkReq->SdMmcCmdBlk;
|
||||
RwMultiBlkReq->Packet.SdMmcStatusBlk = &RwMultiBlkReq->SdMmcStatusBlk;
|
||||
//
|
||||
// Calculate timeout value through the below formula.
|
||||
// Timeout = (transfer size) / (2MB/s).
|
||||
// Taking 2MB/s as divisor as it's the lowest transfer speed
|
||||
// above class 2.
|
||||
// Refer to SD Physical Layer Simplified spec section 3.4 for details.
|
||||
//
|
||||
RwMultiBlkReq->Packet.Timeout = (BufferSize / (2 * 1024 * 1024) + 1) * 1000 * 1000;
|
||||
|
||||
if (IsRead) {
|
||||
RwMultiBlkReq->Packet.InDataBuffer = Buffer;
|
||||
RwMultiBlkReq->Packet.InTransferLength = (UINT32)BufferSize;
|
||||
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_READ_MULTIPLE_BLOCK;
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
|
||||
RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
} else {
|
||||
RwMultiBlkReq->Packet.OutDataBuffer = Buffer;
|
||||
RwMultiBlkReq->Packet.OutTransferLength = (UINT32)BufferSize;
|
||||
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandIndex = SD_WRITE_MULTIPLE_BLOCK;
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAdtc;
|
||||
RwMultiBlkReq->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
|
||||
}
|
||||
|
||||
if (Device->SectorAddressing) {
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)Lba;
|
||||
} else {
|
||||
RwMultiBlkReq->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (Lba, Device->BlockMedia.BlockSize);
|
||||
}
|
||||
|
||||
RwMultiBlkReq->IsEnd = IsEnd;
|
||||
RwMultiBlkReq->Token = Token;
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Status = gBS->CreateEvent (
|
||||
EVT_NOTIFY_SIGNAL,
|
||||
TPL_CALLBACK,
|
||||
AsyncIoCallback,
|
||||
RwMultiBlkReq,
|
||||
&RwMultiBlkReq->Event
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
RwMultiBlkReq->Event = NULL;
|
||||
}
|
||||
|
||||
Status = PassThru->PassThru (PassThru, Device->Slot, &RwMultiBlkReq->Packet, RwMultiBlkReq->Event);
|
||||
|
||||
Error:
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
//
|
||||
// For asynchronous operation, only free request and event in error case.
|
||||
// The request and event will be freed in asynchronous callback for success case.
|
||||
//
|
||||
if (EFI_ERROR (Status) && (RwMultiBlkReq != NULL)) {
|
||||
RemoveEntryList (&RwMultiBlkReq->Link);
|
||||
if (RwMultiBlkReq->Event != NULL) {
|
||||
gBS->CloseEvent (RwMultiBlkReq->Event);
|
||||
}
|
||||
FreePool (RwMultiBlkReq);
|
||||
}
|
||||
} else {
|
||||
//
|
||||
// For synchronous operation, free request whatever the execution result is.
|
||||
//
|
||||
if (RwMultiBlkReq != NULL) {
|
||||
RemoveEntryList (&RwMultiBlkReq->Link);
|
||||
FreePool (RwMultiBlkReq);
|
||||
}
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
This function transfers data from/to the sd memory card device.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] MediaId The media ID that the read/write request is for.
|
||||
@param[in] Lba The starting logical block address to be read/written.
|
||||
The caller is responsible for reading/writing to only
|
||||
legitimate locations.
|
||||
@param[in, out] Buffer A pointer to the destination/source buffer for the data.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] IsRead Indicates it is a read or write operation.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS The data was read/written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be read/written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the read/write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read/write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdReadWrite (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT VOID *Buffer,
|
||||
IN UINTN BufferSize,
|
||||
IN BOOLEAN IsRead,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_BLOCK_IO_MEDIA *Media;
|
||||
UINTN BlockSize;
|
||||
UINTN BlockNum;
|
||||
UINTN IoAlign;
|
||||
UINTN Remaining;
|
||||
UINT32 MaxBlock;
|
||||
BOOLEAN LastRw;
|
||||
|
||||
Status = EFI_SUCCESS;
|
||||
Media = &Device->BlockMedia;
|
||||
LastRw = FALSE;
|
||||
|
||||
if (MediaId != Media->MediaId) {
|
||||
return EFI_MEDIA_CHANGED;
|
||||
}
|
||||
|
||||
if (!IsRead && Media->ReadOnly) {
|
||||
return EFI_WRITE_PROTECTED;
|
||||
}
|
||||
|
||||
//
|
||||
// Check parameters.
|
||||
//
|
||||
if (Buffer == NULL) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if (BufferSize == 0) {
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
gBS->SignalEvent (Token->Event);
|
||||
}
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
BlockSize = Media->BlockSize;
|
||||
if ((BufferSize % BlockSize) != 0) {
|
||||
return EFI_BAD_BUFFER_SIZE;
|
||||
}
|
||||
|
||||
BlockNum = BufferSize / BlockSize;
|
||||
if ((Lba + BlockNum - 1) > Media->LastBlock) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
IoAlign = Media->IoAlign;
|
||||
if (IoAlign > 0 && (((UINTN) Buffer & (IoAlign - 1)) != 0)) {
|
||||
return EFI_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
if ((Token != NULL) && (Token->Event != NULL)) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
}
|
||||
|
||||
//
|
||||
// Start to execute data transfer. The max block number in single cmd is 65535 blocks.
|
||||
//
|
||||
Remaining = BlockNum;
|
||||
MaxBlock = 0xFFFF;
|
||||
|
||||
while (Remaining > 0) {
|
||||
if (Remaining <= MaxBlock) {
|
||||
BlockNum = Remaining;
|
||||
LastRw = TRUE;
|
||||
} else {
|
||||
BlockNum = MaxBlock;
|
||||
}
|
||||
|
||||
BufferSize = BlockNum * BlockSize;
|
||||
if (BlockNum == 1) {
|
||||
Status = SdRwSingleBlock (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw);
|
||||
} else {
|
||||
Status = SdRwMultiBlocks (Device, Lba, Buffer, BufferSize, IsRead, Token, LastRw);
|
||||
}
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
DEBUG ((EFI_D_INFO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n", IsRead ? "Read" : "Write", Lba, BlockNum, Token->Event, Status));
|
||||
|
||||
Lba += BlockNum;
|
||||
Buffer = (UINT8*)Buffer + BufferSize;
|
||||
Remaining -= BlockNum;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO (This);
|
||||
|
||||
PassThru = Device->Private->PassThru;
|
||||
Status = PassThru->ResetDevice (PassThru, Device->Slot);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit 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 performing the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO (This);
|
||||
|
||||
Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, NULL);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the write request is for.
|
||||
@param Lba The starting logical block address to be written. The caller is
|
||||
responsible for writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO (This);
|
||||
|
||||
Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, NULL);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
)
|
||||
{
|
||||
//
|
||||
// return directly
|
||||
//
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
)
|
||||
{
|
||||
SD_DEVICE *Device;
|
||||
LIST_ENTRY *Link;
|
||||
LIST_ENTRY *NextLink;
|
||||
SD_REQUEST *Request;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);
|
||||
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
for (Link = GetFirstNode (&Device->Queue);
|
||||
!IsNull (&Device->Queue, Link);
|
||||
Link = NextLink) {
|
||||
NextLink = GetNextNode (&Device->Queue, Link);
|
||||
RemoveEntryList (Link);
|
||||
|
||||
Request = SD_REQUEST_FROM_LINK (Link);
|
||||
|
||||
gBS->CloseEvent (Request->Event);
|
||||
Request->Token->TransactionStatus = EFI_ABORTED;
|
||||
|
||||
if (Request->IsEnd) {
|
||||
gBS->SignalEvent (Request->Token->Event);
|
||||
}
|
||||
|
||||
FreePool (Request);
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Event is not NULL.
|
||||
The data was read correctly from the device if
|
||||
the Event is NULL.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing
|
||||
the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);
|
||||
|
||||
Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, TRUE, Token);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO2 (This);
|
||||
|
||||
Status = SdReadWrite (Device, MediaId, Lba, Buffer, BufferSize, FALSE, Token);
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
)
|
||||
{
|
||||
//
|
||||
// Signal event and return directly.
|
||||
//
|
||||
if (Token != NULL && Token->Event != NULL) {
|
||||
Token->TransactionStatus = EFI_SUCCESS;
|
||||
gBS->SignalEvent (Token->Event);
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
@ -0,0 +1,221 @@
|
|||
/** @file
|
||||
Header file for SdDxe Driver.
|
||||
|
||||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_BLOCK_IO_H_
|
||||
#define _SD_BLOCK_IO_H_
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReset (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId Id of the media, changes every time the media is replaced.
|
||||
@param Lba The starting Logical Block Address to read from
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit 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 performing the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReadBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
@param MediaId The media ID that the write request is for.
|
||||
@param Lba The starting logical block address to be written. The caller is
|
||||
responsible for writing to only legitimate locations.
|
||||
@param BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdWriteBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param This Indicates a pointer to the calling context.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdFlushBlocks (
|
||||
IN EFI_BLOCK_IO_PROTOCOL *This
|
||||
);
|
||||
|
||||
/**
|
||||
Reset the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] ExtendedVerification Driver may perform diagnostics on reset.
|
||||
|
||||
@retval EFI_SUCCESS The device was reset.
|
||||
@retval EFI_DEVICE_ERROR The device is not functioning properly and could
|
||||
not be reset.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdResetEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN BOOLEAN ExtendedVerification
|
||||
);
|
||||
|
||||
/**
|
||||
Read BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId Id of the media, changes every time the media is replaced.
|
||||
@param[in] Lba The starting Logical Block Address to read from.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[out] Buffer A pointer to the destination buffer for the data. The caller is
|
||||
responsible for either having implicit or explicit ownership of the buffer.
|
||||
|
||||
@retval EFI_SUCCESS The read request was queued if Event is not NULL.
|
||||
The data was read correctly from the device if
|
||||
the Event is NULL.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing
|
||||
the read.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
|
||||
@retval EFI_BAD_BUFFER_SIZE The BufferSize parameter is not a multiple of the
|
||||
intrinsic block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The read request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdReadBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
OUT VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Write BufferSize bytes from Lba into Buffer.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in] MediaId The media ID that the write request is for.
|
||||
@param[in] Lba The starting logical block address to be written. The
|
||||
caller is responsible for writing to only legitimate
|
||||
locations.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
@param[in] BufferSize Size of Buffer, must be a multiple of device block size.
|
||||
@param[in] Buffer A pointer to the source buffer for the data.
|
||||
|
||||
@retval EFI_SUCCESS The data was written correctly to the device.
|
||||
@retval EFI_WRITE_PROTECTED The device can not be written to.
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while performing the write.
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
@retval EFI_MEDIA_CHNAGED The MediaId does not matched the current device.
|
||||
@retval EFI_BAD_BUFFER_SIZE The Buffer was not a multiple of the block size of the device.
|
||||
@retval EFI_INVALID_PARAMETER The write request contains LBAs that are not valid,
|
||||
or the buffer is not on proper alignment.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdWriteBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN UINT32 MediaId,
|
||||
IN EFI_LBA Lba,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token,
|
||||
IN UINTN BufferSize,
|
||||
IN VOID *Buffer
|
||||
);
|
||||
|
||||
/**
|
||||
Flush the Block Device.
|
||||
|
||||
@param[in] This Indicates a pointer to the calling context.
|
||||
@param[in, out] Token A pointer to the token associated with the transaction.
|
||||
|
||||
@retval EFI_SUCCESS All outstanding data was written to the device
|
||||
@retval EFI_DEVICE_ERROR The device reported an error while writing back the data
|
||||
@retval EFI_NO_MEDIA There is no media in the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
SdFlushBlocksEx (
|
||||
IN EFI_BLOCK_IO2_PROTOCOL *This,
|
||||
IN OUT EFI_BLOCK_IO2_TOKEN *Token
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,888 @@
|
|||
/** @file
|
||||
The SdDxe driver is used to manage the SD memory card device.
|
||||
|
||||
It produces BlockIo and BlockIo2 protocols to allow upper layer
|
||||
access the SD memory card device.
|
||||
|
||||
Copyright (c) 2015 - 2016, 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 "SdDxe.h"
|
||||
|
||||
//
|
||||
// SdDxe Driver Binding Protocol Instance
|
||||
//
|
||||
EFI_DRIVER_BINDING_PROTOCOL gSdDxeDriverBinding = {
|
||||
SdDxeDriverBindingSupported,
|
||||
SdDxeDriverBindingStart,
|
||||
SdDxeDriverBindingStop,
|
||||
0x10,
|
||||
NULL,
|
||||
NULL
|
||||
};
|
||||
|
||||
//
|
||||
// Template for SD_DEVICE data structure.
|
||||
//
|
||||
SD_DEVICE mSdDeviceTemplate = {
|
||||
SD_DEVICE_SIGNATURE, // Signature
|
||||
NULL, // Handle
|
||||
NULL, // DevicePath
|
||||
0xFF, // Slot
|
||||
FALSE, // SectorAddressing
|
||||
{ // BlockIo
|
||||
EFI_BLOCK_IO_PROTOCOL_REVISION,
|
||||
NULL,
|
||||
SdReset,
|
||||
SdReadBlocks,
|
||||
SdWriteBlocks,
|
||||
SdFlushBlocks
|
||||
},
|
||||
{ // BlockIo2
|
||||
NULL,
|
||||
SdResetEx,
|
||||
SdReadBlocksEx,
|
||||
SdWriteBlocksEx,
|
||||
SdFlushBlocksEx
|
||||
},
|
||||
{ // BlockMedia
|
||||
0, // MediaId
|
||||
FALSE, // RemovableMedia
|
||||
TRUE, // MediaPresent
|
||||
FALSE, // LogicPartition
|
||||
FALSE, // ReadOnly
|
||||
FALSE, // WritingCache
|
||||
0x200, // BlockSize
|
||||
0, // IoAlign
|
||||
0 // LastBlock
|
||||
},
|
||||
{ // Queue
|
||||
NULL,
|
||||
NULL
|
||||
},
|
||||
{ // Csd
|
||||
0,
|
||||
},
|
||||
{ // Cid
|
||||
0,
|
||||
},
|
||||
NULL, // ControllerNameTable
|
||||
{ // ModelName
|
||||
0,
|
||||
},
|
||||
NULL // Private
|
||||
};
|
||||
|
||||
/**
|
||||
Decode and print SD CSD Register content.
|
||||
|
||||
@param[in] Csd Pointer to SD_CSD data structure.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully
|
||||
**/
|
||||
EFI_STATUS
|
||||
DumpCsd (
|
||||
IN SD_CSD *Csd
|
||||
)
|
||||
{
|
||||
SD_CSD2 *Csd2;
|
||||
|
||||
DEBUG((DEBUG_INFO, "== Dump Sd Csd Register==\n"));
|
||||
DEBUG((DEBUG_INFO, " CSD structure 0x%x\n", Csd->CsdStructure));
|
||||
DEBUG((DEBUG_INFO, " Data read access-time 1 0x%x\n", Csd->Taac));
|
||||
DEBUG((DEBUG_INFO, " Data read access-time 2 0x%x\n", Csd->Nsac));
|
||||
DEBUG((DEBUG_INFO, " Max. bus clock frequency 0x%x\n", Csd->TranSpeed));
|
||||
DEBUG((DEBUG_INFO, " Device command classes 0x%x\n", Csd->Ccc));
|
||||
DEBUG((DEBUG_INFO, " Max. read data block length 0x%x\n", Csd->ReadBlLen));
|
||||
DEBUG((DEBUG_INFO, " Partial blocks for read allowed 0x%x\n", Csd->ReadBlPartial));
|
||||
DEBUG((DEBUG_INFO, " Write block misalignment 0x%x\n", Csd->WriteBlkMisalign));
|
||||
DEBUG((DEBUG_INFO, " Read block misalignment 0x%x\n", Csd->ReadBlkMisalign));
|
||||
DEBUG((DEBUG_INFO, " DSR implemented 0x%x\n", Csd->DsrImp));
|
||||
if (Csd->CsdStructure == 0) {
|
||||
DEBUG((DEBUG_INFO, " Device size 0x%x\n", Csd->CSizeLow | (Csd->CSizeHigh << 2)));
|
||||
DEBUG((DEBUG_INFO, " Max. read current @ VDD min 0x%x\n", Csd->VddRCurrMin));
|
||||
DEBUG((DEBUG_INFO, " Max. read current @ VDD max 0x%x\n", Csd->VddRCurrMax));
|
||||
DEBUG((DEBUG_INFO, " Max. write current @ VDD min 0x%x\n", Csd->VddWCurrMin));
|
||||
DEBUG((DEBUG_INFO, " Max. write current @ VDD max 0x%x\n", Csd->VddWCurrMax));
|
||||
} else {
|
||||
Csd2 = (SD_CSD2*)(VOID*)Csd;
|
||||
DEBUG((DEBUG_INFO, " Device size 0x%x\n", Csd2->CSizeLow | (Csd->CSizeHigh << 16)));
|
||||
}
|
||||
DEBUG((DEBUG_INFO, " Erase sector size 0x%x\n", Csd->SectorSize));
|
||||
DEBUG((DEBUG_INFO, " Erase single block enable 0x%x\n", Csd->EraseBlkEn));
|
||||
DEBUG((DEBUG_INFO, " Write protect group size 0x%x\n", Csd->WpGrpSize));
|
||||
DEBUG((DEBUG_INFO, " Write protect group enable 0x%x\n", Csd->WpGrpEnable));
|
||||
DEBUG((DEBUG_INFO, " Write speed factor 0x%x\n", Csd->R2WFactor));
|
||||
DEBUG((DEBUG_INFO, " Max. write data block length 0x%x\n", Csd->WriteBlLen));
|
||||
DEBUG((DEBUG_INFO, " Partial blocks for write allowed 0x%x\n", Csd->WriteBlPartial));
|
||||
DEBUG((DEBUG_INFO, " File format group 0x%x\n", Csd->FileFormatGrp));
|
||||
DEBUG((DEBUG_INFO, " Copy flag (OTP) 0x%x\n", Csd->Copy));
|
||||
DEBUG((DEBUG_INFO, " Permanent write protection 0x%x\n", Csd->PermWriteProtect));
|
||||
DEBUG((DEBUG_INFO, " Temporary write protection 0x%x\n", Csd->TmpWriteProtect));
|
||||
DEBUG((DEBUG_INFO, " File format 0x%x\n", Csd->FileFormat));
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Get SD device model name.
|
||||
|
||||
@param[in, out] Device The pointer to the SD_DEVICE data structure.
|
||||
@param[in] Cid Pointer to SD_CID data structure.
|
||||
|
||||
@retval EFI_SUCCESS The function completed successfully
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
GetSdModelName (
|
||||
IN OUT SD_DEVICE *Device,
|
||||
IN SD_CID *Cid
|
||||
)
|
||||
{
|
||||
CHAR8 String[SD_MODEL_NAME_MAX_LEN];
|
||||
|
||||
ZeroMem (String, sizeof (String));
|
||||
CopyMem (String, Cid->OemId, sizeof (Cid->OemId));
|
||||
String[sizeof (Cid->OemId)] = ' ';
|
||||
CopyMem (String + sizeof (Cid->OemId) + 1, Cid->ProductName, sizeof (Cid->ProductName));
|
||||
String[sizeof (Cid->OemId) + sizeof (Cid->ProductName)] = ' ';
|
||||
CopyMem (String + sizeof (Cid->OemId) + sizeof (Cid->ProductName) + 1, Cid->ProductSerialNumber, sizeof (Cid->ProductSerialNumber));
|
||||
|
||||
AsciiStrToUnicodeStr (String, Device->ModelName);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
Discover user area partition in the SD device.
|
||||
|
||||
@param[in] Device The pointer to the SD_DEVICE data structure.
|
||||
|
||||
@retval EFI_SUCCESS The user area partition in the SD device is successfully identified.
|
||||
@return Others Some error occurs when identifying the user area.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
DiscoverUserArea (
|
||||
IN SD_DEVICE *Device
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_CSD *Csd;
|
||||
SD_CSD2 *Csd2;
|
||||
SD_CID *Cid;
|
||||
UINT64 Capacity;
|
||||
UINT32 DevStatus;
|
||||
UINT16 Rca;
|
||||
UINT32 CSize;
|
||||
UINT32 CSizeMul;
|
||||
UINT32 ReadBlLen;
|
||||
|
||||
//
|
||||
// Deselect the device to force it enter stby mode.
|
||||
// Note here we don't judge return status as some SD devices return
|
||||
// error but the state has been stby.
|
||||
//
|
||||
SdSelect (Device, 0);
|
||||
|
||||
Status = SdSetRca (Device, &Rca);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Assign new Rca = 0x%x fails with %r\n", Rca, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Csd = &Device->Csd;
|
||||
Status = SdGetCsd (Device, Rca, Csd);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
DumpCsd (Csd);
|
||||
|
||||
Cid = &Device->Cid;
|
||||
Status = SdGetCid (Device, Rca, Cid);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
GetSdModelName (Device, Cid);
|
||||
|
||||
Status = SdSelect (Device, Rca);
|
||||
if (EFI_ERROR (Status)) {
|
||||
DEBUG ((EFI_D_ERROR, "DiscoverUserArea(): Reselect the device 0x%x fails with %r\n", Rca, Status));
|
||||
return Status;
|
||||
}
|
||||
|
||||
Status = SdSendStatus (Device, Rca, &DevStatus);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (Csd->CsdStructure == 0) {
|
||||
Device->SectorAddressing = FALSE;
|
||||
CSize = (Csd->CSizeHigh << 2 | Csd->CSizeLow) + 1;
|
||||
CSizeMul = (1 << (Csd->CSizeMul + 2));
|
||||
ReadBlLen = (1 << (Csd->ReadBlLen));
|
||||
Capacity = MultU64x32 (MultU64x32 ((UINT64)CSize, CSizeMul), ReadBlLen);
|
||||
} else {
|
||||
Device->SectorAddressing = TRUE;
|
||||
Csd2 = (SD_CSD2*)(VOID*)Csd;
|
||||
CSize = (Csd2->CSizeHigh << 16 | Csd2->CSizeLow) + 1;
|
||||
Capacity = MultU64x32 ((UINT64)CSize, SIZE_512KB);
|
||||
}
|
||||
|
||||
Device->BlockIo.Media = &Device->BlockMedia;
|
||||
Device->BlockIo2.Media = &Device->BlockMedia;
|
||||
Device->BlockMedia.IoAlign = Device->Private->PassThru->IoAlign;
|
||||
Device->BlockMedia.BlockSize = 0x200;
|
||||
Device->BlockMedia.LastBlock = 0x00;
|
||||
Device->BlockMedia.RemovableMedia = TRUE;
|
||||
Device->BlockMedia.MediaPresent = TRUE;
|
||||
Device->BlockMedia.LogicalPartition = FALSE;
|
||||
Device->BlockMedia.LastBlock = DivU64x32 (Capacity, Device->BlockMedia.BlockSize) - 1;
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
||||
/**
|
||||
Scan SD Bus to discover the device.
|
||||
|
||||
@param[in] Private The SD driver private data structure.
|
||||
@param[in] Slot The slot number to check device present.
|
||||
|
||||
@retval EFI_SUCCESS Successfully to discover the device and attach
|
||||
SdMmcIoProtocol to it.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack
|
||||
of resources.
|
||||
@retval EFI_ALREADY_STARTED The device was discovered before.
|
||||
@retval Others Fail to discover the device.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
DiscoverSdDevice (
|
||||
IN SD_DRIVER_PRIVATE_DATA *Private,
|
||||
IN UINT8 Slot
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
SD_DEVICE *Device;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *NewDevicePath;
|
||||
EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath;
|
||||
EFI_HANDLE DeviceHandle;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
|
||||
Device = NULL;
|
||||
DevicePath = NULL;
|
||||
NewDevicePath = NULL;
|
||||
RemainingDevicePath = NULL;
|
||||
PassThru = Private->PassThru;
|
||||
|
||||
//
|
||||
// Build Device Path
|
||||
//
|
||||
Status = PassThru->BuildDevicePath (
|
||||
PassThru,
|
||||
Slot,
|
||||
&DevicePath
|
||||
);
|
||||
if (EFI_ERROR(Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
if (DevicePath->SubType != MSG_SD_DP) {
|
||||
Status = EFI_UNSUPPORTED;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
NewDevicePath = AppendDevicePathNode (
|
||||
Private->ParentDevicePath,
|
||||
DevicePath
|
||||
);
|
||||
|
||||
if (NewDevicePath == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
DeviceHandle = NULL;
|
||||
RemainingDevicePath = NewDevicePath;
|
||||
Status = gBS->LocateDevicePath (&gEfiDevicePathProtocolGuid, &RemainingDevicePath, &DeviceHandle);
|
||||
if (!EFI_ERROR (Status) && (DeviceHandle != NULL) && IsDevicePathEnd(RemainingDevicePath)) {
|
||||
//
|
||||
// The device has been started, directly return to fast boot.
|
||||
//
|
||||
Status = EFI_ALREADY_STARTED;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
//
|
||||
// Allocate buffer to store SD_DEVICE private data.
|
||||
//
|
||||
Device = AllocateCopyPool (sizeof (SD_DEVICE), &mSdDeviceTemplate);
|
||||
if (Device == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Device->DevicePath = NewDevicePath;
|
||||
Device->Slot = Slot;
|
||||
Device->Private = Private;
|
||||
InitializeListHead (&Device->Queue);
|
||||
|
||||
//
|
||||
// Expose user area in the Sd memory card to upper layer.
|
||||
//
|
||||
Status = DiscoverUserArea (Device);
|
||||
if (EFI_ERROR(Status)) {
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Device->ControllerNameTable = NULL;
|
||||
AddUnicodeString2 (
|
||||
"eng",
|
||||
gSdDxeComponentName.SupportedLanguages,
|
||||
&Device->ControllerNameTable,
|
||||
Device->ModelName,
|
||||
TRUE
|
||||
);
|
||||
AddUnicodeString2 (
|
||||
"en",
|
||||
gSdDxeComponentName.SupportedLanguages,
|
||||
&Device->ControllerNameTable,
|
||||
Device->ModelName,
|
||||
FALSE
|
||||
);
|
||||
|
||||
Status = gBS->InstallMultipleProtocolInterfaces (
|
||||
&Device->Handle,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Device->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Device->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Device->BlockIo2,
|
||||
NULL
|
||||
);
|
||||
|
||||
if (!EFI_ERROR (Status)) {
|
||||
gBS->OpenProtocol (
|
||||
Private->Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
(VOID **) &(Private->PassThru),
|
||||
Private->DriverBindingHandle,
|
||||
Device->Handle,
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
}
|
||||
|
||||
Error:
|
||||
FreePool (DevicePath);
|
||||
|
||||
if (EFI_ERROR (Status) && (NewDevicePath != NULL)) {
|
||||
FreePool (NewDevicePath);
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status) && (Device != NULL)) {
|
||||
FreePool (Device);
|
||||
}
|
||||
|
||||
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
|
||||
SdDxeDriverBindingSupported (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
UINT8 Slot;
|
||||
|
||||
//
|
||||
// Test EFI_SD_MMC_PASS_THRU_PROTOCOL on the controller handle.
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
(VOID**) &PassThru,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
|
||||
if (Status == EFI_ALREADY_STARTED) {
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
if (EFI_ERROR (Status)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Test RemainingDevicePath is valid or not.
|
||||
//
|
||||
if ((RemainingDevicePath != NULL) && !IsDevicePathEnd (RemainingDevicePath)) {
|
||||
Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Close the I/O Abstraction(s) used to perform the supported test
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
return Status;
|
||||
}
|
||||
}
|
||||
|
||||
//
|
||||
// Close the I/O Abstraction(s) used to perform the supported test
|
||||
//
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
//
|
||||
// Open the EFI Device Path protocol needed to perform the supported test
|
||||
//
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &ParentDevicePath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
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
|
||||
SdDxeDriverBindingStart (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
SD_DRIVER_PRIVATE_DATA *Private;
|
||||
UINT8 Slot;
|
||||
|
||||
Private = NULL;
|
||||
PassThru = NULL;
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
(VOID **) &PassThru,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_BY_DRIVER
|
||||
);
|
||||
if ((EFI_ERROR (Status)) && (Status != EFI_ALREADY_STARTED)) {
|
||||
return Status;
|
||||
}
|
||||
|
||||
//
|
||||
// Check EFI_ALREADY_STARTED to reuse the original SD_DRIVER_PRIVATE_DATA.
|
||||
//
|
||||
if (Status != EFI_ALREADY_STARTED) {
|
||||
Private = AllocateZeroPool (sizeof (SD_DRIVER_PRIVATE_DATA));
|
||||
if (Private == NULL) {
|
||||
Status = EFI_OUT_OF_RESOURCES;
|
||||
goto Error;
|
||||
}
|
||||
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
(VOID **) &ParentDevicePath,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
Private->PassThru = PassThru;
|
||||
Private->Controller = Controller;
|
||||
Private->ParentDevicePath = ParentDevicePath;
|
||||
Private->DriverBindingHandle = This->DriverBindingHandle;
|
||||
|
||||
Status = gBS->InstallProtocolInterface (
|
||||
&Controller,
|
||||
&gEfiCallerIdGuid,
|
||||
EFI_NATIVE_INTERFACE,
|
||||
Private
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
} else {
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiCallerIdGuid,
|
||||
(VOID **) &Private,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
goto Error;
|
||||
}
|
||||
}
|
||||
|
||||
if (RemainingDevicePath == NULL) {
|
||||
Slot = 0xFF;
|
||||
while (TRUE) {
|
||||
Status = PassThru->GetNextSlot (PassThru, &Slot);
|
||||
if (EFI_ERROR (Status)) {
|
||||
//
|
||||
// Cannot find more legal slots.
|
||||
//
|
||||
Status = EFI_SUCCESS;
|
||||
break;
|
||||
}
|
||||
|
||||
Status = DiscoverSdDevice (Private, Slot);
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
} else if (!IsDevicePathEnd (RemainingDevicePath)) {
|
||||
Status = PassThru->GetSlotNumber (PassThru, RemainingDevicePath, &Slot);
|
||||
if (!EFI_ERROR (Status)) {
|
||||
Status = DiscoverSdDevice (Private, Slot);
|
||||
}
|
||||
}
|
||||
|
||||
Error:
|
||||
if (EFI_ERROR (Status) && (Status != EFI_ALREADY_STARTED)) {
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
if (Private != NULL) {
|
||||
gBS->UninstallMultipleProtocolInterfaces (
|
||||
Controller,
|
||||
&gEfiCallerIdGuid,
|
||||
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
|
||||
SdDxeDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
BOOLEAN AllChildrenStopped;
|
||||
UINTN Index;
|
||||
SD_DRIVER_PRIVATE_DATA *Private;
|
||||
SD_DEVICE *Device;
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_BLOCK_IO2_PROTOCOL *BlockIo2;
|
||||
EFI_BLOCK_IO_PROTOCOL *BlockIo;
|
||||
LIST_ENTRY *Link;
|
||||
LIST_ENTRY *NextLink;
|
||||
SD_REQUEST *Request;
|
||||
EFI_TPL OldTpl;
|
||||
|
||||
if (NumberOfChildren == 0) {
|
||||
Status = gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiCallerIdGuid,
|
||||
(VOID **) &Private,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
gBS->UninstallProtocolInterface (
|
||||
Controller,
|
||||
&gEfiCallerIdGuid,
|
||||
Private
|
||||
);
|
||||
gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
Controller
|
||||
);
|
||||
|
||||
FreePool (Private);
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
AllChildrenStopped = TRUE;
|
||||
|
||||
for (Index = 0; Index < NumberOfChildren; Index++) {
|
||||
BlockIo = NULL;
|
||||
BlockIo2 = NULL;
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
(VOID **) &BlockIo,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
Status = gBS->OpenProtocol (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
(VOID **) &BlockIo2,
|
||||
This->DriverBindingHandle,
|
||||
Controller,
|
||||
EFI_OPEN_PROTOCOL_GET_PROTOCOL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
AllChildrenStopped = FALSE;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (BlockIo != NULL) {
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO (BlockIo);
|
||||
} else {
|
||||
ASSERT (BlockIo2 != NULL);
|
||||
Device = SD_DEVICE_DATA_FROM_BLKIO2 (BlockIo2);
|
||||
}
|
||||
|
||||
//
|
||||
// Free all on-going async tasks.
|
||||
//
|
||||
OldTpl = gBS->RaiseTPL (TPL_CALLBACK);
|
||||
for (Link = GetFirstNode (&Device->Queue);
|
||||
!IsNull (&Device->Queue, Link);
|
||||
Link = NextLink) {
|
||||
NextLink = GetNextNode (&Device->Queue, Link);
|
||||
RemoveEntryList (Link);
|
||||
|
||||
Request = SD_REQUEST_FROM_LINK (Link);
|
||||
|
||||
gBS->CloseEvent (Request->Event);
|
||||
Request->Token->TransactionStatus = EFI_ABORTED;
|
||||
|
||||
if (Request->IsEnd) {
|
||||
gBS->SignalEvent (Request->Token->Event);
|
||||
}
|
||||
|
||||
FreePool (Request);
|
||||
}
|
||||
gBS->RestoreTPL (OldTpl);
|
||||
|
||||
//
|
||||
// Close the child handle
|
||||
//
|
||||
Status = gBS->CloseProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
This->DriverBindingHandle,
|
||||
ChildHandleBuffer[Index]
|
||||
);
|
||||
|
||||
Status = gBS->UninstallMultipleProtocolInterfaces (
|
||||
ChildHandleBuffer[Index],
|
||||
&gEfiDevicePathProtocolGuid,
|
||||
Device->DevicePath,
|
||||
&gEfiBlockIoProtocolGuid,
|
||||
&Device->BlockIo,
|
||||
&gEfiBlockIo2ProtocolGuid,
|
||||
&Device->BlockIo2,
|
||||
NULL
|
||||
);
|
||||
if (EFI_ERROR (Status)) {
|
||||
AllChildrenStopped = FALSE;
|
||||
gBS->OpenProtocol (
|
||||
Controller,
|
||||
&gEfiSdMmcPassThruProtocolGuid,
|
||||
(VOID **)&PassThru,
|
||||
This->DriverBindingHandle,
|
||||
ChildHandleBuffer[Index],
|
||||
EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
|
||||
);
|
||||
} else {
|
||||
FreePool (Device->DevicePath);
|
||||
FreeUnicodeStringTable (Device->ControllerNameTable);
|
||||
FreePool (Device);
|
||||
}
|
||||
}
|
||||
|
||||
if (!AllChildrenStopped) {
|
||||
return EFI_DEVICE_ERROR;
|
||||
}
|
||||
|
||||
return EFI_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
The user Entry Point for module SdDxe. The user code starts with this function.
|
||||
|
||||
@param[in] ImageHandle The firmware allocated handle for the EFI image.
|
||||
@param[in] SystemTable A pointer to the EFI System Table.
|
||||
|
||||
@retval EFI_SUCCESS The entry point is executed successfully.
|
||||
@retval other Some errors occur when executing this entry point.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
EFIAPI
|
||||
InitializeSdDxe (
|
||||
IN EFI_HANDLE ImageHandle,
|
||||
IN EFI_SYSTEM_TABLE *SystemTable
|
||||
)
|
||||
{
|
||||
EFI_STATUS Status;
|
||||
|
||||
//
|
||||
// Install driver model protocol(s).
|
||||
//
|
||||
Status = EfiLibInstallDriverBindingComponentName2 (
|
||||
ImageHandle,
|
||||
SystemTable,
|
||||
&gSdDxeDriverBinding,
|
||||
ImageHandle,
|
||||
&gSdDxeComponentName,
|
||||
&gSdDxeComponentName2
|
||||
);
|
||||
ASSERT_EFI_ERROR (Status);
|
||||
|
||||
return Status;
|
||||
}
|
||||
|
|
@ -0,0 +1,469 @@
|
|||
/** @file
|
||||
Header file for SdDxe Driver.
|
||||
|
||||
This file defines common data structures, macro definitions and some module
|
||||
internal function header files.
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _SD_DXE_H_
|
||||
#define _SD_DXE_H_
|
||||
|
||||
#include <Uefi.h>
|
||||
#include <IndustryStandard/Sd.h>
|
||||
|
||||
#include <Protocol/SdMmcPassThru.h>
|
||||
#include <Protocol/BlockIo.h>
|
||||
#include <Protocol/BlockIo2.h>
|
||||
|
||||
#include <Protocol/DevicePath.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/UefiRuntimeServicesTableLib.h>
|
||||
|
||||
#include "SdBlockIo.h"
|
||||
//
|
||||
// Global Variables
|
||||
//
|
||||
extern EFI_DRIVER_BINDING_PROTOCOL gSdDxeDriverBinding;
|
||||
extern EFI_COMPONENT_NAME_PROTOCOL gSdDxeComponentName;
|
||||
extern EFI_COMPONENT_NAME2_PROTOCOL gSdDxeComponentName2;
|
||||
|
||||
#define SD_DEVICE_SIGNATURE SIGNATURE_32 ('S', 'D', 't', 'f')
|
||||
|
||||
#define SD_DEVICE_DATA_FROM_BLKIO(a) \
|
||||
CR(a, SD_DEVICE, BlockIo, SD_DEVICE_SIGNATURE)
|
||||
|
||||
#define SD_DEVICE_DATA_FROM_BLKIO2(a) \
|
||||
CR(a, SD_DEVICE, BlockIo2, SD_DEVICE_SIGNATURE)
|
||||
|
||||
//
|
||||
// Take 2.5 seconds as generic time out value, 1 microsecond as unit.
|
||||
//
|
||||
#define SD_GENERIC_TIMEOUT 2500 * 1000
|
||||
|
||||
#define SD_REQUEST_SIGNATURE SIGNATURE_32 ('S', 'D', 'R', 'E')
|
||||
|
||||
#define SD_MODEL_NAME_MAX_LEN 32
|
||||
|
||||
typedef struct _SD_DEVICE SD_DEVICE;
|
||||
typedef struct _SD_DRIVER_PRIVATE_DATA SD_DRIVER_PRIVATE_DATA;
|
||||
|
||||
//
|
||||
// Asynchronous I/O request.
|
||||
//
|
||||
typedef struct {
|
||||
UINT32 Signature;
|
||||
LIST_ENTRY Link;
|
||||
|
||||
EFI_SD_MMC_COMMAND_BLOCK SdMmcCmdBlk;
|
||||
EFI_SD_MMC_STATUS_BLOCK SdMmcStatusBlk;
|
||||
EFI_SD_MMC_PASS_THRU_COMMAND_PACKET Packet;
|
||||
|
||||
BOOLEAN IsEnd;
|
||||
|
||||
EFI_BLOCK_IO2_TOKEN *Token;
|
||||
|
||||
EFI_EVENT Event;
|
||||
} SD_REQUEST;
|
||||
|
||||
#define SD_REQUEST_FROM_LINK(a) \
|
||||
CR(a, SD_REQUEST, Link, SD_REQUEST_SIGNATURE)
|
||||
|
||||
struct _SD_DEVICE {
|
||||
UINT32 Signature;
|
||||
EFI_HANDLE Handle;
|
||||
EFI_DEVICE_PATH_PROTOCOL *DevicePath;
|
||||
UINT8 Slot;
|
||||
BOOLEAN SectorAddressing;
|
||||
EFI_BLOCK_IO_PROTOCOL BlockIo;
|
||||
EFI_BLOCK_IO2_PROTOCOL BlockIo2;
|
||||
EFI_BLOCK_IO_MEDIA BlockMedia;
|
||||
|
||||
LIST_ENTRY Queue;
|
||||
|
||||
SD_CSD Csd;
|
||||
SD_CID Cid;
|
||||
EFI_UNICODE_STRING_TABLE *ControllerNameTable;
|
||||
//
|
||||
// The model name consists of three fields in CID register
|
||||
// 1) OEM/Application ID (2 bytes)
|
||||
// 2) Product Name (5 bytes)
|
||||
// 3) Product Serial Number (4 bytes)
|
||||
// The delimiters of these fields are whitespace.
|
||||
//
|
||||
CHAR16 ModelName[SD_MODEL_NAME_MAX_LEN];
|
||||
SD_DRIVER_PRIVATE_DATA *Private;
|
||||
} ;
|
||||
|
||||
//
|
||||
// SD DXE driver private data structure
|
||||
//
|
||||
struct _SD_DRIVER_PRIVATE_DATA {
|
||||
EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
|
||||
EFI_HANDLE Controller;
|
||||
EFI_DEVICE_PATH_PROTOCOL *ParentDevicePath;
|
||||
EFI_HANDLE DriverBindingHandle;
|
||||
} ;
|
||||
|
||||
/**
|
||||
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
|
||||
SdDxeDriverBindingSupported (
|
||||
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
|
||||
SdDxeDriverBindingStart (
|
||||
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
|
||||
SdDxeDriverBindingStop (
|
||||
IN EFI_DRIVER_BINDING_PROTOCOL *This,
|
||||
IN EFI_HANDLE Controller,
|
||||
IN UINTN NumberOfChildren,
|
||||
IN EFI_HANDLE *ChildHandleBuffer
|
||||
);
|
||||
|
||||
/**
|
||||
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
|
||||
SdDxeComponentNameGetDriverName (
|
||||
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
|
||||
SdDxeComponentNameGetControllerName (
|
||||
IN EFI_COMPONENT_NAME_PROTOCOL *This,
|
||||
IN EFI_HANDLE ControllerHandle,
|
||||
IN EFI_HANDLE ChildHandle OPTIONAL,
|
||||
IN CHAR8 *Language,
|
||||
OUT CHAR16 **ControllerName
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SET_RELATIVE_ADDRESS to the device to set the device address.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[out] Rca The relative device address to assign.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSetRca (
|
||||
IN SD_DEVICE *Device,
|
||||
OUT UINT16 *Rca
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SELECT to the device to select/deselect the device.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSelect (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_STATUS to the device to get device status.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] DevStatus The buffer to store the device status.
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdSendStatus (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT UINT32 *DevStatus
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_CSD to the device to get the CSD register data.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Csd The buffer to store the SD_CSD register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdGetCsd (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT SD_CSD *Csd
|
||||
);
|
||||
|
||||
/**
|
||||
Send command SEND_CID to the device to get the CID register data.
|
||||
|
||||
@param[in] Device A pointer to the SD_DEVICE instance.
|
||||
@param[in] Rca The relative device address to use.
|
||||
@param[out] Cid The buffer to store the SD_CID register data.
|
||||
|
||||
@retval EFI_SUCCESS The request is executed successfully.
|
||||
@retval EFI_OUT_OF_RESOURCES The request could not be executed due to a lack of resources.
|
||||
@retval Others The request could not be executed successfully.
|
||||
|
||||
**/
|
||||
EFI_STATUS
|
||||
SdGetCid (
|
||||
IN SD_DEVICE *Device,
|
||||
IN UINT16 Rca,
|
||||
OUT SD_CID *Cid
|
||||
);
|
||||
|
||||
#endif
|
||||
|
|
@ -0,0 +1,65 @@
|
|||
## @file
|
||||
# SdDxe driver is used to manage the SD memory card device.
|
||||
#
|
||||
# It produces BlockIo and BlockIo2 protocols to allow upper layer
|
||||
# access the SD memory card device.
|
||||
#
|
||||
# Copyright (c) 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 = SdDxe
|
||||
MODULE_UNI_FILE = SdDxe.uni
|
||||
FILE_GUID = 430AC2F7-EEC6-4093-94F7-9F825A7C1C40
|
||||
MODULE_TYPE = UEFI_DRIVER
|
||||
VERSION_STRING = 1.0
|
||||
ENTRY_POINT = InitializeSdDxe
|
||||
|
||||
#
|
||||
# The following information is for reference only and not required by the build tools.
|
||||
#
|
||||
# VALID_ARCHITECTURES = IA32 X64 IPF EBC
|
||||
#
|
||||
# DRIVER_BINDING = gSdDxeDriverBinding
|
||||
# COMPONENT_NAME = gSdDxeComponentName
|
||||
# COMPONENT_NAME2 = gSdDxeComponentName2
|
||||
#
|
||||
|
||||
[Sources.common]
|
||||
ComponentName.c
|
||||
SdDxe.c
|
||||
SdDxe.h
|
||||
SdBlockIo.c
|
||||
SdBlockIo.h
|
||||
|
||||
[Packages]
|
||||
MdePkg/MdePkg.dec
|
||||
|
||||
[LibraryClasses]
|
||||
DevicePathLib
|
||||
UefiBootServicesTableLib
|
||||
MemoryAllocationLib
|
||||
BaseMemoryLib
|
||||
UefiLib
|
||||
BaseLib
|
||||
UefiDriverEntryPoint
|
||||
DebugLib
|
||||
|
||||
[Protocols]
|
||||
gEfiSdMmcPassThruProtocolGuid ## TO_START
|
||||
gEfiBlockIoProtocolGuid ## BY_START
|
||||
gEfiBlockIo2ProtocolGuid ## BY_START
|
||||
## TO_START
|
||||
## BY_START
|
||||
gEfiDevicePathProtocolGuid
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// /** @file
|
||||
// SD memory card device driver to manage the SD memory card device and provide interface for upper layer
|
||||
// access.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "SD device driver to manage the SD memory card device and provide interface for upper layer access"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This driver follows the UEFI driver model and layers on the SdMmcPassThru protocol. It installs BlockIo and BlockIo2 protocols on the SD device."
|
||||
|
|
@ -0,0 +1,20 @@
|
|||
// /** @file
|
||||
// SD memory card device driver to manage the SD memory card device and provide interface for upper layer
|
||||
// access.
|
||||
//
|
||||
// Copyright (c) 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.
|
||||
//
|
||||
// **/
|
||||
|
||||
|
||||
#string STR_MODULE_ABSTRACT #language en-US "SD device driver to manage the SD memory card device and provide interface for upper layer access"
|
||||
|
||||
#string STR_MODULE_DESCRIPTION #language en-US "This driver follows the UEFI driver model and layers on the SdMmcPassThru protocol. It installs BlockIo and BlockIo2 protocols on the SD device."
|
||||
|
|
@ -0,0 +1,64 @@
|
|||
/** @file
|
||||
|
||||
Copyright (c) 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.
|
||||
|
||||
**/
|
||||
|
||||
#ifndef _EDKII_PEI_SD_MMC_HOST_CONTROLLER_PPI_H_
|
||||
#define _EDKII_PEI_SD_MMC_HOST_CONTROLLER_PPI_H_
|
||||
|
||||
///
|
||||
/// Global ID for the EDKII_SD_MMC_HOST_CONTROLLER_PPI.
|
||||
///
|
||||
#define EDKII_SD_MMC_HOST_CONTROLLER_PPI_GUID \
|
||||
{ \
|
||||
0xb30dfeed, 0x947f, 0x4396, { 0xb1, 0x5a, 0xdf, 0xbd, 0xb9, 0x16, 0xdc, 0x24 } \
|
||||
}
|
||||
|
||||
///
|
||||
/// Forward declaration for the SD_MMC_HOST_CONTROLLER_PPI.
|
||||
///
|
||||
typedef struct _EDKII_SD_MMC_HOST_CONTROLLER_PPI EDKII_SD_MMC_HOST_CONTROLLER_PPI;
|
||||
|
||||
/**
|
||||
Get the MMIO base address of SD/MMC host controller.
|
||||
|
||||
@param[in] This The protocol instance pointer.
|
||||
@param[in] ControllerId The ID of the SD/MMC host controller.
|
||||
@param[in,out] MmioBar The pointer to store the array of available
|
||||
SD/MMC host controller slot MMIO base addresses.
|
||||
The entry number of the array is specified by BarNum.
|
||||
@param[out] BarNum The pointer to store the supported bar number.
|
||||
|
||||
@retval EFI_SUCCESS The operation succeeds.
|
||||
@retval EFI_INVALID_PARAMETER The parameters are invalid.
|
||||
|
||||
**/
|
||||
typedef
|
||||
EFI_STATUS
|
||||
(EFIAPI *EDKII_SD_MMC_HC_GET_MMIO_BAR)(
|
||||
IN EDKII_SD_MMC_HOST_CONTROLLER_PPI *This,
|
||||
IN UINT8 ControllerId,
|
||||
IN OUT UINTN **MmioBar,
|
||||
OUT UINT8 *BarNum
|
||||
);
|
||||
|
||||
///
|
||||
/// This PPI contains a set of services to interact with the SD_MMC host controller.
|
||||
///
|
||||
struct _EDKII_SD_MMC_HOST_CONTROLLER_PPI {
|
||||
EDKII_SD_MMC_HC_GET_MMIO_BAR GetSdMmcHcMmioBar;
|
||||
};
|
||||
|
||||
extern EFI_GUID gEdkiiPeiSdMmcHostControllerPpiGuid;
|
||||
|
||||
#endif
|
|
@ -388,6 +388,9 @@
|
|||
## Include/Ppi/IpmiPpi.h
|
||||
gPeiIpmiPpiGuid = { 0xa9731431, 0xd968, 0x4277, { 0xb7, 0x52, 0xa3, 0xa9, 0xa6, 0xae, 0x18, 0x98 }}
|
||||
|
||||
## Include/Ppi/SdMmcHostController.h
|
||||
gEdkiiPeiSdMmcHostControllerPpiGuid = { 0xb30dfeed, 0x947f, 0x4396, { 0xb1, 0x5a, 0xdf, 0xbd, 0xb9, 0x16, 0xdc, 0x24 }}
|
||||
|
||||
[Protocols]
|
||||
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
||||
# Include/Protocol/LoadPe32Image.h
|
||||
|
@ -1495,6 +1498,12 @@
|
|||
# @Prompt Set NX for stack.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE|BOOLEAN|0x0001006f
|
||||
|
||||
## This PCD specifies the PCI-based SD/MMC host controller mmio base address.
|
||||
# Define the mmio base address of the pci-based SD/MMC host controller. If there are multiple SD/MMC
|
||||
# host controllers, their mmio base addresses are calculated one by one from this base address.
|
||||
# @Prompt Mmio base address of pci-based SD/MMC host controller.
|
||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSdMmcPciHostControllerMmioBase|0xd0000000|UINT32|0x30001043
|
||||
|
||||
[PcdsPatchableInModule]
|
||||
## Specify memory size with page number for PEI code when
|
||||
# Loading Module at Fixed Address feature is enabled.
|
||||
|
|
|
@ -215,6 +215,12 @@
|
|||
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
|
||||
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
|
||||
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.inf
|
||||
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
|
||||
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
|
||||
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
|
||||
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
|
||||
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
|
||||
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
|
||||
MdeModulePkg/Bus/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
|
||||
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
|
||||
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
|
||||
|
|
Loading…
Reference in New Issue