The MmcDxe is not ARM architecture specific. git-svn-id: https://edk2.svn.sourceforge.net/svnroot/edk2/trunk/edk2@11725 6f19259b-4bc3-4df7-8a09-765794883524
		
			
				
	
	
		
			216 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			216 lines
		
	
	
		
			7.7 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
/** @file
 | 
						|
  Diagnostics Protocol implementation for the MMC DXE driver
 | 
						|
 | 
						|
  Copyright (c) 2011, ARM Limited. All rights reserved.
 | 
						|
  
 | 
						|
  This program and the accompanying materials                          
 | 
						|
  are licensed and made available under the terms and conditions of the BSD License         
 | 
						|
  which accompanies this distribution.  The full text of the license may be found at        
 | 
						|
  http://opensource.org/licenses/bsd-license.php                                            
 | 
						|
 | 
						|
  THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,                     
 | 
						|
  WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.             
 | 
						|
 | 
						|
**/
 | 
						|
 | 
						|
#include <Uefi.h>
 | 
						|
#include <Library/DebugLib.h>
 | 
						|
#include <Library/BaseMemoryLib.h>
 | 
						|
#include <Library/MemoryAllocationLib.h>
 | 
						|
 | 
						|
#include "Mmc.h"
 | 
						|
 | 
						|
#define DIAGNOSTIC_LOGBUFFER_MAXCHAR  1024
 | 
						|
 | 
						|
CHAR16* mLogBuffer = NULL;
 | 
						|
UINTN   mLogRemainChar = 0;
 | 
						|
 | 
						|
CHAR16* DiagnosticInitLog(UINTN MaxBufferChar) {
 | 
						|
    mLogRemainChar = MaxBufferChar;
 | 
						|
    mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));
 | 
						|
    return mLogBuffer;
 | 
						|
}
 | 
						|
 | 
						|
UINTN DiagnosticLog(CONST CHAR16* Str) {
 | 
						|
    UINTN len = StrLen (Str);
 | 
						|
    if (len <= mLogRemainChar) {
 | 
						|
        mLogRemainChar -= len;
 | 
						|
        StrCpy (mLogBuffer, Str);
 | 
						|
        mLogBuffer += len;
 | 
						|
        return len;
 | 
						|
    } else {
 | 
						|
        return 0;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
VOID GenerateRandomBuffer(VOID* Buffer, UINTN BufferSize) {
 | 
						|
    UINT64 i;
 | 
						|
    UINT64* Buffer64 = (UINT64*)Buffer;
 | 
						|
 | 
						|
    for (i = 0; i < (BufferSize >> 3); i++) {
 | 
						|
        *Buffer64 = i | (~i << 32);
 | 
						|
        Buffer64++;
 | 
						|
    }
 | 
						|
}
 | 
						|
 | 
						|
BOOLEAN CompareBuffer(VOID *BufferA, VOID *BufferB, UINTN BufferSize) {
 | 
						|
    UINTN i;
 | 
						|
    UINT64* BufferA64 = (UINT64*)BufferA;
 | 
						|
    UINT64* BufferB64 = (UINT64*)BufferB;
 | 
						|
 | 
						|
    for (i = 0; i < (BufferSize >> 3); i++) {
 | 
						|
        if (*BufferA64 != *BufferB64) {
 | 
						|
            DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));
 | 
						|
            DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));
 | 
						|
            return FALSE;
 | 
						|
        }
 | 
						|
        BufferA64++;
 | 
						|
        BufferB64++;
 | 
						|
    }
 | 
						|
    return TRUE;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS MmcReadWriteDataTest(MMC_HOST_INSTANCE *MmcHostInstance, EFI_LBA Lba, UINTN BufferSize) {
 | 
						|
    VOID                        *BackBuffer;
 | 
						|
    VOID                        *WriteBuffer;
 | 
						|
    VOID                        *ReadBuffer;
 | 
						|
    EFI_STATUS                  Status;
 | 
						|
    
 | 
						|
    // Check if a Media is Present
 | 
						|
    if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
 | 
						|
        DiagnosticLog(L"ERROR: No Media Present\n");
 | 
						|
        return EFI_NO_MEDIA;
 | 
						|
    }
 | 
						|
 | 
						|
    if (MmcHostInstance->State != MmcTransferState) {
 | 
						|
        DiagnosticLog(L"ERROR: Not ready for Transfer state\n");
 | 
						|
        return EFI_NOT_READY;
 | 
						|
    }
 | 
						|
 | 
						|
    BackBuffer = AllocatePool(BufferSize);
 | 
						|
    WriteBuffer = AllocatePool(BufferSize);
 | 
						|
    ReadBuffer = AllocatePool(BufferSize);
 | 
						|
 | 
						|
    // Read (and save) buffer at a specific location
 | 
						|
    Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);
 | 
						|
    if (Status != EFI_SUCCESS) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Read Block (1)\n");
 | 
						|
        return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Write buffer at the same location
 | 
						|
    GenerateRandomBuffer(WriteBuffer,BufferSize);
 | 
						|
    Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);
 | 
						|
    if (Status != EFI_SUCCESS) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Write Block (1)\n");
 | 
						|
        return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Read the buffer at the same location
 | 
						|
    Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);
 | 
						|
    if (Status != EFI_SUCCESS) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Read Block (2)\n");
 | 
						|
        return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check that is conform
 | 
						|
    if (!CompareBuffer(ReadBuffer,WriteBuffer,BufferSize)) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Read/Write Block (1)\n");
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    // Restore content at the original location
 | 
						|
    Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);
 | 
						|
    if (Status != EFI_SUCCESS) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Write Block (2)\n");
 | 
						|
        return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Read the restored content
 | 
						|
    Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);
 | 
						|
    if (Status != EFI_SUCCESS) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Read Block (3)\n");
 | 
						|
        return Status;
 | 
						|
    }
 | 
						|
 | 
						|
    // Check the content is correct
 | 
						|
    if (!CompareBuffer(ReadBuffer,BackBuffer,BufferSize)) {
 | 
						|
        DiagnosticLog(L"ERROR: Fail to Read/Write Block (2)\n");
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    return EFI_SUCCESS;
 | 
						|
}
 | 
						|
 | 
						|
