Dbg2Parser.c 9.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311
  1. /** @file
  2. DBG2 table parser
  3. Copyright (c) 2016 - 2020, ARM Limited. All rights reserved.
  4. SPDX-License-Identifier: BSD-2-Clause-Patent
  5. @par Reference(s):
  6. - Microsoft Debug Port Table 2 (DBG2) Specification - December 10, 2015.
  7. **/
  8. #include <IndustryStandard/DebugPort2Table.h>
  9. #include <Library/UefiLib.h>
  10. #include "AcpiParser.h"
  11. #include "AcpiTableParser.h"
  12. // Local variables pointing to the table fields
  13. STATIC CONST UINT32 *OffsetDbgDeviceInfo;
  14. STATIC CONST UINT32 *NumberDbgDeviceInfo;
  15. STATIC CONST UINT16 *DbgDevInfoLen;
  16. STATIC CONST UINT8 *GasCount;
  17. STATIC CONST UINT16 *NameSpaceStringLength;
  18. STATIC CONST UINT16 *NameSpaceStringOffset;
  19. STATIC CONST UINT16 *OEMDataLength;
  20. STATIC CONST UINT16 *OEMDataOffset;
  21. STATIC CONST UINT16 *BaseAddrRegOffset;
  22. STATIC CONST UINT16 *AddrSizeOffset;
  23. STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
  24. /**
  25. This function validates the NameSpace string length.
  26. @param [in] Ptr Pointer to the start of the buffer.
  27. @param [in] Context Pointer to context specific information e.g. this
  28. could be a pointer to the ACPI table header.
  29. **/
  30. STATIC
  31. VOID
  32. EFIAPI
  33. ValidateNameSpaceStrLen (
  34. IN UINT8 *Ptr,
  35. IN VOID *Context
  36. )
  37. {
  38. UINT16 NameSpaceStrLen;
  39. NameSpaceStrLen = *(UINT16 *)Ptr;
  40. if (NameSpaceStrLen < 2) {
  41. IncrementErrorCount ();
  42. Print (
  43. L"\nERROR: NamespaceString Length = %d. If no Namespace device exists, " \
  44. L"NamespaceString[] must contain a period '.'",
  45. NameSpaceStrLen
  46. );
  47. }
  48. }
  49. /// An ACPI_PARSER array describing the ACPI DBG2 table.
  50. STATIC CONST ACPI_PARSER Dbg2Parser[] = {
  51. PARSE_ACPI_HEADER (&AcpiHdrInfo),
  52. { L"OffsetDbgDeviceInfo", 4, 36, L"0x%x", NULL,
  53. (VOID **)&OffsetDbgDeviceInfo, NULL, NULL },
  54. { L"NumberDbgDeviceInfo", 4, 40, L"%d", NULL,
  55. (VOID **)&NumberDbgDeviceInfo, NULL, NULL }
  56. };
  57. /// An ACPI_PARSER array describing the debug device information structure
  58. /// header.
  59. STATIC CONST ACPI_PARSER DbgDevInfoHeaderParser[] = {
  60. { L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
  61. { L"Length", 2, 1, L"%d", NULL, (VOID **)&DbgDevInfoLen, NULL, NULL }
  62. };
  63. /// An ACPI_PARSER array describing the debug device information.
  64. STATIC CONST ACPI_PARSER DbgDevInfoParser[] = {
  65. { L"Revision", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },
  66. { L"Length", 2, 1, L"%d", NULL, NULL, NULL, NULL },
  67. { L"Generic Address Registers Count", 1, 3, L"0x%x", NULL,
  68. (VOID **)&GasCount, NULL, NULL },
  69. { L"NameSpace String Length", 2, 4, L"%d", NULL,
  70. (VOID **)&NameSpaceStringLength, ValidateNameSpaceStrLen, NULL },
  71. { L"NameSpace String Offset", 2, 6, L"0x%x", NULL,
  72. (VOID **)&NameSpaceStringOffset, NULL, NULL },
  73. { L"OEM Data Length", 2, 8, L"%d", NULL, (VOID **)&OEMDataLength,
  74. NULL, NULL },
  75. { L"OEM Data Offset", 2, 10, L"0x%x", NULL, (VOID **)&OEMDataOffset,
  76. NULL, NULL },
  77. { L"Port Type", 2, 12, L"0x%x", NULL, NULL, NULL, NULL },
  78. { L"Port SubType", 2, 14, L"0x%x", NULL, NULL, NULL, NULL },
  79. { L"Reserved", 2, 16, L"%x", NULL, NULL, NULL, NULL },
  80. { L"Base Address Register Offset", 2, 18, L"0x%x", NULL,
  81. (VOID **)&BaseAddrRegOffset, NULL, NULL },
  82. { L"Address Size Offset", 2, 20, L"0x%x", NULL,
  83. (VOID **)&AddrSizeOffset, NULL, NULL }
  84. };
  85. /**
  86. This function parses the debug device information structure.
  87. @param [in] Ptr Pointer to the start of the buffer.
  88. @param [in] Length Length of the debug device information structure.
  89. **/
  90. STATIC
  91. VOID
  92. EFIAPI
  93. DumpDbgDeviceInfo (
  94. IN UINT8 *Ptr,
  95. IN UINT16 Length
  96. )
  97. {
  98. UINT16 Index;
  99. UINT16 Offset;
  100. ParseAcpi (
  101. TRUE,
  102. 2,
  103. "Debug Device Info",
  104. Ptr,
  105. Length,
  106. PARSER_PARAMS (DbgDevInfoParser)
  107. );
  108. // Check if the values used to control the parsing logic have been
  109. // successfully read.
  110. if ((GasCount == NULL) ||
  111. (NameSpaceStringLength == NULL) ||
  112. (NameSpaceStringOffset == NULL) ||
  113. (OEMDataLength == NULL) ||
  114. (OEMDataOffset == NULL) ||
  115. (BaseAddrRegOffset == NULL) ||
  116. (AddrSizeOffset == NULL))
  117. {
  118. IncrementErrorCount ();
  119. Print (
  120. L"ERROR: Insufficient Debug Device Information Structure length. " \
  121. L"Length = %d.\n",
  122. Length
  123. );
  124. return;
  125. }
  126. // GAS
  127. Index = 0;
  128. Offset = *BaseAddrRegOffset;
  129. while ((Index++ < *GasCount) &&
  130. (Offset < Length))
  131. {
  132. PrintFieldName (4, L"BaseAddressRegister");
  133. Offset += (UINT16)DumpGasStruct (
  134. Ptr + Offset,
  135. 4,
  136. Length - Offset
  137. );
  138. }
  139. // Make sure the array of address sizes corresponding to each GAS fit in the
  140. // Debug Device Information structure
  141. if ((*AddrSizeOffset + (*GasCount * sizeof (UINT32))) > Length) {
  142. IncrementErrorCount ();
  143. Print (
  144. L"ERROR: Invalid GAS count. GasCount = %d. RemainingBufferLength = %d. " \
  145. L"Parsing of the Debug Device Information structure aborted.\n",
  146. *GasCount,
  147. Length - *AddrSizeOffset
  148. );
  149. return;
  150. }
  151. // Address Size
  152. Index = 0;
  153. Offset = *AddrSizeOffset;
  154. while ((Index++ < *GasCount) &&
  155. (Offset < Length))
  156. {
  157. PrintFieldName (4, L"Address Size");
  158. Print (L"0x%x\n", *((UINT32 *)(Ptr + Offset)));
  159. Offset += sizeof (UINT32);
  160. }
  161. // NameSpace String
  162. Index = 0;
  163. Offset = *NameSpaceStringOffset;
  164. PrintFieldName (4, L"NameSpace String");
  165. while ((Index++ < *NameSpaceStringLength) &&
  166. (Offset < Length))
  167. {
  168. Print (L"%c", *(Ptr + Offset));
  169. Offset++;
  170. }
  171. Print (L"\n");
  172. // OEM Data
  173. if (*OEMDataOffset != 0) {
  174. Index = 0;
  175. Offset = *OEMDataOffset;
  176. PrintFieldName (4, L"OEM Data");
  177. while ((Index++ < *OEMDataLength) &&
  178. (Offset < Length))
  179. {
  180. Print (L"%x ", *(Ptr + Offset));
  181. if ((Index & 7) == 0) {
  182. Print (L"\n%-*s ", OUTPUT_FIELD_COLUMN_WIDTH, L"");
  183. }
  184. Offset++;
  185. }
  186. Print (L"\n");
  187. }
  188. }
  189. /**
  190. This function parses the ACPI DBG2 table.
  191. When trace is enabled this function parses the DBG2 table and
  192. traces the ACPI table fields.
  193. This function also performs validation of the ACPI table fields.
  194. @param [in] Trace If TRUE, trace the ACPI fields.
  195. @param [in] Ptr Pointer to the start of the buffer.
  196. @param [in] AcpiTableLength Length of the ACPI table.
  197. @param [in] AcpiTableRevision Revision of the ACPI table.
  198. **/
  199. VOID
  200. EFIAPI
  201. ParseAcpiDbg2 (
  202. IN BOOLEAN Trace,
  203. IN UINT8 *Ptr,
  204. IN UINT32 AcpiTableLength,
  205. IN UINT8 AcpiTableRevision
  206. )
  207. {
  208. UINT32 Offset;
  209. UINT32 Index;
  210. if (!Trace) {
  211. return;
  212. }
  213. Offset = ParseAcpi (
  214. TRUE,
  215. 0,
  216. "DBG2",
  217. Ptr,
  218. AcpiTableLength,
  219. PARSER_PARAMS (Dbg2Parser)
  220. );
  221. // Check if the values used to control the parsing logic have been
  222. // successfully read.
  223. if ((OffsetDbgDeviceInfo == NULL) ||
  224. (NumberDbgDeviceInfo == NULL))
  225. {
  226. IncrementErrorCount ();
  227. Print (
  228. L"ERROR: Insufficient table length. AcpiTableLength = %d\n",
  229. AcpiTableLength
  230. );
  231. return;
  232. }
  233. Offset = *OffsetDbgDeviceInfo;
  234. Index = 0;
  235. while (Index++ < *NumberDbgDeviceInfo) {
  236. // Parse the Debug Device Information Structure header to obtain Length
  237. ParseAcpi (
  238. FALSE,
  239. 0,
  240. NULL,
  241. Ptr + Offset,
  242. AcpiTableLength - Offset,
  243. PARSER_PARAMS (DbgDevInfoHeaderParser)
  244. );
  245. // Check if the values used to control the parsing logic have been
  246. // successfully read.
  247. if (DbgDevInfoLen == NULL) {
  248. IncrementErrorCount ();
  249. Print (
  250. L"ERROR: Insufficient remaining table buffer length to read the " \
  251. L"Debug Device Information structure's 'Length' field. " \
  252. L"RemainingTableBufferLength = %d.\n",
  253. AcpiTableLength - Offset
  254. );
  255. return;
  256. }
  257. // Validate Debug Device Information Structure length
  258. if ((*DbgDevInfoLen == 0) ||
  259. ((Offset + (*DbgDevInfoLen)) > AcpiTableLength))
  260. {
  261. IncrementErrorCount ();
  262. Print (
  263. L"ERROR: Invalid Debug Device Information Structure length. " \
  264. L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
  265. *DbgDevInfoLen,
  266. Offset,
  267. AcpiTableLength
  268. );
  269. return;
  270. }
  271. DumpDbgDeviceInfo (Ptr + Offset, (*DbgDevInfoLen));
  272. Offset += (*DbgDevInfoLen);
  273. }
  274. }