]> git.proxmox.com Git - mirror_edk2.git/blame - EmbeddedPkg/Universal/MmcDxe/Diagnostics.c
EmbeddedPkg/MmcDxe: Improved parameters checking
[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
28CHAR16* DiagnosticInitLog(UINTN MaxBufferChar) {\r
29 mLogRemainChar = MaxBufferChar;\r
30 mLogBuffer = AllocatePool ((UINTN)MaxBufferChar * sizeof(CHAR16));\r
31 return mLogBuffer;\r
32}\r
33\r
34UINTN DiagnosticLog(CONST CHAR16* Str) {\r
35 UINTN len = StrLen (Str);\r
36 if (len <= mLogRemainChar) {\r
37 mLogRemainChar -= len;\r
38 StrCpy (mLogBuffer, Str);\r
39 mLogBuffer += len;\r
40 return len;\r
41 } else {\r
42 return 0;\r
43 }\r
44}\r
45\r
46VOID GenerateRandomBuffer(VOID* Buffer, UINTN BufferSize) {\r
47 UINT64 i;\r
48 UINT64* Buffer64 = (UINT64*)Buffer;\r
49\r
50 for (i = 0; i < (BufferSize >> 3); i++) {\r
51 *Buffer64 = i | (~i << 32);\r
52 Buffer64++;\r
53 }\r
54}\r
55\r
56BOOLEAN CompareBuffer(VOID *BufferA, VOID *BufferB, UINTN BufferSize) {\r
57 UINTN i;\r
58 UINT64* BufferA64 = (UINT64*)BufferA;\r
59 UINT64* BufferB64 = (UINT64*)BufferB;\r
60\r
61 for (i = 0; i < (BufferSize >> 3); i++) {\r
62 if (*BufferA64 != *BufferB64) {\r
63 DEBUG((EFI_D_ERROR, "CompareBuffer: Error at %i", i));\r
64 DEBUG((EFI_D_ERROR, "(0x%lX) != (0x%lX)\n", *BufferA64, *BufferB64));\r
65 return FALSE;\r
66 }\r
67 BufferA64++;\r
68 BufferB64++;\r
69 }\r
70 return TRUE;\r
71}\r
72\r
73EFI_STATUS MmcReadWriteDataTest(MMC_HOST_INSTANCE *MmcHostInstance, EFI_LBA Lba, UINTN BufferSize) {\r
74 VOID *BackBuffer;\r
75 VOID *WriteBuffer;\r
76 VOID *ReadBuffer;\r
77 EFI_STATUS Status;\r
78 \r
79 // Check if a Media is Present\r
80 if (!MmcHostInstance->BlockIo.Media->MediaPresent) {\r
81 DiagnosticLog(L"ERROR: No Media Present\n");\r
82 return EFI_NO_MEDIA;\r
83 }\r
84\r
85 if (MmcHostInstance->State != MmcTransferState) {\r
86 DiagnosticLog(L"ERROR: Not ready for Transfer state\n");\r
87 return EFI_NOT_READY;\r
88 }\r
89\r
90 BackBuffer = AllocatePool(BufferSize);\r
91 WriteBuffer = AllocatePool(BufferSize);\r
92 ReadBuffer = AllocatePool(BufferSize);\r
93\r
94 // Read (and save) buffer at a specific location\r
95 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
96 if (Status != EFI_SUCCESS) {\r
97 DiagnosticLog(L"ERROR: Fail to Read Block (1)\n");\r
98 return Status;\r
99 }\r
100\r
101 // Write buffer at the same location\r
102 GenerateRandomBuffer(WriteBuffer,BufferSize);\r
103 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,WriteBuffer);\r
104 if (Status != EFI_SUCCESS) {\r
105 DiagnosticLog(L"ERROR: Fail to Write Block (1)\n");\r
106 return Status;\r
107 }\r
108\r
109 // Read the buffer at the same location\r
110 Status = MmcReadBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,ReadBuffer);\r
111 if (Status != EFI_SUCCESS) {\r
112 DiagnosticLog(L"ERROR: Fail to Read Block (2)\n");\r
113 return Status;\r
114 }\r
115\r
116 // Check that is conform\r
117 if (!CompareBuffer(ReadBuffer,WriteBuffer,BufferSize)) {\r
118 DiagnosticLog(L"ERROR: Fail to Read/Write Block (1)\n");\r
119 return EFI_INVALID_PARAMETER;\r
120 }\r
121\r
122 // Restore content at the original location\r
123 Status = MmcWriteBlocks (&(MmcHostInstance->BlockIo), MmcHostInstance->BlockIo.Media->MediaId,Lba,BufferSize,BackBuffer);\r
124 if (Status != EFI_SUCCESS) {\r
125 DiagnosticLog(L"ERROR: Fail to Write Block (2)\n");\r
126 return Status;\r
127 }\r
128\r
129 // Read the restored content\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 (3)\n");\r
133 return Status;\r
134 }\r
135\r
136 // Check the content is correct\r
137 if (!CompareBuffer(ReadBuffer,BackBuffer,BufferSize)) {\r
138 DiagnosticLog(L"ERROR: Fail to Read/Write Block (2)\n");\r
139 return EFI_INVALID_PARAMETER;\r
140 }\r
141\r
142 return EFI_SUCCESS;\r
143}\r
144\r
145EFI_STATUS\r
146EFIAPI\r
147MmcDriverDiagnosticsRunDiagnostics (\r
148 IN EFI_DRIVER_DIAGNOSTICS_PROTOCOL *This,\r
149 IN EFI_HANDLE ControllerHandle,\r
150 IN EFI_HANDLE ChildHandle OPTIONAL,\r
151 IN EFI_DRIVER_DIAGNOSTIC_TYPE DiagnosticType,\r
152 IN CHAR8 *Language,\r
153 OUT EFI_GUID **ErrorType,\r
154 OUT UINTN *BufferSize,\r
155 OUT CHAR16 **Buffer\r
156 )\r
157{\r
158 LIST_ENTRY *CurrentLink;\r
159 MMC_HOST_INSTANCE *MmcHostInstance;\r
160 EFI_STATUS Status;\r
161\r
162 if (Language == NULL ||\r
163 ErrorType == NULL ||\r
164 Buffer == NULL ||\r
165 ControllerHandle == NULL ||\r
166 BufferSize == NULL) {\r
167 return EFI_INVALID_PARAMETER;\r
168 }\r
169\r
170 Status = EFI_SUCCESS;\r
171 *ErrorType = NULL;\r
172 *BufferSize = DIAGNOSTIC_LOGBUFFER_MAXCHAR;\r
173 *Buffer = DiagnosticInitLog(DIAGNOSTIC_LOGBUFFER_MAXCHAR);\r
174\r
175 DiagnosticLog(L"MMC Driver Diagnostics\n");\r
176\r
177 // For each MMC instance\r
178 CurrentLink = mMmcHostPool.ForwardLink;\r
179 while (CurrentLink != NULL && CurrentLink != &mMmcHostPool && (Status == EFI_SUCCESS)) {\r
180 MmcHostInstance = MMC_HOST_INSTANCE_FROM_LINK(CurrentLink);\r
181 ASSERT(MmcHostInstance != NULL);\r
182\r
183 // LBA=1 Size=BlockSize\r
184 DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block\n");\r
185 Status = MmcReadWriteDataTest(MmcHostInstance, 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
186\r
187 // LBA=2 Size=BlockSize\r
188 DiagnosticLog(L"MMC Driver Diagnostics - Test: Second Block\n");\r
189 Status = MmcReadWriteDataTest(MmcHostInstance, 2, MmcHostInstance->BlockIo.Media->BlockSize);\r
190\r
191 // LBA=10 Size=BlockSize\r
192 DiagnosticLog(L"MMC Driver Diagnostics - Test: Any Block\n");\r
193 Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock >> 1, MmcHostInstance->BlockIo.Media->BlockSize);\r
194\r
195 // LBA=LastBlock Size=BlockSize\r
196 DiagnosticLog(L"MMC Driver Diagnostics - Test: Last Block\n");\r
197 Status = MmcReadWriteDataTest(MmcHostInstance, MmcHostInstance->BlockIo.Media->LastBlock, MmcHostInstance->BlockIo.Media->BlockSize);\r
198\r
199 // LBA=1 Size=2*BlockSize\r
200 DiagnosticLog(L"MMC Driver Diagnostics - Test: First Block / 2 BlockSSize\n");\r
201 Status = MmcReadWriteDataTest(MmcHostInstance, 1, 2*MmcHostInstance->BlockIo.Media->BlockSize);\r
202\r
203 CurrentLink = CurrentLink->ForwardLink;\r
204 }\r
205\r
206 return Status;\r
207}\r
208\r
209//\r
210// EFI Driver Diagnostics 2 Protocol\r
211//\r
212GLOBAL_REMOVE_IF_UNREFERENCED EFI_DRIVER_DIAGNOSTICS2_PROTOCOL gMmcDriverDiagnostics2 = {\r
213 (EFI_DRIVER_DIAGNOSTICS2_RUN_DIAGNOSTICS) MmcDriverDiagnosticsRunDiagnostics,\r
214 "en"\r
215};\r