]> git.proxmox.com Git - mirror_edk2.git/blob - EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
EmbeddedPkg: Replace BSD License with BSD+Patent License
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / Diagnostics.c
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 };