]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
EmbeddedPkg/MmcDxe: The timeout while waiting for the programming to be complete...
[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
4 Copyright (c) 2011, ARM Limited. All rights reserved.\r
5 \r
6 This program and the accompanying materials \r
7 are licensed and made available under the terms and conditions of the BSD License \r
8 which accompanies this distribution. The full text of the license may be found at \r
9 http://opensource.org/licenses/bsd-license.php \r
10\r
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS, \r
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED. \r
13\r
14**/\r
15\r
16#include <Uefi.h>\r
17#include <Library/DebugLib.h>\r
18#include <Library/BaseMemoryLib.h>\r
19#include <Library/MemoryAllocationLib.h>\r
20\r
21#include "Mmc.h"\r
22\r
23#define DIAGNOSTIC_LOGBUFFER_MAXCHAR 1024\r
24\r
25CHAR16* mLogBuffer = NULL;\r
26UINTN mLogRemainChar = 0;\r
27\r
11c20f4e 28CHAR16*\r
29DiagnosticInitLog (\r
30 UINTN MaxBufferChar\r
31 )\r
32{\r
33 mLogRemainChar = MaxBufferChar;\r
34 mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));\r
35 return mLogBuffer;\r
1bfda055 36}\r
37\r
11c20f4e 38UINTN\r
39DiagnosticLog (\r
40 CONST CHAR16* Str\r
41 )\r
42{\r
43 UINTN len = StrLen (Str);\r
44 if (len <= mLogRemainChar) {\r
45 mLogRemainChar -= len;\r
46 StrCpy (mLogBuffer, Str);\r
47 mLogBuffer += len;\r
48 return len;\r
49 } else {\r
50 return 0;\r
51 }\r
1bfda055 52}\r
53\r
11c20f4e 54VOID\r
55GenerateRandomBuffer (\r
56 VOID* Buffer,\r
57 UINTN BufferSize\r
58 )\r
59{\r
60 UINT64 i;\r
61 UINT64* Buffer64 = (UINT64*)Buffer;\r
1bfda055 62\r
11c20f4e 63 for (i = 0; i < (BufferSize >> 3); i++) {\r
64 *Buffer64 = i | (~i << 32);\r
65 Buffer64++;\r
66 }\r
1bfda055 67}\r
68\r
11c20f4e 69BOOLEAN\r
70CompareBuffer (\r
71 VOID *BufferA,\r
72 VOID *BufferB,\r
73 UINTN BufferSize\r
74 )\r
75{\r
76 UINTN i;\r
77 UINT64* BufferA64 = (UINT64*)BufferA;\r
78 UINT64* BufferB64 = (UINT64*)BufferB;\r
79\r
80 for (i = 0; i < (BufferSize >> 3); i++) {\r
81 if (*BufferA64 != *BufferB64) {\r
82 DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));\r
83 DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
84 return FALSE;\r
1bfda055 85 }\r
11c20f4e 86 BufferA64++;\r
87 BufferB64++;\r
88 }\r
89 return TRUE;\r
1bfda055 90}\r
91\r
11c20f4e 92EFI_STATUS\r
93MmcReadWriteDataTest (\r
94 MMC_HOST_INSTANCE *MmcHostInstance,\r
95 EFI_LBA Lba,\r
96 UINTN BufferSize\r
97 )\r
98{\r
99 VOID *BackBuffer;\r
100 VOID *WriteBuffer;\r
101 VOID *ReadBuffer;\r
102 EFI_STATUS Status;\r
103\r
104 // Check if a Media is Present\r
105 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
106 DiagnosticLog (L"ERROR: No Media Present\n");\r
107 return EFI_NO_MEDIA;\r
108 }\r
109\r
110 if (MmcHostInstance->State != MmcTransferState) {\r
111 DiagnosticLog (L"ERROR: Not ready for Transfer state\n");\r
112 return EFI_NOT_READY;\r
113 }\r
114\r
115 BackBuffer = AllocatePool (BufferSize);\r
116 WriteBuffer = AllocatePool (BufferSize);\r
117 ReadBuffer = AllocatePool (BufferSize);\r
118\r
119 // Read (and save) buffer at a specific location\r
120 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
121 if (Status != EFI_SUCCESS) {\r
122 DiagnosticLog (L"ERROR: Fail to Read Block (1)\n");\r
123 return Status;\r
124 }\r
1bfda055 125\r
11c20f4e 126 // Write buffer at the same location\r
127 GenerateRandomBuffer (WriteBuffer,BufferSize);\r
128 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);\r
129 if (Status != EFI_SUCCESS) {\r
130 DiagnosticLog (L"ERROR: Fail to Write Block (1)\n");\r
131 return Status;\r
132 }\r
1bfda055 133\r
11c20f4e 134 // Read the buffer at the same location\r
135 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
136 if (Status != EFI_SUCCESS) {\r
137 DiagnosticLog (L"ERROR: Fail to Read Block (2)\n");\r
138 return Status;\r
139 }\r
140\r
141 // Check that is conform\r
142 if (!CompareBuffer (ReadBuffer,WriteBuffer,BufferSize)) {\r
143 DiagnosticLog (L"ERROR: Fail to Read/Write Block (1)\n");\r
144 return EFI_INVALID_PARAMETER;\r
145 }\r
146\r
147 // Restore content at the original location\r
148 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
149 if (Status != EFI_SUCCESS) {\r
150 DiagnosticLog (L"ERROR: Fail to Write Block (2)\n");\r
151 return Status;\r
152 }\r
1bfda055 153\r
11c20f4e 154 // Read the restored content\r
155 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
156 if (Status != EFI_SUCCESS) {\r
157 DiagnosticLog (L"ERROR: Fail to Read Block (3)\n");\r
158 return Status;\r
159 }\r
1bfda055 160\r
11c20f4e 161 // Check the content is correct\r
162 if (!CompareBuffer (ReadBuffer,BackBuffer,BufferSize)) {\r
163 DiagnosticLog (L"ERROR: Fail to Read/Write Block (2)\n");\r
164 return EFI_INVALID_PARAMETER;\r
165 }\r
1bfda055 166\r
11c20f4e 167 return EFI_SUCCESS;\r
1bfda055 168}\r
169\r
170EFI_STATUS\r
171EFIAPI\r
172MmcDriverDiagnosticsRunDiagnostics (\r
173 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,\r
174 IN EFI_HANDLE ControllerHandle,\r
175 IN EFI_HANDLE ChildHandle OPTIONAL,\r
176 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,\r
177 IN CHAR8 *Language,\r
178 OUT EFI_GUID **ErrorType,\r
179 OUT UINTN *BufferSize,\r
180 OUT CHAR16 **Buffer\r
181 )\r
182{\r
11c20f4e 183 LIST_ENTRY *CurrentLink;\r
184 MMC_HOST_INSTANCE *MmcHostInstance;\r
185 EFI_STATUS Status;\r
186\r
187 if ((Language == NULL) ||\r
188 (ErrorType == NULL) ||\r
189 (Buffer == NULL) ||\r
190 (ControllerHandle == NULL) ||\r
191 (BufferSize == NULL)) {\r
192 return EFI_INVALID_PARAMETER;\r
193 }\r
194\r
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
202 // For each MMC instance\r
203 CurrentLink = mMmcHostPool.ForwardLink;\r
204 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
205 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
206 ASSERT(MmcHostInstance != NULL);\r
207\r
208 // LBA=1 Size=BlockSize\r
209 DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block\n");\r
210 Status = MmcReadWriteDataTest (MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
211\r
212 // LBA=2 Size=BlockSize\r
213 DiagnosticLog (L"MMC Driver Diagnostics - Test: Second Block\n");\r
214 Status = MmcReadWriteDataTest (MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);\r
215\r
216 // LBA=10 Size=BlockSize\r
217 DiagnosticLog (L"MMC Driver Diagnostics - Test: Any Block\n");\r
218 Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
219\r
220 // LBA=LastBlock Size=BlockSize\r
221 DiagnosticLog (L"MMC Driver Diagnostics - Test: Last Block\n");\r
222 Status = MmcReadWriteDataTest (MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);\r
223\r
224 // LBA=1 Size=2*BlockSize\r
225 DiagnosticLog (L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");\r
226 Status = MmcReadWriteDataTest (MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);\r
227\r
228 CurrentLink = CurrentLink->ForwardLink;\r
229 }\r
230\r
231 return Status;\r
1bfda055 232}\r
233\r
234//\r
235// EFI Driver Diagnostics 2 Protocol\r
236//\r
237GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
238 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,\r
239 "en"\r
240};\r