Diagnostics.c 7.5 KB

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