]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
ArmVirtPkg: Change use of EFI_D_* to DEBUG_*
[mirror_edk2.git] / EmbeddedPkg / Universal / MmcDxe / Diagnostics.c
CommitLineData
1bfda055 1/** @file\r
2 Diagnostics Protocol implementation for the MMC DXE driver\r
3\r
7ff04597 4 Copyright (c) 2011-2020, ARM Limited. All rights reserved.\r
3402aac7 5\r
878b807a 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
1bfda055 7\r
8**/\r
9\r
10#include <Uefi.h>\r
11#include <Library/DebugLib.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include <Library/MemoryAllocationLib.h>\r
c8af31ec 14#include <Library/BaseLib.h>\r
1bfda055 15\r
16#include "Mmc.h"\r
17\r
18#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024\r
19\r
20CHAR16* mLogBuffer = NULL;\r
21UINTN mLogRemainChar = 0;\r
22\r
11c20f4e 23CHAR16*\r
24DiagnosticInitLog (\r
25 UINTN MaxBufferChar\r
26 )\r
27{\r
28 mLogRemainChar = MaxBufferChar;\r
c8af31ec 29 mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof (CHAR16));\r
11c20f4e 30 return mLogBuffer;\r
1bfda055 31}\r
32\r
11c20f4e 33UINTN\r
34DiagnosticLog (\r
35 CONST CHAR16* Str\r
36 )\r
37{\r
38 UINTN len = StrLen (Str);\r
4b335e4b
AB
39 if (len < mLogRemainChar) {\r
40 StrCpyS (mLogBuffer, mLogRemainChar, Str);\r
11c20f4e 41 mLogRemainChar -= len;\r
11c20f4e 42 mLogBuffer += len;\r
43 return len;\r
44 } else {\r
45 return 0;\r
46 }\r
1bfda055 47}\r
48\r
11c20f4e 49VOID\r
50GenerateRandomBuffer (\r
51 VOID* Buffer,\r
52 UINTN BufferSize\r
53 )\r
54{\r
55 UINT64 i;\r
56 UINT64* Buffer64 = (UINT64*)Buffer;\r
1bfda055 57\r
11c20f4e 58 for (i = 0; i < (BufferSize >> 3); i++) {\r
7ff04597 59 *Buffer64 = i | LShiftU64 (~i, 32);\r
11c20f4e 60 Buffer64++;\r
61 }\r
1bfda055 62}\r
63\r
11c20f4e 64BOOLEAN\r
65CompareBuffer (\r
66 VOID *BufferA,\r
67 VOID *BufferB,\r
68 UINTN BufferSize\r
69 )\r
70{\r
71 UINTN i;\r
72 UINT64* BufferA64 = (UINT64*)BufferA;\r
73 UINT64* BufferB64 = (UINT64*)BufferB;\r
74\r
75 for (i = 0; i < (BufferSize >> 3); i++) {\r
76 if (*BufferA64 != *BufferB64) {\r
c8af31ec
OM
77 DEBUG ((EFI_D_ERROR, "CompareBuffer: Error at %i", i));\r
78 DEBUG ((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
11c20f4e 79 return FALSE;\r
1bfda055 80 }\r
11c20f4e 81 BufferA64++;\r
82 BufferB64++;\r
83 }\r
84 return TRUE;\r
1bfda055 85}\r
86\r
11c20f4e 87EFI_STATUS\r
88MmcReadWriteDataTest (\r
89 MMC_HOST_INSTANCE *MmcHostInstance,\r
90 EFI_LBA Lba,\r
91 UINTN BufferSize\r
92 )\r
93{\r
94 VOID *BackBuffer;\r
95 VOID *WriteBuffer;\r
96 VOID *ReadBuffer;\r
97 EFI_STATUS Status;\r
98\r
99 // Check if a Media is Present\r
100 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
101 DiagnosticLog (L"ERROR: No Media Present\n");\r
102 return EFI_NO_MEDIA;\r
103 }\r
104\r
105 if (MmcHostInstance->State != MmcTransferState) {\r
106 DiagnosticLog (L"ERROR: Not ready for Transfer state\n");\r
107 return EFI_NOT_READY;\r
108 }\r
109\r
110 BackBuffer = AllocatePool (BufferSize);\r
111 WriteBuffer = AllocatePool (BufferSize);\r
112 ReadBuffer = AllocatePool (BufferSize);\r
113\r
114 // Read (and save) buffer at a specific location\r
115 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
116 if (Status != EFI_SUCCESS) {\r
117 DiagnosticLog (L"ERROR: Fail to Read Block (1)\n");\r
118 return Status;\r
119 }\r
1bfda055 120\r
11c20f4e 121 // Write buffer at the same location\r
122 GenerateRandomBuffer (WriteBuffer,BufferSize);\r
123 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);\r
124 if (Status != EFI_SUCCESS) {\r
125 DiagnosticLog (L"ERROR: Fail to Write Block (1)\n");\r
126 return Status;\r
127 }\r
1bfda055 128\r
11c20f4e 129 // Read the buffer at the same location\r
130 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
131 if (Status != EFI_SUCCESS) {\r
132 DiagnosticLog (L"ERROR: Fail to Read Block (2)\n");\r
133 return Status;\r
134 }\r
135\r
136 // Check that is conform\r
137 if (!CompareBuffer (ReadBuffer,WriteBuffer,BufferSize)) {\r
138 DiagnosticLog (L"ERROR: Fail to Read/Write Block (1)\n");\r
139 return EFI_INVALID_PARAMETER;\r
140 }\r
141\r
142 // Restore content at the original location\r
143 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
144 if (Status != EFI_SUCCESS) {\r
145 DiagnosticLog (L"ERROR: Fail to Write Block (2)\n");\r
146 return Status;\r
147 }\r
1bfda055 148\r
11c20f4e 149 // Read the restored content\r
150 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
151 if (Status != EFI_SUCCESS) {\r
152 DiagnosticLog (L"ERROR: Fail to Read Block (3)\n");\r
153 return Status;\r
154 }\r
1bfda055 155\r
11c20f4e 156 // Check the content is correct\r
157 if (!CompareBuffer (ReadBuffer,BackBuffer,BufferSize)) {\r
158 DiagnosticLog (L"ERROR: Fail to Read/Write Block (2)\n");\r
159 return EFI_INVALID_PARAMETER;\r
160 }\r
1bfda055 161\r
11c20f4e 162 return EFI_SUCCESS;\r
1bfda055 163}\r
164\r
165EFI_STATUS\r
166EFIAPI\r
167MmcDriverDiagnosticsRunDiagnostics (\r
168 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,\r
169 IN EFI_HANDLE ControllerHandle,\r
170 IN EFI_HANDLE ChildHandle OPTIONAL,\r
171 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,\r
172 IN CHAR8 *Language,\r
173 OUT EFI_GUID **ErrorType,\r
174 OUT UINTN *BufferSize,\r
175 OUT CHAR16 **Buffer\r
176 )\r
177{\r
11c20f4e 178 LIST_ENTRY *CurrentLink;\r
179 MMC_HOST_INSTANCE *MmcHostInstance;\r
180 EFI_STATUS Status;\r
181\r
182 if ((Language == NULL) ||\r
183 (ErrorType == NULL) ||\r
184 (Buffer == NULL) ||\r
185 (ControllerHandle == NULL) ||\r
186 (BufferSize == NULL)) {\r
187 return EFI_INVALID_PARAMETER;\r
188 }\r
189\r
c8af31ec
OM
190 // Check Language is supported (i.e. is "en-*" - only English is supported)\r
191 if (AsciiStrnCmp (Language, "en", 2) != 0) {\r
192 return EFI_UNSUPPORTED;\r
193 }\r
194\r
11c20f4e 195 Status = EFI_SUCCESS;\r
196 *ErrorType = NULL;\r
197 *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;\r
198 *Buffer = DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR);\r
199\r
200 DiagnosticLog (L"MMC Driver Diagnostics\n");\r
201\r
5c5a34d4
OM
202 // Find the MMC Host instance on which we have been asked to run diagnostics\r
203 MmcHostInstance = NULL;\r
11c20f4e 204 CurrentLink = mMmcHostPool.ForwardLink;\r
205 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
5c5a34d4
OM
206 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
207 ASSERT(MmcHostInstance != NULL);\r
208 if (MmcHostInstance->MmcHandle == ControllerHandle) {\r
209 break;\r
210 }\r
211 CurrentLink = CurrentLink->ForwardLink;\r
212 }\r
11c20f4e 213\r
5c5a34d4
OM
214 // If we didn't find the controller, return EFI_UNSUPPORTED\r
215 if ((MmcHostInstance == NULL)\r
216 || (MmcHostInstance->MmcHandle != ControllerHandle)) {\r
217 return EFI_UNSUPPORTED;\r
218 }\r
11c20f4e 219\r
5c5a34d4
OM
220 // LBA=1 Size=BlockSize\r
221 DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block\n");\r
222 Status = MmcReadWriteDataTest (MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
11c20f4e 223\r
5c5a34d4
OM
224 // LBA=2 Size=BlockSize\r
225 DiagnosticLog (L"MMC Driver Diagnostics - Test: Second Block\n");\r
226 Status = MmcReadWriteDataTest (MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);\r
11c20f4e 227\r
5c5a34d4
OM
228 // LBA=10 Size=BlockSize\r
229 DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n");\r
7ff04597
PG
230 Status = MmcReadWriteDataTest (\r
231 MmcHostInstance,\r
232 RShiftU64 (MmcHostInstance->BlockIo.Media->LastBlock, 1),\r
233 MmcHostInstance->BlockIo.Media->BlockSize\r
234 );\r
11c20f4e 235\r
5c5a34d4
OM
236 // LBA=LastBlock Size=BlockSize\r
237 DiagnosticLog (L"MMC Driver Diagnostics - Test: Last Block\n");\r
238 Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);\r
11c20f4e 239\r
5c5a34d4
OM
240 // LBA=1 Size=2*BlockSize\r
241 DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");\r
242 Status = MmcReadWriteDataTest (MmcHostInstance, 1, 2 * MmcHostInstance->BlockIo.Media->BlockSize);\r
11c20f4e 243\r
244 return Status;\r
1bfda055 245}\r
246\r
247//\r
248// EFI Driver Diagnostics 2 Protocol\r
249//\r
250GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
251 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,\r
252 "en"\r
253};\r