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