2 Diagnostics Protocol implementation for the MMC DXE driver
4 Copyright (c) 2011-2014, 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>
20 #include <Library/BaseLib.h>
24 #define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024
26 CHAR16
* mLogBuffer
= NULL
;
27 UINTN mLogRemainChar
= 0;
34 mLogRemainChar
= MaxBufferChar
;
35 mLogBuffer
= AllocatePool ((UINTN
)MaxBufferChar
* sizeof (CHAR16
));
44 UINTN len
= StrLen (Str
);
45 if (len
< mLogRemainChar
) {
46 StrCpyS (mLogBuffer
, mLogRemainChar
, Str
);
47 mLogRemainChar
-= len
;
56 GenerateRandomBuffer (
62 UINT64
* Buffer64
= (UINT64
*)Buffer
;
64 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
65 *Buffer64
= i
| (~i
<< 32);
78 UINT64
* BufferA64
= (UINT64
*)BufferA
;
79 UINT64
* BufferB64
= (UINT64
*)BufferB
;
81 for (i
= 0; i
< (BufferSize
>> 3); i
++) {
82 if (*BufferA64
!= *BufferB64
) {
83 DEBUG ((EFI_D_ERROR
, "CompareBuffer: Error at %i", i
));
84 DEBUG ((EFI_D_ERROR
, "(0x%lX) != (0x%lX)\n", *BufferA64
, *BufferB64
));
94 MmcReadWriteDataTest (
95 MMC_HOST_INSTANCE
*MmcHostInstance
,
105 // Check if a Media is Present
106 if (!MmcHostInstance
->BlockIo
.Media
->MediaPresent
) {
107 DiagnosticLog (L
"ERROR: No Media Present\n");
111 if (MmcHostInstance
->State
!= MmcTransferState
) {
112 DiagnosticLog (L
"ERROR: Not ready for Transfer state\n");
113 return EFI_NOT_READY
;
116 BackBuffer
= AllocatePool (BufferSize
);
117 WriteBuffer
= AllocatePool (BufferSize
);
118 ReadBuffer
= AllocatePool (BufferSize
);
120 // Read (and save) buffer at a specific location
121 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
122 if (Status
!= EFI_SUCCESS
) {
123 DiagnosticLog (L
"ERROR: Fail to Read Block (1)\n");
127 // Write buffer at the same location
128 GenerateRandomBuffer (WriteBuffer
,BufferSize
);
129 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,WriteBuffer
);
130 if (Status
!= EFI_SUCCESS
) {
131 DiagnosticLog (L
"ERROR: Fail to Write Block (1)\n");
135 // Read the buffer at the same location
136 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,ReadBuffer
);
137 if (Status
!= EFI_SUCCESS
) {
138 DiagnosticLog (L
"ERROR: Fail to Read Block (2)\n");
142 // Check that is conform
143 if (!CompareBuffer (ReadBuffer
,WriteBuffer
,BufferSize
)) {
144 DiagnosticLog (L
"ERROR: Fail to Read/Write Block (1)\n");
145 return EFI_INVALID_PARAMETER
;
148 // Restore content at the original location
149 Status
= MmcWriteBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,BackBuffer
);
150 if (Status
!= EFI_SUCCESS
) {
151 DiagnosticLog (L
"ERROR: Fail to Write Block (2)\n");
155 // Read the restored content
156 Status
= MmcReadBlocks (&(MmcHostInstance
->BlockIo
), MmcHostInstance
->BlockIo
.Media
->MediaId
,Lba
,BufferSize
,ReadBuffer
);
157 if (Status
!= EFI_SUCCESS
) {
158 DiagnosticLog (L
"ERROR: Fail to Read Block (3)\n");
162 // Check the content is correct
163 if (!CompareBuffer (ReadBuffer
,BackBuffer
,BufferSize
)) {
164 DiagnosticLog (L
"ERROR: Fail to Read/Write Block (2)\n");
165 return EFI_INVALID_PARAMETER
;
173 MmcDriverDiagnosticsRunDiagnostics (
174 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL
*This
,
175 IN EFI_HANDLE ControllerHandle
,
176 IN EFI_HANDLE ChildHandle OPTIONAL
,
177 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType
,
179 OUT EFI_GUID
**ErrorType
,
180 OUT UINTN
*BufferSize
,
184 LIST_ENTRY
*CurrentLink
;
185 MMC_HOST_INSTANCE
*MmcHostInstance
;
188 if ((Language
== NULL
) ||
189 (ErrorType
== NULL
) ||
191 (ControllerHandle
== NULL
) ||
192 (BufferSize
== NULL
)) {
193 return EFI_INVALID_PARAMETER
;
196 // Check Language is supported (i.e. is "en-*" - only English is supported)
197 if (AsciiStrnCmp (Language
, "en", 2) != 0) {
198 return EFI_UNSUPPORTED
;
201 Status
= EFI_SUCCESS
;
203 *BufferSize
= DIAGNOSTIC_LOGBUFFER_MAXCHAR
;
204 *Buffer
= DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR
);
206 DiagnosticLog (L
"MMC Driver Diagnostics\n");
208 // Find the MMC Host instance on which we have been asked to run diagnostics
209 MmcHostInstance
= NULL
;
210 CurrentLink
= mMmcHostPool
.ForwardLink
;
211 while (CurrentLink
!= NULL
&& CurrentLink
!= &mMmcHostPool
&& (Status
== EFI_SUCCESS
)) {
212 MmcHostInstance
= MMC_HOST_INSTANCE_FROM_LINK(CurrentLink
);
213 ASSERT(MmcHostInstance
!= NULL
);
214 if (MmcHostInstance
->MmcHandle
== ControllerHandle
) {
217 CurrentLink
= CurrentLink
->ForwardLink
;
220 // If we didn't find the controller, return EFI_UNSUPPORTED
221 if ((MmcHostInstance
== NULL
)
222 || (MmcHostInstance
->MmcHandle
!= ControllerHandle
)) {
223 return EFI_UNSUPPORTED
;
226 // LBA=1 Size=BlockSize
227 DiagnosticLog (L
"MMC Driver Diagnostics - Test: First Block\n");
228 Status
= MmcReadWriteDataTest (MmcHostInstance
, 1, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
230 // LBA=2 Size=BlockSize
231 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Second Block\n");
232 Status
= MmcReadWriteDataTest (MmcHostInstance
, 2, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
234 // LBA=10 Size=BlockSize
235 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Any Block\n");
236 Status
= MmcReadWriteDataTest (MmcHostInstance
, MmcHostInstance
->BlockIo
.Media
->LastBlock
>> 1, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
238 // LBA=LastBlock Size=BlockSize
239 DiagnosticLog (L
"MMC Driver Diagnostics - Test: Last Block\n");
240 Status
= MmcReadWriteDataTest (MmcHostInstance
, MmcHostInstance
->BlockIo
.Media
->LastBlock
, MmcHostInstance
->BlockIo
.Media
->BlockSize
);
242 // LBA=1 Size=2*BlockSize
243 DiagnosticLog (L
"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
244 Status
= MmcReadWriteDataTest (MmcHostInstance
, 1, 2 * MmcHostInstance
->BlockIo
.Media
->BlockSize
);
250 // EFI Driver Diagnostics 2 Protocol
252 GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2
= {
253 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS
) MmcDriverDiagnosticsRunDiagnostics
,