]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[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
e7108d0e 20CHAR16 *mLogBuffer = NULL;\r
1bfda055 21UINTN mLogRemainChar = 0;\r
22\r
e7108d0e 23CHAR16 *\r
11c20f4e 24DiagnosticInitLog (\r
e7108d0e 25 UINTN MaxBufferChar\r
11c20f4e 26 )\r
27{\r
28 mLogRemainChar = MaxBufferChar;\r
e7108d0e 29 mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof (CHAR16));\r
11c20f4e 30 return mLogBuffer;\r
1bfda055 31}\r
32\r
11c20f4e 33UINTN\r
34DiagnosticLog (\r
e7108d0e 35 CONST CHAR16 *Str\r
11c20f4e 36 )\r
37{\r
e7108d0e
MK
38 UINTN len = StrLen (Str);\r
39\r
4b335e4b
AB
40 if (len < mLogRemainChar) {\r
41 StrCpyS (mLogBuffer, mLogRemainChar, Str);\r
11c20f4e 42 mLogRemainChar -= len;\r
e7108d0e 43 mLogBuffer += len;\r
11c20f4e 44 return len;\r
45 } else {\r
46 return 0;\r
47 }\r
1bfda055 48}\r
49\r
11c20f4e 50VOID\r
51GenerateRandomBuffer (\r
e7108d0e
MK
52 VOID *Buffer,\r
53 UINTN BufferSize\r
11c20f4e 54 )\r
55{\r
56 UINT64 i;\r
e7108d0e 57 UINT64 *Buffer64 = (UINT64 *)Buffer;\r
1bfda055 58\r
11c20f4e 59 for (i = 0; i < (BufferSize >> 3); i++) {\r
7ff04597 60 *Buffer64 = i | LShiftU64 (~i, 32);\r
11c20f4e 61 Buffer64++;\r
62 }\r
1bfda055 63}\r
64\r
11c20f4e 65BOOLEAN\r
66CompareBuffer (\r
e7108d0e
MK
67 VOID *BufferA,\r
68 VOID *BufferB,\r
69 UINTN BufferSize\r
11c20f4e 70 )\r
71{\r
e7108d0e
MK
72 UINTN i;\r
73 UINT64 *BufferA64 = (UINT64 *)BufferA;\r
74 UINT64 *BufferB64 = (UINT64 *)BufferB;\r
11c20f4e 75\r
76 for (i = 0; i < (BufferSize >> 3); i++) {\r
77 if (*BufferA64 != *BufferB64) {\r
a1878955
MK
78 DEBUG ((DEBUG_ERROR, "CompareBuffer: Error at %i", i));\r
79 DEBUG ((DEBUG_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
11c20f4e 80 return FALSE;\r
1bfda055 81 }\r
e7108d0e 82\r
11c20f4e 83 BufferA64++;\r
84 BufferB64++;\r
85 }\r
e7108d0e 86\r
11c20f4e 87 return TRUE;\r
1bfda055 88}\r
89\r
11c20f4e 90EFI_STATUS\r
91MmcReadWriteDataTest (\r
e7108d0e
MK
92 MMC_HOST_INSTANCE *MmcHostInstance,\r
93 EFI_LBA Lba,\r
94 UINTN BufferSize\r
11c20f4e 95 )\r
96{\r
e7108d0e
MK
97 VOID *BackBuffer;\r
98 VOID *WriteBuffer;\r
99 VOID *ReadBuffer;\r
100 EFI_STATUS Status;\r
11c20f4e 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
e7108d0e 113 BackBuffer = AllocatePool (BufferSize);\r
11c20f4e 114 WriteBuffer = AllocatePool (BufferSize);\r
e7108d0e 115 ReadBuffer = AllocatePool (BufferSize);\r
11c20f4e 116\r
117 // Read (and save) buffer at a specific location\r
e7108d0e 118 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId, Lba, BufferSize, BackBuffer);\r
11c20f4e 119 if (Status != EFI_SUCCESS) {\r
120 DiagnosticLog (L"ERROR: Fail to Read Block (1)\n");\r
121 return Status;\r
122 }\r
1bfda055 123\r
11c20f4e 124 // Write buffer at the same location\r
e7108d0e
MK
125 GenerateRandomBuffer (WriteBuffer, BufferSize);\r
126 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId, Lba, BufferSize, WriteBuffer);\r
11c20f4e 127 if (Status != EFI_SUCCESS) {\r
128 DiagnosticLog (L"ERROR: Fail to Write Block (1)\n");\r
129 return Status;\r
130 }\r
1bfda055 131\r
11c20f4e 132 // Read the buffer at the same location\r
e7108d0e 133 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId, Lba, BufferSize, ReadBuffer);\r
11c20f4e 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
e7108d0e 140 if (!CompareBuffer (ReadBuffer, WriteBuffer, BufferSize)) {\r
11c20f4e 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
e7108d0e 146 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId, Lba, BufferSize, BackBuffer);\r
11c20f4e 147 if (Status != EFI_SUCCESS) {\r
148 DiagnosticLog (L"ERROR: Fail to Write Block (2)\n");\r
149 return Status;\r
150 }\r
1bfda055 151\r
11c20f4e 152 // Read the restored content\r
e7108d0e 153 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId, Lba, BufferSize, ReadBuffer);\r
11c20f4e 154 if (Status != EFI_SUCCESS) {\r
155 DiagnosticLog (L"ERROR: Fail to Read Block (3)\n");\r
156 return Status;\r
157 }\r
1bfda055 158\r
11c20f4e 159 // Check the content is correct\r
e7108d0e 160 if (!CompareBuffer (ReadBuffer, BackBuffer, BufferSize)) {\r
11c20f4e 161 DiagnosticLog (L"ERROR: Fail to Read/Write Block (2)\n");\r
162 return EFI_INVALID_PARAMETER;\r
163 }\r
1bfda055 164\r
11c20f4e 165 return EFI_SUCCESS;\r
1bfda055 166}\r
167\r
168EFI_STATUS\r
169EFIAPI\r
170MmcDriverDiagnosticsRunDiagnostics (\r
e7108d0e
MK
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
1bfda055 179 )\r
180{\r
e7108d0e
MK
181 LIST_ENTRY *CurrentLink;\r
182 MMC_HOST_INSTANCE *MmcHostInstance;\r
183 EFI_STATUS Status;\r
11c20f4e 184\r
185 if ((Language == NULL) ||\r
186 (ErrorType == NULL) ||\r
187 (Buffer == NULL) ||\r
188 (ControllerHandle == NULL) ||\r
e7108d0e
MK
189 (BufferSize == NULL))\r
190 {\r
11c20f4e 191 return EFI_INVALID_PARAMETER;\r
192 }\r
193\r
c8af31ec
OM
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
e7108d0e 199 Status = EFI_SUCCESS;\r
11c20f4e 200 *ErrorType = NULL;\r
201 *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;\r
e7108d0e 202 *Buffer = DiagnosticInitLog (DIAGNOSTIC_LOGBUFFER_MAXCHAR);\r
11c20f4e 203\r
204 DiagnosticLog (L"MMC Driver Diagnostics\n");\r
205\r
5c5a34d4
OM
206 // Find the MMC Host instance on which we have been asked to run diagnostics\r
207 MmcHostInstance = NULL;\r
e7108d0e 208 CurrentLink = mMmcHostPool.ForwardLink;\r
11c20f4e 209 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
e7108d0e
MK
210 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK (CurrentLink);\r
211 ASSERT (MmcHostInstance != NULL);\r
5c5a34d4
OM
212 if (MmcHostInstance->MmcHandle == ControllerHandle) {\r
213 break;\r
214 }\r
e7108d0e 215\r
5c5a34d4
OM
216 CurrentLink = CurrentLink->ForwardLink;\r
217 }\r
11c20f4e 218\r
5c5a34d4 219 // If we didn't find the controller, return EFI_UNSUPPORTED\r
e7108d0e
MK
220 if ( (MmcHostInstance == NULL)\r
221 || (MmcHostInstance->MmcHandle != ControllerHandle))\r
222 {\r
5c5a34d4
OM
223 return EFI_UNSUPPORTED;\r
224 }\r
11c20f4e 225\r
5c5a34d4
OM
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
11c20f4e 229\r
5c5a34d4
OM
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
11c20f4e 233\r
5c5a34d4
OM
234 // LBA=10 Size=BlockSize\r
235 DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n");\r
7ff04597
PG
236 Status = MmcReadWriteDataTest (\r
237 MmcHostInstance,\r
238 RShiftU64 (MmcHostInstance->BlockIo.Media->LastBlock, 1),\r
239 MmcHostInstance->BlockIo.Media->BlockSize\r
240 );\r
11c20f4e 241\r
5c5a34d4
OM
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
11c20f4e 245\r
5c5a34d4
OM
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
11c20f4e 249\r
250 return Status;\r
1bfda055 251}\r
252\r
253//\r
254// EFI Driver Diagnostics 2 Protocol\r
255//\r
e7108d0e
MK
256GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
257 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS)MmcDriverDiagnosticsRunDiagnostics,\r
1bfda055 258 "en"\r
259};\r