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