EFI_STATUS
 | 
						|
EFIAPI
 | 
						|
MmcDriverDiagnosticsRunDiagnostics (
 | 
						|
  IN  EFI_DRIVER_DIAGNOSTICS_PROTOCOL               *This,
 | 
						|
  IN  EFI_HANDLE                                    ControllerHandle,
 | 
						|
  IN  EFI_HANDLE                                    ChildHandle  OPTIONAL,
 | 
						|
  IN  EFI_DRIVER_DIAGNOSTIC_TYPE                    DiagnosticType,
 | 
						|
  IN  CHAR8                                         *Language,
 | 
						|
  OUT EFI_GUID                                      **ErrorType,
 | 
						|
  OUT UINTN                                         *BufferSize,
 | 
						|
  OUT CHAR16                                        **Buffer
 | 
						|
  )
 | 
						|
{
 | 
						|
    LIST_ENTRY          *CurrentLink;
 | 
						|
    MMC_HOST_INSTANCE   *MmcHostInstance;
 | 
						|
    EFI_STATUS          Status;
 | 
						|
 | 
						|
    if (Language         == NULL ||
 | 
						|
        ErrorType        == NULL ||
 | 
						|
        Buffer           == NULL ||
 | 
						|
        ControllerHandle == NULL ||
 | 
						|
        BufferSize       == NULL) {
 | 
						|
        return EFI_INVALID_PARAMETER;
 | 
						|
    }
 | 
						|
 | 
						|
    Status = EFI_SUCCESS;
 | 
						|
    *ErrorType  = NULL;
 | 
						|
    *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;
 | 
						|
    *Buffer = DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR);
 | 
						|
 | 
						|
    DiagnosticLog(L"MMC Driver Diagnostics\n");
 | 
						|
 | 
						|
    // For each MMC instance
 | 
						|
    CurrentLink = mMmcHostPool.ForwardLink;
 | 
						|
    while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {
 | 
						|
        MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);
 | 
						|
        ASSERT(MmcHostInstance != NULL);
 | 
						|
 | 
						|
        // LBA=1 Size=BlockSize
 | 
						|
        DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block\n");
 | 
						|
        Status = MmcReadWriteDataTest(MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
 | 
						|
        // LBA=2 Size=BlockSize
 | 
						|
        DiagnosticLog(L"MMC Driver Diagnostics - Test: Second Block\n");
 | 
						|
        Status = MmcReadWriteDataTest(MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
 | 
						|
        // LBA=10 Size=BlockSize
 | 
						|
        DiagnosticLog(L"MMC Driver Diagnostics - Test: Any Block\n");
 | 
						|
        Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
 | 
						|
        // LBA=LastBlock Size=BlockSize
 | 
						|
        DiagnosticLog(L"MMC Driver Diagnostics - Test: Last Block\n");
 | 
						|
        Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
 | 
						|
        // LBA=1 Size=2*BlockSize
 | 
						|
        DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
 | 
						|
        Status = MmcReadWriteDataTest(MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);
 | 
						|
 | 
						|
        CurrentLink = CurrentLink->ForwardLink;
 | 
						|
    }
 | 
						|
 | 
						|
    return Status;
 | 
						|
}
 | 
						|
 | 
						|
//
 | 
						|
// EFI Driver Diagnostics 2 Protocol
 | 
						|
//
 | 
						|
GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {
 | 
						|
  (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,
 | 
						|
  "en"
 | 
						|
};
 |