diff options
author | Leif Lindholm <leif.lindholm@linaro.org> | 2014-05-22 10:30:46 +0100 |
---|---|---|
committer | Leif Lindholm <leif.lindholm@linaro.org> | 2014-05-22 10:30:46 +0100 |
commit | a50bf4634f25834e3a99078eba7dec8fa7e10418 (patch) | |
tree | 01022bad044717e3006fd560f064540e8e998d35 | |
parent | 7fea8ff365808402457dabd5a0e52ac0f2529025 (diff) | |
parent | 965e4e4d9a02b2d50098d7356072bc5f98b96424 (diff) |
Merge remote-tracking branch 'rmt-1/linaro-topic-misc' into release-prep
-rw-r--r-- | .gitignore | 22 | ||||
-rw-r--r-- | EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c | 305 | ||||
-rw-r--r-- | MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c | 9 | ||||
l--------- | edk2 | 1 |
4 files changed, 337 insertions, 0 deletions
diff --git a/.gitignore b/.gitignore new file mode 100644 index 000000000..70df4bdd1 --- /dev/null +++ b/.gitignore @@ -0,0 +1,22 @@ +*.d +*.o +*.pyc +BaseTools/Source/C/VfrCompile/EfiVfrParser.cpp +BaseTools/Source/C/VfrCompile/EfiVfrParser.h +BaseTools/Source/C/VfrCompile/Pccts/antlr/antlr +BaseTools/Source/C/VfrCompile/Pccts/dlg/dlg +BaseTools/Source/C/VfrCompile/VfrLexer.cpp +BaseTools/Source/C/VfrCompile/VfrLexer.h +BaseTools/Source/C/VfrCompile/VfrParser.dlg +BaseTools/Source/C/VfrCompile/VfrSyntax.cpp +BaseTools/Source/C/VfrCompile/VfrTokens.h +BaseTools/Source/C/bin/ +BaseTools/Source/C/libs/ +Build/ +Conf/.cache/ +Conf/BuildEnv.sh +Conf/build_rule.txt +Conf/target.txt +Conf/tools_def.txt +PandaBoardPkg/Tools/chtool +tmp.bin diff --git a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c index 04c82613d..8e13e05c3 100644 --- a/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c +++ b/EmbeddedPkg/Universal/MmcDxe/MmcBlockIo.c @@ -14,9 +14,50 @@ #include <Library/BaseMemoryLib.h>
#include <Library/TimerLib.h>
+#include <Library/UefiBootServicesTableLib.h> #include "Mmc.h"
+#define MAX_RETRY_COUNT 1000
+#define CMD_RETRY_COUNT 20
+
+#define TPL_FIRMWARE_INTERRUPTS ((EFI_TPL)((int) TPL_NOTIFY + 1)) +#define TPL_FOR_MMC_BLOCK_IO TPL_FIRMWARE_INTERRUPTS + +EFI_TPL +CurrentTpl() { + const EFI_TPL Current = gBS->RaiseTPL(TPL_HIGH_LEVEL) ; + gBS->RestoreTPL(Current) ; + return Current ; +} + +EFI_TPL +RaiseTplIfLow() { + EFI_TPL Current = CurrentTpl() ; + /* + UEFI Spec states: + TPL_CALLBACK Interrupts code executing below TPL_CALLBACK level. Long + term operations (such as file system operations and disk I/O) can occur + at this level. + TPL_NOTIFY Interrupts code executing below TPL_NOTIFY level. Blocking is + not allowed at this level. Code executes to completion and returns. If + code requires more processing, it needs to signal an event to wait to + obtain control again at whatever level it requires. This level is + typically used to process low level IO to or from a device. + (Firmware Interrupts) This level is internal to the firmware . It is the + level at which internal interrupts occur. Code running at this level + interrupts code running at the TPL_NOTIFY level (or lower levels). If + the interrupt requires extended time to complete, firmware signals + another event (or events) to perform the longer term operations so that + other interrupts can occur. + */ + if (Current < TPL_FOR_MMC_BLOCK_IO) { + Current = gBS->RaiseTPL(TPL_FOR_MMC_BLOCK_IO) ; + } + return Current ; +} + + EFI_STATUS
MmcNotifyState (
IN MMC_HOST_INSTANCE *MmcHostInstance,
@@ -64,6 +105,265 @@ MmcGetCardStatus ( EFI_STATUS
EFIAPI
+MmcIdentificationMode (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ EFI_STATUS Status;
+ UINT32 Response[4];
+ UINTN Timeout;
+ UINTN CmdArg;
+ BOOLEAN IsHCS;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+
+ MmcHost = MmcHostInstance->MmcHost;
+ CmdArg = 0;
+ IsHCS = FALSE;
+
+ if (MmcHost == NULL) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ // We can get into this function if we restart the identification mode
+ if (MmcHostInstance->State == MmcHwInitializationState) {
+ // Initialize the MMC Host HW
+ Status = MmcNotifyState (MmcHostInstance, MmcHwInitializationState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcHwInitializationState\n"));
+ return Status;
+ }
+ }
+
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD0, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD0): Error\n"));
+ return Status;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcIdleState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdleState\n"));
+ return Status;
+ }
+
+ // Are we using SDIO ?
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD5, 0);
+ +#if 1 // Added for Panda Board + /* It seems few SD cards need some time to recover from this command? */ + MicroSecondDelay(1000); +#endif + + if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD5): Error - SDIO not supported.\n"));
+ return EFI_UNSUPPORTED;
+ }
+
+ // Check which kind of card we are using. Ver2.00 or later SD Memory Card (PL180 is SD v1.1)
+ CmdArg = (0x0UL << 12 | BIT8 | 0xCEUL << 0);
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD8, CmdArg);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_ERROR, "Card is SD2.0 => Supports high capacity\n"));
+ IsHCS = TRUE;
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_R7, Response);
+ PrintResponseR1 (Response[0]);
+ //check if it is valid response
+ if (Response[0] != CmdArg) {
+ DEBUG ((EFI_D_ERROR, "The Card is not usable\n"));
+ return EFI_UNSUPPORTED;
+ }
+ } else {
+ DEBUG ((EFI_D_ERROR, "Not a SD2.0 Card\n"));
+ }
+
+ // We need to wait for the MMC or SD card is ready => (gCardInfo.OCRData.PowerUp == 1)
+ Timeout = MAX_RETRY_COUNT;
+ while (Timeout > 0) {
+ // SD Card or MMC Card ? CMD55 indicates to the card that the next command is an application specific command
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD55, 0);
+ if (Status == EFI_SUCCESS) {
+ DEBUG ((EFI_D_INFO, "Card should be SD\n"));
+ if (IsHCS) {
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2;
+ } else {
+ MmcHostInstance->CardInfo.CardType = SD_CARD;
+ }
+
+ // Note: The first time CmdArg will be zero
+ CmdArg = ((UINTN *) &(MmcHostInstance->CardInfo.OCRData))[0];
+ if (IsHCS) {
+ CmdArg |= BIT30;
+ }
+ Status = MmcHost->SendCommand (MmcHost, MMC_ACMD41, CmdArg);
+ if (!EFI_ERROR (Status)) {
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
+ }
+ } else {
+ DEBUG ((EFI_D_INFO, "Card should be MMC\n"));
+ MmcHostInstance->CardInfo.CardType = MMC_CARD;
+
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD1, 0x800000);
+ if (!EFI_ERROR (Status)) {
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_OCR, Response);
+ ((UINT32 *) &(MmcHostInstance->CardInfo.OCRData))[0] = Response[0];
+ }
+ }
+
+ if (!EFI_ERROR (Status)) {
+ if (!MmcHostInstance->CardInfo.OCRData.PowerUp) {
+ MicroSecondDelay (1);
+ Timeout--;
+ } else {
+ if ((MmcHostInstance->CardInfo.CardType == SD_CARD_2) && (MmcHostInstance->CardInfo.OCRData.AccessMode & BIT1)) {
+ MmcHostInstance->CardInfo.CardType = SD_CARD_2_HIGH;
+ DEBUG ((EFI_D_ERROR, "High capacity card.\n"));
+ }
+ break; // The MMC/SD card is ready. Continue the Identification Mode
+ }
+ } else {
+ MicroSecondDelay (1);
+ Timeout--;
+ }
+ }
+
+ if (Timeout == 0) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(): No Card\n"));
+ return EFI_NO_MEDIA;
+ } else {
+ PrintOCR (Response[0]);
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcReadyState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcReadyState\n"));
+ return Status;
+ }
+
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD2, 0);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD2): Error\n"));
+ return Status;
+ }
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CID, Response);
+ PrintCID (Response);
+
+ Status = MmcNotifyState (MmcHostInstance, MmcIdentificationState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcIdentificationState\n"));
+ return Status;
+ }
+
+ //
+ // Note, SD specifications say that "if the command execution causes a state change, it
+ // will be visible to the host in the response to the next command"
+ // The status returned for this CMD3 will be 2 - identification
+ //
+ CmdArg = 1;
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD3, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode(MMC_CMD3): Error\n"));
+ return Status;
+ }
+
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_RCA, Response);
+ PrintRCA (Response[0]);
+
+ // For MMC card, RCA is assigned by CMD3 while CMD3 dumps the RCA for SD card
+ if (MmcHostInstance->CardInfo.CardType != MMC_CARD) {
+ MmcHostInstance->CardInfo.RCA = Response[0] >> 16;
+ } else {
+ MmcHostInstance->CardInfo.RCA = CmdArg;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcStandByState);
+ if (EFI_ERROR (Status)) {
+ DEBUG ((EFI_D_ERROR, "MmcIdentificationMode() : Error MmcStandByState\n"));
+ return Status;
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS InitializeMmcDevice (
+ IN MMC_HOST_INSTANCE *MmcHostInstance
+ )
+{
+ UINT32 Response[4];
+ EFI_STATUS Status;
+ UINTN CardSize, NumBlocks, BlockSize, CmdArg;
+ EFI_MMC_HOST_PROTOCOL *MmcHost;
+ UINTN BlockCount;
+
+ BlockCount = 1;
+ MmcHost = MmcHostInstance->MmcHost;
+
+ MmcIdentificationMode (MmcHostInstance);
+
+ //Send a command to get Card specific data
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD9, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD9): Error, Status=%r\n", Status));
+ return Status;
+ }
+ //Read Response
+ MmcHost->ReceiveResponse (MmcHost, MMC_RESPONSE_TYPE_CSD, Response);
+ PrintCSD (Response);
+
+ if (MmcHostInstance->CardInfo.CardType == SD_CARD_2_HIGH) {
+ CardSize = HC_MMC_CSD_GET_DEVICESIZE (Response);
+ NumBlocks = ((CardSize + 1) * 1024);
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
+ } else {
+ CardSize = MMC_CSD_GET_DEVICESIZE (Response);
+ NumBlocks = (CardSize + 1) * (1 << (MMC_CSD_GET_DEVICESIZEMULT (Response) + 2));
+ BlockSize = 1 << MMC_CSD_GET_READBLLEN (Response);
+ }
+
+ //For >=2G card, BlockSize may be 1K, but the transfer size is 512 bytes.
+ if (BlockSize > 512) {
+ NumBlocks = MultU64x32 (NumBlocks, BlockSize/512);
+ BlockSize = 512;
+ }
+
+ MmcHostInstance->BlockIo.Media->LastBlock = (NumBlocks - 1);
+ MmcHostInstance->BlockIo.Media->BlockSize = BlockSize;
+ MmcHostInstance->BlockIo.Media->ReadOnly = MmcHost->IsReadOnly (MmcHost);
+ MmcHostInstance->BlockIo.Media->MediaPresent = TRUE;
+ MmcHostInstance->BlockIo.Media->MediaId++;
+
+ CmdArg = MmcHostInstance->CardInfo.RCA << 16;
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD7, CmdArg);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD7): Error and Status = %r\n", Status));
+ return Status;
+ }
+
+ Status = MmcNotifyState (MmcHostInstance, MmcTransferState);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "InitializeMmcDevice(): Error MmcTransferState\n"));
+ return Status;
+ }
+
+ // Set Block Length
+ Status = MmcHost->SendCommand (MmcHost, MMC_CMD16, MmcHostInstance->BlockIo.Media->BlockSize);
+ if (EFI_ERROR (Status)) {
+ DEBUG((EFI_D_ERROR, "InitializeMmcDevice(MMC_CMD16): Error MmcHostInstance->BlockIo.Media->BlockSize: %d and Error = %r\n",
+ MmcHostInstance->BlockIo.Media->BlockSize, Status));
+ return Status;
+ }
+
+ // Block Count (not used). Could return an error for SD card
+ if (MmcHostInstance->CardInfo.CardType == MMC_CARD) {
+ MmcHost->SendCommand (MmcHost, MMC_CMD23, BlockCount);
+ }
+
+ return EFI_SUCCESS;
+}
+
+EFI_STATUS
+EFIAPI
MmcReset (
IN EFI_BLOCK_IO_PROTOCOL *This,
IN BOOLEAN ExtendedVerification
@@ -146,6 +446,7 @@ MmcIoBlocks ( EFI_MMC_HOST_PROTOCOL *MmcHost;
UINTN BytesRemainingToBeTransfered;
UINTN BlockCount;
+ EFI_TPL Tpl; BlockCount = 1;
MmcHostInstance = MMC_HOST_INSTANCE_FROM_BLOCK_IO_THIS (This);
@@ -225,8 +526,11 @@ MmcIoBlocks ( // Write a single block
Cmd = MMC_CMD24;
}
+ // Raise Tpl to protect against Timer events between command and block IO + Tpl = RaiseTplIfLow() ; Status = MmcHost->SendCommand (MmcHost, Cmd, CmdArg);
if (EFI_ERROR (Status)) {
+ gBS->RestoreTPL(Tpl); DEBUG ((EFI_D_ERROR, "MmcIoBlocks(MMC_CMD%d): Error %r\n", Cmd, Status));
return Status;
}
@@ -234,6 +538,7 @@ MmcIoBlocks ( if (Transfer == MMC_IOBLOCKS_READ) {
// Read one block of Data
Status = MmcHost->ReadBlockData (MmcHost, Lba, This->Media->BlockSize, Buffer);
+ gBS->RestoreTPL(Tpl) ; if (EFI_ERROR (Status)) {
DEBUG ((EFI_D_BLKIO, "MmcIoBlocks(): Error Read Block Data and Status = %r\n", Status));
MmcStopTransmission (MmcHost);
diff --git a/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c b/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c index a35b4f2d0..5134310d4 100644 --- a/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c +++ b/MdeModulePkg/Universal/Disk/PartitionDxe/Mbr.c @@ -157,6 +157,15 @@ PartitionInstallMbrChildHandles ( BlockSize,
Mbr
);
+ + // RMH - hack - Linaro's development boards use SD cards, currently we have + // a problem where each unique SD card has a different UUID when created + // with linaro-media-create / linaro-android-media create. + // This means that no one Boot Device configuration can boot Linaro images + // without some manual intervention from the user. + // This hack will zero the signature (UUID) read from the card. + ZeroMem(&(Mbr->UniqueMbrSignature[0]), sizeof (Mbr->UniqueMbrSignature)); + if (EFI_ERROR (Status)) {
Found = Status;
goto Done;
@@ -0,0 +1 @@ +.
\ No newline at end of file |