2 Diagnostics Protocol implementation for the MMC DXE driver
4 Copyright (c) 2011, ARM Limited. All rights reserved.
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
17 #include <Library/DebugLib.h>
18 #include <Library/BaseMemoryLib.h>
19 #include <Library/MemoryAllocationLib.h>
23 #define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024
25 CHAR16
* mLogBuffer
= NULL
;
26 UINTN mLogRemainChar
= 0;
28 CHAR16
* DiagnosticInitLog(UINTN MaxBufferChar
) {
29 mLogRemainChar
= MaxBufferChar
;
30 mLogBuffer
= AllocatePool ((UINTN
)MaxBufferChar
* sizeof(CHAR16
));
34 UINTN
DiagnosticLog(CONST CHAR16
* Str
) {
35 UINTN len
= StrLen (Str
);
36 if (len
<= mLogRemainChar
) {
37 mLogRemainChar
-= len
;
38 StrCpy (mLogBuffer
, Str
);
46 VOID
GenerateRandomBuffer(VOID
* Buffer
, UINTN BufferSize
) {
48 UINT64
* Buffer64
= (UINT64
*)Buffer
;
50 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
51 *Buffer64
= i
| (~i
<< 32);
56 BOOLEAN
CompareBuffer(VOID
*BufferA
, VOID
*BufferB
, UINTN BufferSize
) {
58 UINT64
* BufferA64
= (UINT64
*)BufferA
;
59 UINT64
* BufferB64
= (UINT64
*)BufferB
;
61 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
62 if (*BufferA64
!= *BufferB64
) {
63 DEBUG((EFI_D_ERROR
, "CompareBuffer: Error at %i", i
));
64 DEBUG((EFI_D_ERROR
, "(0x%lX) != (0x%lX)\n", *BufferA64
, *BufferB64
));
73 EFI_STATUS
MmcReadWriteDataTest(MMC_HOST_INSTANCE
*MmcHostInstance
, EFI_LBA Lba
, UINTN BufferSize
) {
79 // Check if a Media is Present
80 if (!MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
81 DiagnosticLog(L
"ERROR: No Media Present\n");
85 if (MmcHostInstance
->State
!= MmcTransferState
) {
86 DiagnosticLog(L
"ERROR: Not ready for Transfer state\n");
90 BackBuffer
= AllocatePool(BufferSize
);
91 WriteBuffer
= AllocatePool(BufferSize
);
92 ReadBuffer
= AllocatePool(BufferSize
);
94 // Read (and save) buffer at a specific location
95 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
96 if (Status
!= EFI_SUCCESS
) {
97 DiagnosticLog(L
"ERROR: Fail to Read Block (1)\n");
101 // Write buffer at the same location
102 GenerateRandomBuffer(WriteBuffer
,BufferSize
);
103 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,WriteBuffer
);
104 if (Status
!= EFI_SUCCESS
) {
105 DiagnosticLog(L
"ERROR: Fail to Write Block (1)\n");
109 // Read the buffer at the same location
110 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,ReadBuffer
);
111 if (Status
!= EFI_SUCCESS
) {
112 DiagnosticLog(L
"ERROR: Fail to Read Block (2)\n");
116 // Check that is conform
117 if (!CompareBuffer(ReadBuffer
,WriteBuffer
,BufferSize
)) {
118 DiagnosticLog(L
"ERROR: Fail to Read/Write Block (1)\n");
119 return EFI_INVALID_PARAMETER
;
122 // Restore content at the original location
123 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
124 if (Status
!= EFI_SUCCESS
) {
125 DiagnosticLog(L
"ERROR: Fail to Write Block (2)\n");
129 // Read the restored content
130 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,ReadBuffer
);
131 if (Status
!= EFI_SUCCESS
) {
132 DiagnosticLog(L
"ERROR: Fail to Read Block (3)\n");
136 // Check the content is correct
137 if (!CompareBuffer(ReadBuffer
,BackBuffer
,BufferSize
)) {
138 DiagnosticLog(L
"ERROR: Fail to Read/Write Block (2)\n");
139 return EFI_INVALID_PARAMETER
;
147 MmcDriverDiagnosticsRunDiagnostics (
148 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL
*This
,
149 IN EFI_HANDLE ControllerHandle
,
150 IN EFI_HANDLE ChildHandle OPTIONAL
,
151 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType
,
153 OUT EFI_GUID
**ErrorType
,
154 OUT UINTN
*BufferSize
,
158 LIST_ENTRY
*CurrentLink
;
159 MMC_HOST_INSTANCE
*MmcHostInstance
;
162 if (Language
== NULL
||
165 ControllerHandle
== NULL
||
166 BufferSize
== NULL
) {
167 return EFI_INVALID_PARAMETER
;
170 Status
= EFI_SUCCESS
;
172 *BufferSize
= DIAGNOSTIC_LOGBUFFER_MAXCHAR
;
173 *Buffer
= DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR
);
175 DiagnosticLog(L
"MMC Driver Diagnostics\n");
177 // For each MMC instance
178 CurrentLink
= mMmcHostPool
.ForwardLink
;
179 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
180 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
181 ASSERT(MmcHostInstance
!= NULL
);
183 // LBA=1 Size=BlockSize
184 DiagnosticLog(L
"MMC Driver Diagnostics - Test: First Block\n");
185 Status
= MmcReadWriteDataTest(MmcHostInstance
, 1, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
187 // LBA=2 Size=BlockSize
188 DiagnosticLog(L
"MMC Driver Diagnostics - Test: Second Block\n");
189 Status
= MmcReadWriteDataTest(MmcHostInstance
, 2, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
191 // LBA=10 Size=BlockSize
192 DiagnosticLog(L
"MMC Driver Diagnostics - Test: Any Block\n");
193 Status
= MmcReadWriteDataTest(MmcHostInstance
, MmcHostInstance
->BlockIo
.Media
->LastBlock
>> 1, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
195 // LBA=LastBlock Size=BlockSize
196 DiagnosticLog(L
"MMC Driver Diagnostics - Test: Last Block\n");
197 Status
= MmcReadWriteDataTest(MmcHostInstance
, MmcHostInstance
->BlockIo
.Media
->LastBlock
, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
199 // LBA=1 Size=2*BlockSize
200 DiagnosticLog(L
"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
201 Status
= MmcReadWriteDataTest(MmcHostInstance
, 1, 2*MmcHostInstance
->BlockIo
.Media
->BlockSize
);
203 CurrentLink
= CurrentLink
->ForwardLink
;
210 // EFI Driver Diagnostics 2 Protocol
212 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2
= {
213 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS
) MmcDriverDiagnosticsRunDiagnostics
,