1 | /** @file
|
---|
2 | Diagnostics Protocol implementation for the MMC DXE driver
|
---|
3 |
|
---|
4 | Copyright (c) 2011-2014, ARM Limited. All rights reserved.
|
---|
5 |
|
---|
6 | SPDX-License-Identifier: BSD-2-Clause-Patent
|
---|
7 |
|
---|
8 | **/
|
---|
9 |
|
---|
10 | #include <Uefi.h>
|
---|
11 | #include <Library/DebugLib.h>
|
---|
12 | #include <Library/BaseMemoryLib.h>
|
---|
13 | #include <Library/MemoryAllocationLib.h>
|
---|
14 | #include <Library/BaseLib.h>
|
---|
15 |
|
---|
16 | #include "Mmc.h"
|
---|
17 |
|
---|
18 | #define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024
|
---|
19 |
|
---|
20 | CHAR16* mLogBuffer = NULL;
|
---|
21 | UINTN mLogRemainChar = 0;
|
---|
22 |
|
---|
23 | CHAR16*
|
---|
24 | DiagnosticInitLog (
|
---|
25 | UINTN MaxBufferChar
|
---|
26 | )
|
---|
27 | {
|
---|
28 | mLogRemainChar = MaxBufferChar;
|
---|
29 | mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof (CHAR16));
|
---|
30 | return mLogBuffer;
|
---|
31 | }
|
---|
32 |
|
---|
33 | UINTN
|
---|
34 | DiagnosticLog (
|
---|
35 | CONST CHAR16* Str
|
---|
36 | )
|
---|
37 | {
|
---|
38 | UINTN len = StrLen (Str);
|
---|
39 | if (len < mLogRemainChar) {
|
---|
40 | StrCpyS (mLogBuffer, mLogRemainChar, Str);
|
---|
41 | mLogRemainChar -= len;
|
---|
42 | mLogBuffer += len;
|
---|
43 | return len;
|
---|
44 | } else {
|
---|
45 | return 0;
|
---|
46 | }
|
---|
47 | }
|
---|
48 |
|
---|
49 | VOID
|
---|
50 | GenerateRandomBuffer (
|
---|
51 | VOID* Buffer,
|
---|
52 | UINTN BufferSize
|
---|
53 | )
|
---|
54 | {
|
---|
55 | UINT64 i;
|
---|
56 | UINT64* Buffer64 = (UINT64*)Buffer;
|
---|
57 |
|
---|
58 | for (i = 0; i < (BufferSize >> 3); i++) {
|
---|
59 | *Buffer64 = i | (~i << 32);
|
---|
60 | Buffer64++;
|
---|
61 | }
|
---|
62 | }
|
---|
63 |
|
---|
64 | BOOLEAN
|
---|
65 | CompareBuffer (
|
---|
66 | VOID *BufferA,
|
---|
67 | VOID *BufferB,
|
---|
68 | UINTN BufferSize
|
---|
69 | )
|
---|
70 | {
|
---|
71 | UINTN i;
|
---|
72 | UINT64* BufferA64 = (UINT64*)BufferA;
|
---|
73 | UINT64* BufferB64 = (UINT64*)BufferB;
|
---|
74 |
|
---|
75 | for (i = 0; i < (BufferSize >> 3); i++) {
|
---|
76 | if (*BufferA64 != *BufferB64) {
|
---|
77 | DEBUG ((EFI_D_ERROR, "CompareBuffer: Error at %i", i));
|
---|
78 | DEBUG ((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));
|
---|
79 | return FALSE;
|
---|
80 | }
|
---|
81 | BufferA64++;
|
---|
82 | BufferB64++;
|
---|
83 | }
|
---|
84 | return TRUE;
|
---|
85 | }
|
---|
86 |
|
---|
87 | EFI_STATUS
|
---|
88 | MmcReadWriteDataTest (
|
---|
89 | MMC_HOST_INSTANCE *MmcHostInstance,
|
---|
90 | EFI_LBA Lba,
|
---|
91 | UINTN BufferSize
|
---|
92 | )
|
---|
93 | {
|
---|
94 | VOID *BackBuffer;
|
---|
95 | VOID *WriteBuffer;
|
---|
96 | VOID *ReadBuffer;
|
---|
97 | EFI_STATUS Status;
|
---|
98 |
|
---|
99 | // Check if a Media is Present
|
---|
100 | if (!MmcHostInstance->BlockIo.Media->MediaPresent) {
|
---|
101 | DiagnosticLog (L"ERROR: No Media Present\n");
|
---|
102 | return EFI_NO_MEDIA;
|
---|
103 | }
|
---|
104 |
|
---|
105 | if (MmcHostInstance->State != MmcTransferState) {
|
---|
106 | DiagnosticLog (L"ERROR: Not ready for Transfer state\n");
|
---|
107 | return EFI_NOT_READY;
|
---|
108 | }
|
---|
109 |
|
---|
110 | BackBuffer = AllocatePool (BufferSize);
|
---|
111 | WriteBuffer = AllocatePool (BufferSize);
|
---|
112 | ReadBuffer = AllocatePool (BufferSize);
|
---|
113 |
|
---|
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");
|
---|
118 | return Status;
|
---|
119 | }
|
---|
120 |
|
---|
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");
|
---|
126 | return Status;
|
---|
127 | }
|
---|
128 |
|
---|
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");
|
---|
133 | return Status;
|
---|
134 | }
|
---|
135 |
|
---|
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;
|
---|
140 | }
|
---|
141 |
|
---|
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");
|
---|
146 | return Status;
|
---|
147 | }
|
---|
148 |
|
---|
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");
|
---|
153 | return Status;
|
---|
154 | }
|
---|
155 |
|
---|
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;
|
---|
160 | }
|
---|
161 |
|
---|
162 | return EFI_SUCCESS;
|
---|
163 | }
|
---|
164 |
|
---|
165 | EFI_STATUS
|
---|
166 | EFIAPI
|
---|
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,
|
---|
172 | IN CHAR8 *Language,
|
---|
173 | OUT EFI_GUID **ErrorType,
|
---|
174 | OUT UINTN *BufferSize,
|
---|
175 | OUT CHAR16 **Buffer
|
---|
176 | )
|
---|
177 | {
|
---|
178 | LIST_ENTRY *CurrentLink;
|
---|
179 | MMC_HOST_INSTANCE *MmcHostInstance;
|
---|
180 | EFI_STATUS Status;
|
---|
181 |
|
---|
182 | if ((Language == NULL) ||
|
---|
183 | (ErrorType == NULL) ||
|
---|
184 | (Buffer == NULL) ||
|
---|
185 | (ControllerHandle == NULL) ||
|
---|
186 | (BufferSize == NULL)) {
|
---|
187 | return EFI_INVALID_PARAMETER;
|
---|
188 | }
|
---|
189 |
|
---|
190 | // Check Language is supported (i.e. is "en-*" - only English is supported)
|
---|
191 | if (AsciiStrnCmp (Language, "en", 2) != 0) {
|
---|
192 | return EFI_UNSUPPORTED;
|
---|
193 | }
|
---|
194 |
|
---|
195 | Status = EFI_SUCCESS;
|
---|
196 | *ErrorType = NULL;
|
---|
197 | *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;
|
---|
198 | *Buffer = DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR);
|
---|
199 |
|
---|
200 | DiagnosticLog (L"MMC Driver Diagnostics\n");
|
---|
201 |
|
---|
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) {
|
---|
209 | break;
|
---|
210 | }
|
---|
211 | CurrentLink = CurrentLink->ForwardLink;
|
---|
212 | }
|
---|
213 |
|
---|
214 | // If we didn't find the controller, return EFI_UNSUPPORTED
|
---|
215 | if ((MmcHostInstance == NULL)
|
---|
216 | || (MmcHostInstance->MmcHandle != ControllerHandle)) {
|
---|
217 | return EFI_UNSUPPORTED;
|
---|
218 | }
|
---|
219 |
|
---|
220 | // LBA=1 Size=BlockSize
|
---|
221 | DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block\n");
|
---|
222 | Status = MmcReadWriteDataTest (MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);
|
---|
223 |
|
---|
224 | // LBA=2 Size=BlockSize
|
---|
225 | DiagnosticLog (L"MMC Driver Diagnostics - Test: Second Block\n");
|
---|
226 | Status = MmcReadWriteDataTest (MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);
|
---|
227 |
|
---|
228 | // LBA=10 Size=BlockSize
|
---|
229 | DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n");
|
---|
230 | Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);
|
---|
231 |
|
---|
232 | // LBA=LastBlock Size=BlockSize
|
---|
233 | DiagnosticLog (L"MMC Driver Diagnostics - Test: Last Block\n");
|
---|
234 | Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);
|
---|
235 |
|
---|
236 | // LBA=1 Size=2*BlockSize
|
---|
237 | DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");
|
---|
238 | Status = MmcReadWriteDataTest (MmcHostInstance, 1, 2 * MmcHostInstance->BlockIo.Media->BlockSize);
|
---|
239 |
|
---|
240 | return Status;
|
---|
241 | }
|
---|
242 |
|
---|
243 | //
|
---|
244 | // EFI Driver Diagnostics 2 Protocol
|
---|
245 | //
|
---|
246 | GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {
|
---|
247 | (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,
|
---|
248 | "en"
|
---|
249 | };
|
---|