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