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:
211
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/ComponentName.c
Normal file
211
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/ComponentName.c
Normal file
@ -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)
|
||||||
|
);
|
||||||
|
}
|
1152
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
Normal file
1152
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/EmmcDevice.c
Normal file
File diff suppressed because it is too large
Load Diff
1165
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
Normal file
1165
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdDevice.c
Normal file
File diff suppressed because it is too large
Load Diff
1261
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
Normal file
1261
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.c
Normal file
File diff suppressed because it is too large
Load Diff
784
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
Normal file
784
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.h
Normal file
@ -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
|
72
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
Normal file
72
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.inf
Normal file
@ -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
|
23
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.uni
Normal file
23
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxe.uni
Normal file
@ -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."
|
||||||
|
|
19
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxeExtra.uni
Normal file
19
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHcDxeExtra.uni
Normal file
@ -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"
|
||||||
|
|
||||||
|
|
1901
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
Normal file
1901
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.c
Normal file
File diff suppressed because it is too large
Load Diff
546
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
Normal file
546
MdeModulePkg/Bus/Pci/SdMmcPciHcDxe/SdMmcPciHci.h
Normal file
@ -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
|
212
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.c
Normal file
212
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.c
Normal file
@ -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;
|
||||||
|
}
|
86
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.h
Normal file
86
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.h
Normal file
@ -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
|
56
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
Normal file
56
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.inf
Normal file
@ -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
|
22
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.uni
Normal file
22
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPei.uni
Normal file
@ -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."
|
||||||
|
|
21
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPeiExtra.uni
Normal file
21
MdeModulePkg/Bus/Pci/SdMmcPciHcPei/SdMmcPciHcPeiExtra.uni
Normal file
@ -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"
|
||||||
|
|
||||||
|
|
807
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c
Normal file
807
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.c
Normal file
@ -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;
|
||||||
|
}
|
381
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h
Normal file
381
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.h
Normal file
@ -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
|
62
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
Normal file
62
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.inf
Normal file
@ -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
|
||||||
|
|
21
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.uni
Normal file
21
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPei.uni
Normal file
@ -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."
|
||||||
|
|
21
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPeiExtra.uni
Normal file
21
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcBlockIoPeiExtra.uni
Normal file
@ -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"
|
||||||
|
|
||||||
|
|
455
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c
Normal file
455
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.c
Normal file
@ -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 ;
|
||||||
|
}
|
61
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h
Normal file
61
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHcMem.h
Normal file
@ -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
|
||||||
|
|
2833
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c
Normal file
2833
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.c
Normal file
File diff suppressed because it is too large
Load Diff
345
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.h
Normal file
345
MdeModulePkg/Bus/Sd/EmmcBlockIoPei/EmmcHci.h
Normal file
@ -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
|
||||||
|
|
241
MdeModulePkg/Bus/Sd/EmmcDxe/ComponentName.c
Normal file
241
MdeModulePkg/Bus/Sd/EmmcDxe/ComponentName.c
Normal file
@ -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)
|
||||||
|
);}
|
||||||
|
|
1591
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
Normal file
1591
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.c
Normal file
File diff suppressed because it is too large
Load Diff
466
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
Normal file
466
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcBlockIo.h
Normal file
@ -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
|
||||||
|
|
1175
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
Normal file
1175
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.c
Normal file
File diff suppressed because it is too large
Load Diff
495
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
Normal file
495
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.h
Normal file
@ -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
|
||||||
|
|
66
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
Normal file
66
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.inf
Normal file
@ -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
|
||||||
|
|
20
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.uni
Normal file
20
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxe.uni
Normal file
@ -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."
|
||||||
|
|
19
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxeExtra.uni
Normal file
19
MdeModulePkg/Bus/Sd/EmmcDxe/EmmcDxeExtra.uni
Normal file
@ -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"
|
||||||
|
|
||||||
|
|
617
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c
Normal file
617
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.c
Normal file
@ -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;
|
||||||
|
}
|
377
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h
Normal file
377
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.h
Normal file
@ -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
|
62
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
Normal file
62
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.inf
Normal file
@ -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
|
||||||
|
|
21
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.uni
Normal file
21
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPei.uni
Normal file
@ -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."
|
||||||
|
|
21
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPeiExtra.uni
Normal file
21
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdBlockIoPeiExtra.uni
Normal file
@ -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"
|
||||||
|
|
||||||
|
|
455
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c
Normal file
455
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.c
Normal file
@ -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 ;
|
||||||
|
}
|
61
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h
Normal file
61
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHcMem.h
Normal file
@ -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
|
||||||
|
|
2874
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
Normal file
2874
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.c
Normal file
File diff suppressed because it is too large
Load Diff
354
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
Normal file
354
MdeModulePkg/Bus/Sd/SdBlockIoPei/SdHci.h
Normal file
@ -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
|
||||||
|
|
240
MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c
Normal file
240
MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c
Normal file
@ -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)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
971
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
Normal file
971
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
221
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
Normal file
221
MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h
Normal file
@ -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
|
||||||
|
|
888
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
Normal file
888
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c
Normal file
@ -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;
|
||||||
|
}
|
||||||
|
|
469
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
Normal file
469
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h
Normal file
@ -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
|
||||||
|
|
65
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
Normal file
65
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf
Normal file
@ -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
|
||||||
|
|
20
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni
Normal file
20
MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni
Normal file
@ -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."
|
||||||
|
|
20
MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni
Normal file
20
MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni
Normal file
@ -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."
|
||||||
|
|
64
MdeModulePkg/Include/Ppi/SdMmcHostController.h
Normal file
64
MdeModulePkg/Include/Ppi/SdMmcHostController.h
Normal file
@ -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
|
## Include/Ppi/IpmiPpi.h
|
||||||
gPeiIpmiPpiGuid = { 0xa9731431, 0xd968, 0x4277, { 0xb7, 0x52, 0xa3, 0xa9, 0xa6, 0xae, 0x18, 0x98 }}
|
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]
|
[Protocols]
|
||||||
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
## Load File protocol provides capability to load and unload EFI image into memory and execute it.
|
||||||
# Include/Protocol/LoadPe32Image.h
|
# Include/Protocol/LoadPe32Image.h
|
||||||
@ -1495,6 +1498,12 @@
|
|||||||
# @Prompt Set NX for stack.
|
# @Prompt Set NX for stack.
|
||||||
gEfiMdeModulePkgTokenSpaceGuid.PcdSetNxForStack|FALSE|BOOLEAN|0x0001006f
|
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]
|
[PcdsPatchableInModule]
|
||||||
## Specify memory size with page number for PEI code when
|
## Specify memory size with page number for PEI code when
|
||||||
# Loading Module at Fixed Address feature is enabled.
|
# Loading Module at Fixed Address feature is enabled.
|
||||||
|
@ -215,6 +215,12 @@
|
|||||||
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
|
MdeModulePkg/Bus/Pci/PciBusDxe/PciBusDxe.inf
|
||||||
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
|
MdeModulePkg/Bus/Pci/IncompatiblePciDeviceSupportDxe/IncompatiblePciDeviceSupportDxe.inf
|
||||||
MdeModulePkg/Bus/Pci/NvmExpressDxe/NvmExpressDxe.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/Pci/UfsPciHcDxe/UfsPciHcDxe.inf
|
||||||
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
|
MdeModulePkg/Bus/Ufs/UfsPassThruDxe/UfsPassThruDxe.inf
|
||||||
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
|
MdeModulePkg/Bus/Pci/UfsPciHcPei/UfsPciHcPei.inf
|
||||||
|
Reference in New Issue
Block a user