diff options
Diffstat (limited to 'roms/edk2/MdeModulePkg/Bus/Sd/SdDxe')
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c | 234 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c | 1381 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h | 252 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.c | 132 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.h | 109 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c | 908 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h | 475 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf | 64 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni | 15 | ||||
-rw-r--r-- | roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni | 15 |
10 files changed, 3585 insertions, 0 deletions
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c new file mode 100644 index 000000000..acd29d72c --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/ComponentName.c @@ -0,0 +1,234 @@ +/** @file
+ UEFI Component Name(2) protocol implementation for SdDxe driver.
+
+ Copyright (c) 2015, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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)
+ );
+}
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c new file mode 100644 index 000000000..721f26437 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.c @@ -0,0 +1,1381 @@ +/** @file
+ The helper functions for BlockIo and BlockIo2 protocol.
+
+ Copyright (c) 2015 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SdDxe.h"
+
+/**
+ Nonblocking I/O callback function 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;
+ if (Rca != 0) {
+ 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_NOTIFY);
+ 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_NOTIFY,
+ 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)) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&RwSingleBlkReq->Link);
+ gBS->RestoreTPL (OldTpl);
+ if (RwSingleBlkReq->Event != NULL) {
+ gBS->CloseEvent (RwSingleBlkReq->Event);
+ }
+ FreePool (RwSingleBlkReq);
+ }
+ } else {
+ //
+ // For synchronous operation, free request whatever the execution result is.
+ //
+ if (RwSingleBlkReq != NULL) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&RwSingleBlkReq->Link);
+ gBS->RestoreTPL (OldTpl);
+ 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_NOTIFY);
+ 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_NOTIFY,
+ 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)) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&RwMultiBlkReq->Link);
+ gBS->RestoreTPL (OldTpl);
+ if (RwMultiBlkReq->Event != NULL) {
+ gBS->CloseEvent (RwMultiBlkReq->Event);
+ }
+ FreePool (RwMultiBlkReq);
+ }
+ } else {
+ //
+ // For synchronous operation, free request whatever the execution result is.
+ //
+ if (RwMultiBlkReq != NULL) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&RwMultiBlkReq->Link);
+ gBS->RestoreTPL (OldTpl);
+ 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_CHANGED The MediaId does not match 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 ((DEBUG_BLKIO, "Sd%a(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
+ IsRead ? "Read" : "Write", Lba, BlockNum,
+ (Token != NULL) ? Token->Event : NULL, 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 match 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_CHANGED The MediaId does not match 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_NOTIFY);
+ 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_CHANGED The MediaId does not match 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;
+}
+
+/**
+ Set the erase start address through sync or async I/O request.
+
+ @param[in] Device A pointer to the SD_DEVICE instance.
+ @param[in] StartLba The starting logical block address to be erased.
+ @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
+SdEraseBlockStart (
+ IN SD_DEVICE *Device,
+ IN EFI_LBA StartLba,
+ IN EFI_BLOCK_IO2_TOKEN *Token,
+ IN BOOLEAN IsEnd
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
+ SD_REQUEST *EraseBlockStart;
+ EFI_TPL OldTpl;
+
+ EraseBlockStart = NULL;
+ PassThru = Device->Private->PassThru;
+
+ EraseBlockStart = AllocateZeroPool (sizeof (SD_REQUEST));
+ if (EraseBlockStart == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ EraseBlockStart->Signature = SD_REQUEST_SIGNATURE;
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ InsertTailList (&Device->Queue, &EraseBlockStart->Link);
+ gBS->RestoreTPL (OldTpl);
+ EraseBlockStart->Packet.SdMmcCmdBlk = &EraseBlockStart->SdMmcCmdBlk;
+ EraseBlockStart->Packet.SdMmcStatusBlk = &EraseBlockStart->SdMmcStatusBlk;
+ EraseBlockStart->Packet.Timeout = SD_GENERIC_TIMEOUT;
+
+ EraseBlockStart->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_START;
+ EraseBlockStart->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
+ EraseBlockStart->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+
+ if (Device->SectorAddressing) {
+ EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)StartLba;
+ } else {
+ EraseBlockStart->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (StartLba, Device->BlockMedia.BlockSize);
+ }
+
+ EraseBlockStart->IsEnd = IsEnd;
+ EraseBlockStart->Token = Token;
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ AsyncIoCallback,
+ EraseBlockStart,
+ &EraseBlockStart->Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ } else {
+ EraseBlockStart->Event = NULL;
+ }
+
+ Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockStart->Packet, EraseBlockStart->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) && (EraseBlockStart != NULL)) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlockStart->Link);
+ gBS->RestoreTPL (OldTpl);
+ if (EraseBlockStart->Event != NULL) {
+ gBS->CloseEvent (EraseBlockStart->Event);
+ }
+ FreePool (EraseBlockStart);
+ }
+ } else {
+ //
+ // For synchronous operation, free request whatever the execution result is.
+ //
+ if (EraseBlockStart != NULL) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlockStart->Link);
+ gBS->RestoreTPL (OldTpl);
+ FreePool (EraseBlockStart);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Set the erase end address through sync or async I/O request.
+
+ @param[in] Device A pointer to the SD_DEVICE instance.
+ @param[in] EndLba The ending logical block address to be erased.
+ @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
+SdEraseBlockEnd (
+ IN SD_DEVICE *Device,
+ IN EFI_LBA EndLba,
+ IN EFI_BLOCK_IO2_TOKEN *Token,
+ IN BOOLEAN IsEnd
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
+ SD_REQUEST *EraseBlockEnd;
+ EFI_TPL OldTpl;
+
+ EraseBlockEnd = NULL;
+ PassThru = Device->Private->PassThru;
+
+ EraseBlockEnd = AllocateZeroPool (sizeof (SD_REQUEST));
+ if (EraseBlockEnd == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ EraseBlockEnd->Signature = SD_REQUEST_SIGNATURE;
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ InsertTailList (&Device->Queue, &EraseBlockEnd->Link);
+ gBS->RestoreTPL (OldTpl);
+ EraseBlockEnd->Packet.SdMmcCmdBlk = &EraseBlockEnd->SdMmcCmdBlk;
+ EraseBlockEnd->Packet.SdMmcStatusBlk = &EraseBlockEnd->SdMmcStatusBlk;
+ EraseBlockEnd->Packet.Timeout = SD_GENERIC_TIMEOUT;
+
+ EraseBlockEnd->SdMmcCmdBlk.CommandIndex = SD_ERASE_WR_BLK_END;
+ EraseBlockEnd->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
+ EraseBlockEnd->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1;
+
+ if (Device->SectorAddressing) {
+ EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)EndLba;
+ } else {
+ EraseBlockEnd->SdMmcCmdBlk.CommandArgument = (UINT32)MultU64x32 (EndLba, Device->BlockMedia.BlockSize);
+ }
+
+ EraseBlockEnd->IsEnd = IsEnd;
+ EraseBlockEnd->Token = Token;
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ AsyncIoCallback,
+ EraseBlockEnd,
+ &EraseBlockEnd->Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ } else {
+ EraseBlockEnd->Event = NULL;
+ }
+
+ Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlockEnd->Packet, EraseBlockEnd->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) && (EraseBlockEnd != NULL)) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlockEnd->Link);
+ gBS->RestoreTPL (OldTpl);
+ if (EraseBlockEnd->Event != NULL) {
+ gBS->CloseEvent (EraseBlockEnd->Event);
+ }
+ FreePool (EraseBlockEnd);
+ }
+ } else {
+ //
+ // For synchronous operation, free request whatever the execution result is.
+ //
+ if (EraseBlockEnd != NULL) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlockEnd->Link);
+ gBS->RestoreTPL (OldTpl);
+ FreePool (EraseBlockEnd);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Erase specified blocks through sync or async I/O request.
+
+ @param[in] Device A pointer to the SD_DEVICE instance.
+ @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
+SdEraseBlock (
+ IN SD_DEVICE *Device,
+ IN EFI_BLOCK_IO2_TOKEN *Token,
+ IN BOOLEAN IsEnd
+ )
+{
+ EFI_STATUS Status;
+ EFI_SD_MMC_PASS_THRU_PROTOCOL *PassThru;
+ SD_REQUEST *EraseBlock;
+ EFI_TPL OldTpl;
+
+ EraseBlock = NULL;
+ PassThru = Device->Private->PassThru;
+
+ EraseBlock = AllocateZeroPool (sizeof (SD_REQUEST));
+ if (EraseBlock == NULL) {
+ Status = EFI_OUT_OF_RESOURCES;
+ goto Error;
+ }
+
+ EraseBlock->Signature = SD_REQUEST_SIGNATURE;
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ InsertTailList (&Device->Queue, &EraseBlock->Link);
+ gBS->RestoreTPL (OldTpl);
+ EraseBlock->Packet.SdMmcCmdBlk = &EraseBlock->SdMmcCmdBlk;
+ EraseBlock->Packet.SdMmcStatusBlk = &EraseBlock->SdMmcStatusBlk;
+ EraseBlock->Packet.Timeout = SD_GENERIC_TIMEOUT;
+
+ EraseBlock->SdMmcCmdBlk.CommandIndex = SD_ERASE;
+ EraseBlock->SdMmcCmdBlk.CommandType = SdMmcCommandTypeAc;
+ EraseBlock->SdMmcCmdBlk.ResponseType = SdMmcResponseTypeR1b;
+
+ EraseBlock->IsEnd = IsEnd;
+ EraseBlock->Token = Token;
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Status = gBS->CreateEvent (
+ EVT_NOTIFY_SIGNAL,
+ TPL_NOTIFY,
+ AsyncIoCallback,
+ EraseBlock,
+ &EraseBlock->Event
+ );
+ if (EFI_ERROR (Status)) {
+ goto Error;
+ }
+ } else {
+ EraseBlock->Event = NULL;
+ }
+
+ Status = PassThru->PassThru (PassThru, Device->Slot, &EraseBlock->Packet, EraseBlock->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) && (EraseBlock != NULL)) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlock->Link);
+ gBS->RestoreTPL (OldTpl);
+ if (EraseBlock->Event != NULL) {
+ gBS->CloseEvent (EraseBlock->Event);
+ }
+ FreePool (EraseBlock);
+ }
+ } else {
+ //
+ // For synchronous operation, free request whatever the execution result is.
+ //
+ if (EraseBlock != NULL) {
+ OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
+ RemoveEntryList (&EraseBlock->Link);
+ gBS->RestoreTPL (OldTpl);
+ FreePool (EraseBlock);
+ }
+ }
+
+ return Status;
+}
+
+/**
+ Erase a specified number of device blocks.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the erase request is for.
+ @param[in] Lba The starting logical block address to be
+ erased. The caller is responsible for erasing
+ only legitimate locations.
+ @param[in, out] Token A pointer to the token associated with the
+ transaction.
+ @param[in] Size The size in bytes to be erased. This must be
+ a multiple of the physical block size of the
+ device.
+
+ @retval EFI_SUCCESS The erase request was queued if Event is not
+ NULL. The data was erased correctly to the
+ device if the Event is NULL.to the device.
+ @retval EFI_WRITE_PROTECTED The device cannot be erased due to write
+ protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the erase operation.
+ @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
+ valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+**/
+EFI_STATUS
+EFIAPI
+SdEraseBlocks (
+ IN EFI_ERASE_BLOCK_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
+ IN UINTN Size
+ )
+{
+ EFI_STATUS Status;
+ EFI_BLOCK_IO_MEDIA *Media;
+ UINTN BlockSize;
+ UINTN BlockNum;
+ EFI_LBA LastLba;
+ SD_DEVICE *Device;
+
+ Status = EFI_SUCCESS;
+ Device = SD_DEVICE_DATA_FROM_ERASEBLK (This);
+ Media = &Device->BlockMedia;
+
+ if (MediaId != Media->MediaId) {
+ return EFI_MEDIA_CHANGED;
+ }
+
+ if (Media->ReadOnly) {
+ return EFI_WRITE_PROTECTED;
+ }
+
+ //
+ // Check parameters.
+ //
+ BlockSize = Media->BlockSize;
+ if ((Size % BlockSize) != 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ BlockNum = Size / BlockSize;
+ if ((Lba + BlockNum - 1) > Media->LastBlock) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ if ((Token != NULL) && (Token->Event != NULL)) {
+ Token->TransactionStatus = EFI_SUCCESS;
+ }
+
+ LastLba = Lba + BlockNum - 1;
+
+ Status = SdEraseBlockStart (Device, Lba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SdEraseBlockEnd (Device, LastLba, (EFI_BLOCK_IO2_TOKEN*)Token, FALSE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ Status = SdEraseBlock (Device, (EFI_BLOCK_IO2_TOKEN*)Token, TRUE);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ DEBUG ((
+ DEBUG_INFO,
+ "SdEraseBlocks(): Lba 0x%x BlkNo 0x%x Event %p with %r\n",
+ Lba,
+ BlockNum,
+ (Token != NULL) ? Token->Event : NULL,
+ Status
+ ));
+
+ return Status;
+}
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h new file mode 100644 index 000000000..b6b4c45f1 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdBlockIo.h @@ -0,0 +1,252 @@ +/** @file
+ Header file for SdDxe Driver.
+
+ This file defines common data structures, macro definitions and some module
+ internal function header files.
+
+ Copyright (c) 2015 - 2016, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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 match 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_CHANGED The MediaId does not match 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_CHANGED The MediaId does not match 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
+ );
+
+/**
+ Erase a specified number of device blocks.
+
+ @param[in] This Indicates a pointer to the calling context.
+ @param[in] MediaId The media ID that the erase request is for.
+ @param[in] Lba The starting logical block address to be
+ erased. The caller is responsible for erasing
+ only legitimate locations.
+ @param[in, out] Token A pointer to the token associated with the
+ transaction.
+ @param[in] Size The size in bytes to be erased. This must be
+ a multiple of the physical block size of the
+ device.
+
+ @retval EFI_SUCCESS The erase request was queued if Event is not
+ NULL. The data was erased correctly to the
+ device if the Event is NULL.to the device.
+ @retval EFI_WRITE_PROTECTED The device cannot be erased due to write
+ protection.
+ @retval EFI_DEVICE_ERROR The device reported an error while attempting
+ to perform the erase operation.
+ @retval EFI_INVALID_PARAMETER The erase request contains LBAs that are not
+ valid.
+ @retval EFI_NO_MEDIA There is no media in the device.
+ @retval EFI_MEDIA_CHANGED The MediaId is not for the current media.
+
+**/
+EFI_STATUS
+EFIAPI
+SdEraseBlocks (
+ IN EFI_ERASE_BLOCK_PROTOCOL *This,
+ IN UINT32 MediaId,
+ IN EFI_LBA Lba,
+ IN OUT EFI_ERASE_BLOCK_TOKEN *Token,
+ IN UINTN Size
+ );
+
+#endif
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.c b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.c new file mode 100644 index 000000000..6563f7232 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.c @@ -0,0 +1,132 @@ +/** @file
+ Implement the EFI_DISK_INFO_PROTOCOL interface on SD memory card devices.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include "SdDxe.h"
+
+/**
+ Provides inquiry information for the controller type.
+
+ This function is used by the driver entity to get inquiry data. Data format of
+ Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in,out] InquiryData Pointer to a buffer for the inquiry data.
+ @param[in,out] InquiryDataSize Pointer to the value for the inquiry data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device.
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ )
+{
+ EFI_STATUS Status;
+ SD_DEVICE *Device;
+
+ Device = SD_DEVICE_DATA_FROM_DISKINFO (This);
+
+ if (*InquiryDataSize >= sizeof (Device->Cid)) {
+ Status = EFI_SUCCESS;
+ CopyMem (InquiryData, &Device->Cid, sizeof (Device->Cid));
+ } else {
+ Status = EFI_BUFFER_TOO_SMALL;
+ }
+
+ *InquiryDataSize = sizeof (Device->Cid);
+
+ return Status;
+}
+
+/**
+ Provides identify information for the controller type.
+
+ This function is used by the driver entity to get identify data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
+ instance.
+ @param[in,out] IdentifyData Pointer to a buffer for the identify data.
+ @param[in,out] IdentifyDataSize Pointer to the value for the identify data
+ size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device.
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Provides sense data information for the controller type.
+
+ This function is used by the driver entity to get sense data. Data format of
+ Sense data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in,out] SenseData Pointer to the SenseData.
+ @param[in,out] SenseDataSize Size of SenseData in bytes.
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ )
+{
+ return EFI_NOT_FOUND;
+}
+
+/**
+ Provides IDE channel and device information for the interface.
+
+ This function is used by the driver entity to get controller information.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
+
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
+ @retval EFI_UNSUPPORTED This is not an IDE device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ )
+{
+ return EFI_UNSUPPORTED;
+}
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.h b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.h new file mode 100644 index 000000000..64e2f77c9 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDiskInfo.h @@ -0,0 +1,109 @@ +/** @file
+ Header file for EFI_DISK_INFO_PROTOCOL interface on SD memory card devices.
+
+ Copyright (c) 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#ifndef _SD_DISKINFO_H_
+#define _SD_DISKINFO_H_
+
+/**
+ Provides inquiry information for the controller type.
+
+ This function is used by the driver entity to get inquiry data. Data format of
+ Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in,out] InquiryData Pointer to a buffer for the inquiry data.
+ @param[in,out] InquiryDataSize Pointer to the value for the inquiry data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading InquiryData from device.
+ @retval EFI_BUFFER_TOO_SMALL InquiryDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoInquiry (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *InquiryData,
+ IN OUT UINT32 *InquiryDataSize
+ );
+
+/**
+ Provides identify information for the controller type.
+
+ This function is used by the driver entity to get identify data. Data format
+ of Identify data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL
+ instance.
+ @param[in,out] IdentifyData Pointer to a buffer for the identify data.
+ @param[in,out] IdentifyDataSize Pointer to the value for the identify data
+ size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading IdentifyData from device.
+ @retval EFI_BUFFER_TOO_SMALL IdentifyDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoIdentify (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *IdentifyData,
+ IN OUT UINT32 *IdentifyDataSize
+ );
+
+/**
+ Provides sense data information for the controller type.
+
+ This function is used by the driver entity to get sense data. Data format of
+ Sense data is defined by the Interface GUID.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[in,out] SenseData Pointer to the SenseData.
+ @param[in,out] SenseDataSize Size of SenseData in bytes.
+ @param[out] SenseDataNumber Pointer to the value for the sense data size.
+
+ @retval EFI_SUCCESS The command was accepted without any errors.
+ @retval EFI_NOT_FOUND Device does not support this data class.
+ @retval EFI_DEVICE_ERROR Error reading SenseData from device.
+ @retval EFI_BUFFER_TOO_SMALL SenseDataSize not big enough.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoSenseData (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ IN OUT VOID *SenseData,
+ IN OUT UINT32 *SenseDataSize,
+ OUT UINT8 *SenseDataNumber
+ );
+
+/**
+ Provides IDE channel and device information for the interface.
+
+ This function is used by the driver entity to get controller information.
+
+ @param[in] This Pointer to the EFI_DISK_INFO_PROTOCOL instance.
+ @param[out] IdeChannel Pointer to the Ide Channel number. Primary or secondary.
+ @param[out] IdeDevice Pointer to the Ide Device number. Master or slave.
+
+ @retval EFI_SUCCESS IdeChannel and IdeDevice are valid.
+ @retval EFI_UNSUPPORTED This is not an IDE device.
+
+**/
+EFI_STATUS
+EFIAPI
+SdDiskInfoWhichIde (
+ IN EFI_DISK_INFO_PROTOCOL *This,
+ OUT UINT32 *IdeChannel,
+ OUT UINT32 *IdeDevice
+ );
+
+#endif
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c new file mode 100644 index 000000000..73bcc181c --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.c @@ -0,0 +1,908 @@ +/** @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 - 2018, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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
+ },
+ { // EraseBlock
+ EFI_ERASE_BLOCK_PROTOCOL_REVISION,
+ 1,
+ SdEraseBlocks
+ },
+ { // DiskInfo
+ EFI_DISK_INFO_SD_MMC_INTERFACE_GUID,
+ SdDiskInfoInquiry,
+ SdDiskInfoIdentify,
+ SdDiskInfoSenseData,
+ SdDiskInfoWhichIde
+ },
+ { // 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));
+
+ AsciiStrToUnicodeStrS (String, Device->ModelName, sizeof (Device->ModelName) / sizeof (Device->ModelName[0]));
+
+ 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;
+
+ if (Csd->EraseBlkEn) {
+ Device->EraseBlock.EraseLengthGranularity = 1;
+ } else {
+ Device->EraseBlock.EraseLengthGranularity = (Csd->SectorSize + 1) * (1 << (Csd->WriteBlLen - 9));
+ }
+
+ 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",
+ gSdDxeComponentName2.SupportedLanguages,
+ &Device->ControllerNameTable,
+ Device->ModelName,
+ FALSE
+ );
+
+ Status = gBS->InstallMultipleProtocolInterfaces (
+ &Device->Handle,
+ &gEfiDevicePathProtocolGuid,
+ Device->DevicePath,
+ &gEfiBlockIoProtocolGuid,
+ &Device->BlockIo,
+ &gEfiBlockIo2ProtocolGuid,
+ &Device->BlockIo2,
+ &gEfiEraseBlockProtocolGuid,
+ &Device->EraseBlock,
+ &gEfiDiskInfoProtocolGuid,
+ &Device->DiskInfo,
+ 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 failed 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_NOTIFY);
+ 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,
+ &gEfiEraseBlockProtocolGuid,
+ &Device->EraseBlock,
+ &gEfiDiskInfoProtocolGuid,
+ &Device->DiskInfo,
+ 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;
+}
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h new file mode 100644 index 000000000..ff740a521 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.h @@ -0,0 +1,475 @@ +/** @file
+ Header file for SdDxe Driver.
+
+ This file defines common data structures, macro definitions and some module
+ internal function header files.
+
+ Copyright (c) 2015 - 2017, Intel Corporation. All rights reserved.<BR>
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#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/EraseBlock.h>
+#include <Protocol/DiskInfo.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"
+#include "SdDiskInfo.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)
+
+#define SD_DEVICE_DATA_FROM_ERASEBLK(a) \
+ CR(a, SD_DEVICE, EraseBlock, SD_DEVICE_SIGNATURE)
+
+#define SD_DEVICE_DATA_FROM_DISKINFO(a) \
+ CR(a, SD_DEVICE, DiskInfo, 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;
+ EFI_ERASE_BLOCK_PROTOCOL EraseBlock;
+ EFI_DISK_INFO_PROTOCOL DiskInfo;
+
+ 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 failed 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
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf new file mode 100644 index 000000000..69b856b66 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.inf @@ -0,0 +1,64 @@ +## @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 - 2018, Intel Corporation. All rights reserved.<BR>
+#
+# SPDX-License-Identifier: BSD-2-Clause-Patent
+#
+#
+##
+
+[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 EBC
+#
+# DRIVER_BINDING = gSdDxeDriverBinding
+# COMPONENT_NAME = gSdDxeComponentName
+# COMPONENT_NAME2 = gSdDxeComponentName2
+#
+
+[Sources.common]
+ ComponentName.c
+ SdDxe.c
+ SdDxe.h
+ SdBlockIo.c
+ SdBlockIo.h
+ SdDiskInfo.c
+ SdDiskInfo.h
+
+[Packages]
+ MdePkg/MdePkg.dec
+
+[LibraryClasses]
+ DevicePathLib
+ UefiBootServicesTableLib
+ MemoryAllocationLib
+ BaseMemoryLib
+ UefiLib
+ BaseLib
+ UefiDriverEntryPoint
+ DebugLib
+
+[Protocols]
+ gEfiSdMmcPassThruProtocolGuid ## TO_START
+ gEfiBlockIoProtocolGuid ## BY_START
+ gEfiBlockIo2ProtocolGuid ## BY_START
+ gEfiEraseBlockProtocolGuid ## BY_START
+ gEfiDiskInfoProtocolGuid ## BY_START
+ ## TO_START
+ ## BY_START
+ gEfiDevicePathProtocolGuid
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni new file mode 100644 index 000000000..eb8ebd5a3 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxe.uni @@ -0,0 +1,15 @@ +// /** @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>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#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."
+
diff --git a/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni new file mode 100644 index 000000000..eb8ebd5a3 --- /dev/null +++ b/roms/edk2/MdeModulePkg/Bus/Sd/SdDxe/SdDxeExtra.uni @@ -0,0 +1,15 @@ +// /** @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>
+//
+// SPDX-License-Identifier: BSD-2-Clause-Patent
+//
+// **/
+
+
+#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."
+
|