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