2 Diagnostics Protocol implementation for the MMC DXE driver
4 Copyright (c) 2011-2020, ARM Limited. All rights reserved.
6 SPDX-License-Identifier: BSD-2-Clause-Patent
11 #include <Library/DebugLib.h>
12 #include <Library/BaseMemoryLib.h>
13 #include <Library/MemoryAllocationLib.h>
14 #include <Library/BaseLib.h>
18 #define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024
20 CHAR16
* mLogBuffer
= NULL
;
21 UINTN mLogRemainChar
= 0;
28 mLogRemainChar
= MaxBufferChar
;
29 mLogBuffer
= AllocatePool ((UINTN
)MaxBufferChar
* sizeof (CHAR16
));
38 UINTN len
= StrLen (Str
);
39 if (len
< mLogRemainChar
) {
40 StrCpyS (mLogBuffer
, mLogRemainChar
, Str
);
41 mLogRemainChar
-= len
;
50 GenerateRandomBuffer (
56 UINT64
* Buffer64
= (UINT64
*)Buffer
;
58 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
59 *Buffer64
= i
| LShiftU64 (~i
, 32);
72 UINT64
* BufferA64
= (UINT64
*)BufferA
;
73 UINT64
* BufferB64
= (UINT64
*)BufferB
;
75 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
76 if (*BufferA64
!= *BufferB64
) {
77 DEBUG ((DEBUG_ERROR
, "CompareBuffer: Error at %i", i
));
78 DEBUG ((DEBUG_ERROR
, "(0x%lX) != (0x%lX)\n", *BufferA64
, *BufferB64
));
88 MmcReadWriteDataTest (
89 MMC_HOST_INSTANCE
*MmcHostInstance
,
99 // Check if a Media is Present
100 if (!MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
101 DiagnosticLog (L
"ERROR: No Media Present\n");
105 if (MmcHostInstance
->State
!= MmcTransferState
) {
106 DiagnosticLog (L
"ERROR: Not ready for Transfer state\n");
107 return EFI_NOT_READY
;
110 BackBuffer
= AllocatePool (BufferSize
);
111 WriteBuffer
= AllocatePool (BufferSize
);
112 ReadBuffer
= AllocatePool (BufferSize
);
114 // Read (and save) buffer at a specific location
115 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
116 if (Status
!= EFI_SUCCESS
) {
117 DiagnosticLog (L
"ERROR: Fail to Read Block (1)\n");
121 // Write buffer at the same location
122 GenerateRandomBuffer (WriteBuffer
,BufferSize
);
123 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,WriteBuffer
);
124 if (Status
!= EFI_SUCCESS
) {
125 DiagnosticLog (L
"ERROR: Fail to Write Block (1)\n");
129 // Read the buffer at the same location
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 (2)\n");
136 // Check that is conform
137 if (!CompareBuffer (ReadBuffer
,WriteBuffer
,BufferSize
)) {
138 DiagnosticLog (L
"ERROR: Fail to Read/Write Block (1)\n");
139 return EFI_INVALID_PARAMETER
;
142 // Restore content at the original location
143 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
144 if (Status
!= EFI_SUCCESS
) {
145 DiagnosticLog (L
"ERROR: Fail to Write Block (2)\n");
149 // Read the restored content
150 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,ReadBuffer
);
151 if (Status
!= EFI_SUCCESS
) {
152 DiagnosticLog (L
"ERROR: Fail to Read Block (3)\n");
156 // Check the content is correct
157 if (!CompareBuffer (ReadBuffer
,BackBuffer
,BufferSize
)) {
158 DiagnosticLog (L
"ERROR: Fail to Read/Write Block (2)\n");
159 return EFI_INVALID_PARAMETER
;
167 MmcDriverDiagnosticsRunDiagnostics (
168 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL
*This
,
169 IN EFI_HANDLE ControllerHandle
,
170 IN EFI_HANDLE ChildHandle OPTIONAL
,
171 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType
,
173 OUT EFI_GUID
**ErrorType
,
174 OUT UINTN
*BufferSize
,
178 LIST_ENTRY
*CurrentLink
;
179 MMC_HOST_INSTANCE
*MmcHostInstance
;
182 if ((Language
== NULL
) ||
183 (ErrorType
== NULL
) ||
185 (ControllerHandle
== NULL
) ||
186 (BufferSize
== NULL
)) {
187 return EFI_INVALID_PARAMETER
;
190 // Check Language is supported (i.e. is "en-*" - only English is supported)
191 if (AsciiStrnCmp (Language
, "en", 2) != 0) {
192 return EFI_UNSUPPORTED
;
195 Status
= EFI_SUCCESS
;
197 *BufferSize
= DIAGNOSTIC_LOGBUFFER_MAXCHAR
;
198 *Buffer
= DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR
);
200 DiagnosticLog (L
"MMC Driver Diagnostics\n");
202 // Find the MMC Host instance on which we have been asked to run diagnostics
203 MmcHostInstance
= NULL
;
204 CurrentLink
= mMmcHostPool
.ForwardLink
;
205 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
206 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
207 ASSERT(MmcHostInstance
!= NULL
);
208 if (MmcHostInstance
->MmcHandle
== ControllerHandle
) {
211 CurrentLink
= CurrentLink
->ForwardLink
;
214 // If we didn't find the controller, return EFI_UNSUPPORTED
215 if ((MmcHostInstance
== NULL
)
216 || (MmcHostInstance
->MmcHandle
!= ControllerHandle
)) {
217 return EFI_UNSUPPORTED
;
220 // LBA=1 Size=BlockSize
221 DiagnosticLog (L
"MMC Driver Diagnostics - Test: First Block\n");
222 Status
= MmcReadWriteDataTest (MmcHostInstance
, 1, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
224 // LBA=2 Size=BlockSize
225 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Second Block\n");
226 Status
= MmcReadWriteDataTest (MmcHostInstance
, 2, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
228 // LBA=10 Size=BlockSize
229 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Any Block\n");
230 Status
= MmcReadWriteDataTest (
232 RShiftU64 (MmcHostInstance
->BlockIo
.Media
->LastBlock
, 1),
233 MmcHostInstance
->BlockIo
.Media
->BlockSize
236 // LBA=LastBlock Size=BlockSize
237 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Last Block\n");
238 Status
= MmcReadWriteDataTest (MmcHostInstance
, MmcHostInstance
->BlockIo
.Media
->LastBlock
, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
240 // LBA=1 Size=2*BlockSize
241 DiagnosticLog (L
"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
242 Status
= MmcReadWriteDataTest (MmcHostInstance
, 1, 2 * MmcHostInstance
->BlockIo
.Media
->BlockSize
);
248 // EFI Driver Diagnostics 2 Protocol
250 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2
= {
251 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS
) MmcDriverDiagnosticsRunDiagnostics
,