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