]> git.proxmox.com Git - mirror_edk2.git/blame - ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / AcpiParser.c
CommitLineData
a6eaba4d 1/** @file\r
ee4dc24f
RN
2 ACPI parser\r
3\r
10bf6c40 4 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.\r
691b1786 5 Copyright (c) 2022, AMD Incorporated. All rights reserved.\r
56ba3746 6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
ee4dc24f
RN
7**/\r
8\r
9#include <Uefi.h>\r
10#include <Library/UefiLib.h>\r
11#include <Library/UefiBootServicesTableLib.h>\r
691b1786 12#include <Library/BaseMemoryLib.h>\r
ee4dc24f
RN
13#include "AcpiParser.h"\r
14#include "AcpiView.h"\r
e18ac66d 15#include "AcpiViewConfig.h"\r
ee4dc24f 16\r
47d20b54
MK
17STATIC UINT32 gIndent;\r
18STATIC UINT32 mTableErrorCount;\r
19STATIC UINT32 mTableWarningCount;\r
ee4dc24f 20\r
47d20b54 21STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
f75c7478
DB
22\r
23/**\r
24 An ACPI_PARSER array describing the ACPI header.\r
25**/\r
47d20b54 26STATIC CONST ACPI_PARSER AcpiHeaderParser[] = {\r
f75c7478
DB
27 PARSE_ACPI_HEADER (&AcpiHdrInfo)\r
28};\r
29\r
a6eaba4d
DB
30/**\r
31 This function resets the ACPI table error counter to Zero.\r
32**/\r
ee4dc24f
RN
33VOID\r
34ResetErrorCount (\r
35 VOID\r
36 )\r
37{\r
38 mTableErrorCount = 0;\r
39}\r
40\r
a6eaba4d
DB
41/**\r
42 This function returns the ACPI table error count.\r
ee4dc24f
RN
43\r
44 @retval Returns the count of errors detected in the ACPI tables.\r
a6eaba4d 45**/\r
ee4dc24f
RN
46UINT32\r
47GetErrorCount (\r
48 VOID\r
49 )\r
50{\r
51 return mTableErrorCount;\r
52}\r
53\r
a6eaba4d
DB
54/**\r
55 This function resets the ACPI table warning counter to Zero.\r
56**/\r
ee4dc24f
RN
57VOID\r
58ResetWarningCount (\r
59 VOID\r
60 )\r
61{\r
62 mTableWarningCount = 0;\r
63}\r
64\r
a6eaba4d
DB
65/**\r
66 This function returns the ACPI table warning count.\r
ee4dc24f
RN
67\r
68 @retval Returns the count of warning detected in the ACPI tables.\r
a6eaba4d 69**/\r
ee4dc24f
RN
70UINT32\r
71GetWarningCount (\r
72 VOID\r
73 )\r
74{\r
75 return mTableWarningCount;\r
76}\r
77\r
a6eaba4d
DB
78/**\r
79 This function increments the ACPI table error counter.\r
80**/\r
ee4dc24f
RN
81VOID\r
82EFIAPI\r
83IncrementErrorCount (\r
84 VOID\r
85 )\r
86{\r
87 mTableErrorCount++;\r
88}\r
89\r
a6eaba4d
DB
90/**\r
91 This function increments the ACPI table warning counter.\r
92**/\r
ee4dc24f
RN
93VOID\r
94EFIAPI\r
95IncrementWarningCount (\r
96 VOID\r
97 )\r
98{\r
99 mTableWarningCount++;\r
100}\r
101\r
a6eaba4d
DB
102/**\r
103 This function verifies the ACPI table checksum.\r
ee4dc24f
RN
104\r
105 This function verifies the checksum for the ACPI table and optionally\r
106 prints the status.\r
107\r
108 @param [in] Log If TRUE log the status of the checksum.\r
109 @param [in] Ptr Pointer to the start of the table buffer.\r
110 @param [in] Length The length of the buffer.\r
111\r
112 @retval TRUE The checksum is OK.\r
113 @retval FALSE The checksum failed.\r
a6eaba4d 114**/\r
ee4dc24f
RN
115BOOLEAN\r
116EFIAPI\r
117VerifyChecksum (\r
47d20b54
MK
118 IN BOOLEAN Log,\r
119 IN UINT8 *Ptr,\r
120 IN UINT32 Length\r
ee4dc24f
RN
121 )\r
122{\r
47d20b54
MK
123 UINTN ByteCount;\r
124 UINT8 Checksum;\r
125 UINTN OriginalAttribute;\r
ee4dc24f 126\r
0154e02d
SZ
127 //\r
128 // set local variables to suppress incorrect compiler/analyzer warnings\r
129 //\r
130 OriginalAttribute = 0;\r
47d20b54
MK
131 ByteCount = 0;\r
132 Checksum = 0;\r
f75c7478 133\r
ee4dc24f
RN
134 while (ByteCount < Length) {\r
135 Checksum += *(Ptr++);\r
136 ByteCount++;\r
137 }\r
138\r
139 if (Log) {\r
140 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
141 if (Checksum == 0) {\r
142 if (GetColourHighlighting ()) {\r
143 gST->ConOut->SetAttribute (\r
144 gST->ConOut,\r
47d20b54
MK
145 EFI_TEXT_ATTR (\r
146 EFI_GREEN,\r
147 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
148 )\r
ee4dc24f
RN
149 );\r
150 }\r
47d20b54 151\r
5a119220 152 Print (L"Table Checksum : OK\n\n");\r
ee4dc24f
RN
153 } else {\r
154 IncrementErrorCount ();\r
155 if (GetColourHighlighting ()) {\r
156 gST->ConOut->SetAttribute (\r
157 gST->ConOut,\r
47d20b54
MK
158 EFI_TEXT_ATTR (\r
159 EFI_RED,\r
160 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
161 )\r
ee4dc24f
RN
162 );\r
163 }\r
47d20b54 164\r
5a119220 165 Print (L"Table Checksum : FAILED (0x%X)\n\n", Checksum);\r
ee4dc24f 166 }\r
47d20b54 167\r
ee4dc24f
RN
168 if (GetColourHighlighting ()) {\r
169 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
170 }\r
171 }\r
172\r
173 return (Checksum == 0);\r
174}\r
175\r
a6eaba4d
DB
176/**\r
177 This function performs a raw data dump of the ACPI table.\r
ee4dc24f
RN
178\r
179 @param [in] Ptr Pointer to the start of the table buffer.\r
180 @param [in] Length The length of the buffer.\r
a6eaba4d 181**/\r
ee4dc24f
RN
182VOID\r
183EFIAPI\r
184DumpRaw (\r
47d20b54
MK
185 IN UINT8 *Ptr,\r
186 IN UINT32 Length\r
ee4dc24f
RN
187 )\r
188{\r
47d20b54
MK
189 UINTN ByteCount;\r
190 UINTN PartLineChars;\r
191 UINTN AsciiBufferIndex;\r
192 CHAR8 AsciiBuffer[17];\r
ee4dc24f 193\r
47d20b54 194 ByteCount = 0;\r
f75c7478
DB
195 AsciiBufferIndex = 0;\r
196\r
ee4dc24f
RN
197 Print (L"Address : 0x%p\n", Ptr);\r
198 Print (L"Length : %d\n", Length);\r
199\r
200 while (ByteCount < Length) {\r
201 if ((ByteCount & 0x0F) == 0) {\r
202 AsciiBuffer[AsciiBufferIndex] = '\0';\r
203 Print (L" %a\n%08X : ", AsciiBuffer, ByteCount);\r
204 AsciiBufferIndex = 0;\r
205 } else if ((ByteCount & 0x07) == 0) {\r
206 Print (L"- ");\r
207 }\r
208\r
209 if ((*Ptr >= ' ') && (*Ptr < 0x7F)) {\r
210 AsciiBuffer[AsciiBufferIndex++] = *Ptr;\r
211 } else {\r
212 AsciiBuffer[AsciiBufferIndex++] = '.';\r
213 }\r
214\r
215 Print (L"%02X ", *Ptr++);\r
216\r
217 ByteCount++;\r
218 }\r
219\r
220 // Justify the final line using spaces before printing\r
221 // the ASCII data.\r
222 PartLineChars = (Length & 0x0F);\r
223 if (PartLineChars != 0) {\r
224 PartLineChars = 48 - (PartLineChars * 3);\r
225 if ((Length & 0x0F) <= 8) {\r
226 PartLineChars += 2;\r
227 }\r
47d20b54 228\r
ee4dc24f
RN
229 while (PartLineChars > 0) {\r
230 Print (L" ");\r
231 PartLineChars--;\r
232 }\r
233 }\r
234\r
235 // Print ASCII data for the final line.\r
236 AsciiBuffer[AsciiBufferIndex] = '\0';\r
5a119220 237 Print (L" %a\n\n", AsciiBuffer);\r
ee4dc24f
RN
238}\r
239\r
a6eaba4d
DB
240/**\r
241 This function traces 1 byte of data as specified in the format string.\r
ee4dc24f
RN
242\r
243 @param [in] Format The format string for tracing the data.\r
244 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 245**/\r
ee4dc24f
RN
246VOID\r
247EFIAPI\r
248DumpUint8 (\r
47d20b54
MK
249 IN CONST CHAR16 *Format,\r
250 IN UINT8 *Ptr\r
ee4dc24f
RN
251 )\r
252{\r
253 Print (Format, *Ptr);\r
254}\r
255\r
a6eaba4d
DB
256/**\r
257 This function traces 2 bytes of data as specified in the format string.\r
ee4dc24f
RN
258\r
259 @param [in] Format The format string for tracing the data.\r
260 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 261**/\r
ee4dc24f
RN
262VOID\r
263EFIAPI\r
264DumpUint16 (\r
47d20b54
MK
265 IN CONST CHAR16 *Format,\r
266 IN UINT8 *Ptr\r
ee4dc24f
RN
267 )\r
268{\r
47d20b54 269 Print (Format, *(UINT16 *)Ptr);\r
ee4dc24f
RN
270}\r
271\r
a6eaba4d
DB
272/**\r
273 This function traces 4 bytes of data as specified in the format string.\r
ee4dc24f
RN
274\r
275 @param [in] Format The format string for tracing the data.\r
276 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 277**/\r
ee4dc24f
RN
278VOID\r
279EFIAPI\r
280DumpUint32 (\r
47d20b54
MK
281 IN CONST CHAR16 *Format,\r
282 IN UINT8 *Ptr\r
ee4dc24f
RN
283 )\r
284{\r
47d20b54 285 Print (Format, *(UINT32 *)Ptr);\r
ee4dc24f
RN
286}\r
287\r
a6eaba4d
DB
288/**\r
289 This function traces 8 bytes of data as specified by the format string.\r
ee4dc24f
RN
290\r
291 @param [in] Format The format string for tracing the data.\r
292 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 293**/\r
ee4dc24f
RN
294VOID\r
295EFIAPI\r
296DumpUint64 (\r
47d20b54
MK
297 IN CONST CHAR16 *Format,\r
298 IN UINT8 *Ptr\r
ee4dc24f
RN
299 )\r
300{\r
301 // Some fields are not aligned and this causes alignment faults\r
302 // on ARM platforms if the compiler generates LDRD instructions.\r
303 // Perform word access so that LDRD instructions are not generated.\r
47d20b54 304 UINT64 Val;\r
f75c7478 305\r
47d20b54 306 Val = *(UINT32 *)(Ptr + sizeof (UINT32));\r
f75c7478 307\r
47d20b54
MK
308 Val = LShiftU64 (Val, 32);\r
309 Val |= (UINT64)*(UINT32 *)Ptr;\r
ee4dc24f
RN
310\r
311 Print (Format, Val);\r
312}\r
313\r
a6eaba4d
DB
314/**\r
315 This function traces 3 characters which can be optionally\r
316 formated using the format string if specified.\r
ee4dc24f
RN
317\r
318 If no format string is specified the Format must be NULL.\r
319\r
320 @param [in] Format Optional format string for tracing the data.\r
321 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 322**/\r
ee4dc24f
RN
323VOID\r
324EFIAPI\r
325Dump3Chars (\r
47d20b54
MK
326 IN CONST CHAR16 *Format OPTIONAL,\r
327 IN UINT8 *Ptr\r
ee4dc24f
RN
328 )\r
329{\r
330 Print (\r
331 (Format != NULL) ? Format : L"%c%c%c",\r
332 Ptr[0],\r
333 Ptr[1],\r
334 Ptr[2]\r
335 );\r
336}\r
337\r
a6eaba4d
DB
338/**\r
339 This function traces 4 characters which can be optionally\r
340 formated using the format string if specified.\r
ee4dc24f
RN
341\r
342 If no format string is specified the Format must be NULL.\r
343\r
344 @param [in] Format Optional format string for tracing the data.\r
345 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 346**/\r
ee4dc24f
RN
347VOID\r
348EFIAPI\r
349Dump4Chars (\r
47d20b54
MK
350 IN CONST CHAR16 *Format OPTIONAL,\r
351 IN UINT8 *Ptr\r
ee4dc24f
RN
352 )\r
353{\r
354 Print (\r
355 (Format != NULL) ? Format : L"%c%c%c%c",\r
356 Ptr[0],\r
357 Ptr[1],\r
358 Ptr[2],\r
359 Ptr[3]\r
360 );\r
361}\r
362\r
a6eaba4d
DB
363/**\r
364 This function traces 6 characters which can be optionally\r
365 formated using the format string if specified.\r
ee4dc24f
RN
366\r
367 If no format string is specified the Format must be NULL.\r
368\r
369 @param [in] Format Optional format string for tracing the data.\r
370 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 371**/\r
ee4dc24f
RN
372VOID\r
373EFIAPI\r
374Dump6Chars (\r
47d20b54
MK
375 IN CONST CHAR16 *Format OPTIONAL,\r
376 IN UINT8 *Ptr\r
ee4dc24f
RN
377 )\r
378{\r
379 Print (\r
380 (Format != NULL) ? Format : L"%c%c%c%c%c%c",\r
381 Ptr[0],\r
382 Ptr[1],\r
383 Ptr[2],\r
384 Ptr[3],\r
385 Ptr[4],\r
386 Ptr[5]\r
387 );\r
388}\r
389\r
a6eaba4d
DB
390/**\r
391 This function traces 8 characters which can be optionally\r
392 formated using the format string if specified.\r
ee4dc24f
RN
393\r
394 If no format string is specified the Format must be NULL.\r
395\r
396 @param [in] Format Optional format string for tracing the data.\r
397 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 398**/\r
ee4dc24f
RN
399VOID\r
400EFIAPI\r
401Dump8Chars (\r
47d20b54
MK
402 IN CONST CHAR16 *Format OPTIONAL,\r
403 IN UINT8 *Ptr\r
ee4dc24f
RN
404 )\r
405{\r
406 Print (\r
407 (Format != NULL) ? Format : L"%c%c%c%c%c%c%c%c",\r
408 Ptr[0],\r
409 Ptr[1],\r
410 Ptr[2],\r
411 Ptr[3],\r
412 Ptr[4],\r
413 Ptr[5],\r
414 Ptr[6],\r
415 Ptr[7]\r
416 );\r
417}\r
418\r
710ff749
KK
419/**\r
420 This function traces 12 characters which can be optionally\r
421 formated using the format string if specified.\r
422\r
423 If no format string is specified the Format must be NULL.\r
424\r
425 @param [in] Format Optional format string for tracing the data.\r
426 @param [in] Ptr Pointer to the start of the buffer.\r
427**/\r
428VOID\r
429EFIAPI\r
430Dump12Chars (\r
47d20b54
MK
431 IN CONST CHAR16 *Format OPTIONAL,\r
432 IN UINT8 *Ptr\r
710ff749
KK
433 )\r
434{\r
435 Print (\r
436 (Format != NULL) ? Format : L"%c%c%c%c%c%c%c%c%c%c%c%c",\r
437 Ptr[0],\r
438 Ptr[1],\r
439 Ptr[2],\r
440 Ptr[3],\r
441 Ptr[4],\r
442 Ptr[5],\r
443 Ptr[6],\r
444 Ptr[7],\r
445 Ptr[8],\r
446 Ptr[9],\r
447 Ptr[10],\r
448 Ptr[11]\r
449 );\r
450}\r
451\r
a6eaba4d
DB
452/**\r
453 This function indents and prints the ACPI table Field Name.\r
ee4dc24f
RN
454\r
455 @param [in] Indent Number of spaces to add to the global table indent.\r
456 The global table indent is 0 by default; however\r
457 this value is updated on entry to the ParseAcpi()\r
458 by adding the indent value provided to ParseAcpi()\r
459 and restored back on exit.\r
460 Therefore the total indent in the output is\r
461 dependent on from where this function is called.\r
462 @param [in] FieldName Pointer to the Field Name.\r
a6eaba4d 463**/\r
ee4dc24f
RN
464VOID\r
465EFIAPI\r
466PrintFieldName (\r
47d20b54
MK
467 IN UINT32 Indent,\r
468 IN CONST CHAR16 *FieldName\r
469 )\r
ee4dc24f
RN
470{\r
471 Print (\r
472 L"%*a%-*s : ",\r
473 gIndent + Indent,\r
474 "",\r
475 (OUTPUT_FIELD_COLUMN_WIDTH - gIndent - Indent),\r
476 FieldName\r
477 );\r
478}\r
479\r
a6eaba4d
DB
480/**\r
481 This function is used to parse an ACPI table buffer.\r
ee4dc24f
RN
482\r
483 The ACPI table buffer is parsed using the ACPI table parser information\r
484 specified by a pointer to an array of ACPI_PARSER elements. This parser\r
485 function iterates through each item on the ACPI_PARSER array and logs the\r
486 ACPI table fields.\r
487\r
488 This function can optionally be used to parse ACPI tables and fetch specific\r
489 field values. The ItemPtr member of the ACPI_PARSER structure (where used)\r
490 is updated by this parser function to point to the selected field data\r
491 (e.g. useful for variable length nested fields).\r
492\r
493 @param [in] Trace Trace the ACPI fields TRUE else only parse the\r
494 table.\r
495 @param [in] Indent Number of spaces to indent the output.\r
496 @param [in] AsciiName Optional pointer to an ASCII string that describes\r
497 the table being parsed.\r
498 @param [in] Ptr Pointer to the start of the buffer.\r
499 @param [in] Length Length of the buffer pointed by Ptr.\r
500 @param [in] Parser Pointer to an array of ACPI_PARSER structure that\r
501 describes the table being parsed.\r
502 @param [in] ParserItems Number of items in the ACPI_PARSER array.\r
503\r
504 @retval Number of bytes parsed.\r
a6eaba4d 505**/\r
ee4dc24f
RN
506UINT32\r
507EFIAPI\r
508ParseAcpi (\r
509 IN BOOLEAN Trace,\r
510 IN UINT32 Indent,\r
47d20b54
MK
511 IN CONST CHAR8 *AsciiName OPTIONAL,\r
512 IN UINT8 *Ptr,\r
ee4dc24f 513 IN UINT32 Length,\r
47d20b54 514 IN CONST ACPI_PARSER *Parser,\r
ee4dc24f 515 IN UINT32 ParserItems\r
47d20b54 516 )\r
ee4dc24f 517{\r
47d20b54
MK
518 UINT32 Index;\r
519 UINT32 Offset;\r
520 BOOLEAN HighLight;\r
521 UINTN OriginalAttribute;\r
f75c7478 522\r
0154e02d
SZ
523 //\r
524 // set local variables to suppress incorrect compiler/analyzer warnings\r
525 //\r
526 OriginalAttribute = 0;\r
47d20b54 527 Offset = 0;\r
ee4dc24f
RN
528\r
529 // Increment the Indent\r
530 gIndent += Indent;\r
531\r
47d20b54 532 if (Trace && (AsciiName != NULL)) {\r
f75c7478 533 HighLight = GetColourHighlighting ();\r
ee4dc24f
RN
534\r
535 if (HighLight) {\r
536 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
537 gST->ConOut->SetAttribute (\r
538 gST->ConOut,\r
47d20b54
MK
539 EFI_TEXT_ATTR (\r
540 EFI_YELLOW,\r
541 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
542 )\r
ee4dc24f
RN
543 );\r
544 }\r
47d20b54 545\r
ee4dc24f
RN
546 Print (\r
547 L"%*a%-*a :\n",\r
548 gIndent,\r
549 "",\r
550 (OUTPUT_FIELD_COLUMN_WIDTH - gIndent),\r
551 AsciiName\r
552 );\r
553 if (HighLight) {\r
554 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
555 }\r
556 }\r
557\r
558 for (Index = 0; Index < ParserItems; Index++) {\r
559 if ((Offset + Parser[Index].Length) > Length) {\r
5bd326c5
KK
560 // For fields outside the buffer length provided, reset any pointers\r
561 // which were supposed to be updated by this function call\r
562 if (Parser[Index].ItemPtr != NULL) {\r
563 *Parser[Index].ItemPtr = NULL;\r
564 }\r
565\r
ee4dc24f 566 // We don't parse past the end of the max length specified\r
5bd326c5 567 continue;\r
ee4dc24f
RN
568 }\r
569\r
f73843d5 570 if (GetConsistencyChecking () &&\r
47d20b54
MK
571 (Offset != Parser[Index].Offset))\r
572 {\r
ee4dc24f
RN
573 IncrementErrorCount ();\r
574 Print (\r
575 L"\nERROR: %a: Offset Mismatch for %s\n"\r
47d20b54 576 L"CurrentOffset = %d FieldOffset = %d\n",\r
ee4dc24f
RN
577 AsciiName,\r
578 Parser[Index].NameStr,\r
579 Offset,\r
580 Parser[Index].Offset\r
581 );\r
582 }\r
583\r
584 if (Trace) {\r
585 // if there is a Formatter function let the function handle\r
586 // the printing else if a Format is specified in the table use\r
587 // the Format for printing\r
588 PrintFieldName (2, Parser[Index].NameStr);\r
589 if (Parser[Index].PrintFormatter != NULL) {\r
590 Parser[Index].PrintFormatter (Parser[Index].Format, Ptr);\r
591 } else if (Parser[Index].Format != NULL) {\r
592 switch (Parser[Index].Length) {\r
593 case 1:\r
594 DumpUint8 (Parser[Index].Format, Ptr);\r
595 break;\r
596 case 2:\r
597 DumpUint16 (Parser[Index].Format, Ptr);\r
598 break;\r
599 case 4:\r
600 DumpUint32 (Parser[Index].Format, Ptr);\r
601 break;\r
602 case 8:\r
603 DumpUint64 (Parser[Index].Format, Ptr);\r
604 break;\r
605 default:\r
606 Print (\r
607 L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",\r
608 AsciiName,\r
609 Parser[Index].Length\r
610 );\r
611 } // switch\r
856cf5ab 612 }\r
47d20b54 613\r
856cf5ab
SM
614 // Validating only makes sense if we are tracing\r
615 // the parsed table entries, to report by table name.\r
616 if (GetConsistencyChecking () &&\r
47d20b54
MK
617 (Parser[Index].FieldValidator != NULL))\r
618 {\r
856cf5ab 619 Parser[Index].FieldValidator (Ptr, Parser[Index].Context);\r
ee4dc24f 620 }\r
47d20b54 621\r
ee4dc24f
RN
622 Print (L"\n");\r
623 } // if (Trace)\r
624\r
625 if (Parser[Index].ItemPtr != NULL) {\r
47d20b54 626 *Parser[Index].ItemPtr = (VOID *)Ptr;\r
ee4dc24f
RN
627 }\r
628\r
47d20b54 629 Ptr += Parser[Index].Length;\r
ee4dc24f
RN
630 Offset += Parser[Index].Length;\r
631 } // for\r
632\r
633 // Decrement the Indent\r
634 gIndent -= Indent;\r
635 return Offset;\r
636}\r
637\r
a6eaba4d
DB
638/**\r
639 An array describing the ACPI Generic Address Structure.\r
ee4dc24f
RN
640 The GasParser array is used by the ParseAcpi function to parse and/or trace\r
641 the GAS structure.\r
a6eaba4d 642**/\r
47d20b54
MK
643STATIC CONST ACPI_PARSER GasParser[] = {\r
644 { L"Address Space ID", 1, 0, L"0x%x", NULL, NULL, NULL, NULL },\r
645 { L"Register Bit Width", 1, 1, L"0x%x", NULL, NULL, NULL, NULL },\r
646 { L"Register Bit Offset", 1, 2, L"0x%x", NULL, NULL, NULL, NULL },\r
647 { L"Access Size", 1, 3, L"0x%x", NULL, NULL, NULL, NULL },\r
648 { L"Address", 8, 4, L"0x%lx", NULL, NULL, NULL, NULL }\r
ee4dc24f
RN
649};\r
650\r
a6eaba4d
DB
651/**\r
652 This function indents and traces the GAS structure as described by the GasParser.\r
ee4dc24f
RN
653\r
654 @param [in] Ptr Pointer to the start of the buffer.\r
655 @param [in] Indent Number of spaces to indent the output.\r
58cc0ffe
KK
656 @param [in] Length Length of the GAS structure buffer.\r
657\r
658 @retval Number of bytes parsed.\r
a6eaba4d 659**/\r
58cc0ffe 660UINT32\r
ee4dc24f
RN
661EFIAPI\r
662DumpGasStruct (\r
47d20b54
MK
663 IN UINT8 *Ptr,\r
664 IN UINT32 Indent,\r
665 IN UINT32 Length\r
ee4dc24f
RN
666 )\r
667{\r
668 Print (L"\n");\r
58cc0ffe
KK
669 return ParseAcpi (\r
670 TRUE,\r
671 Indent,\r
672 NULL,\r
673 Ptr,\r
674 Length,\r
675 PARSER_PARAMS (GasParser)\r
676 );\r
ee4dc24f
RN
677}\r
678\r
a6eaba4d
DB
679/**\r
680 This function traces the GAS structure as described by the GasParser.\r
ee4dc24f
RN
681\r
682 @param [in] Format Optional format string for tracing the data.\r
683 @param [in] Ptr Pointer to the start of the buffer.\r
a6eaba4d 684**/\r
ee4dc24f
RN
685VOID\r
686EFIAPI\r
687DumpGas (\r
47d20b54
MK
688 IN CONST CHAR16 *Format OPTIONAL,\r
689 IN UINT8 *Ptr\r
ee4dc24f
RN
690 )\r
691{\r
0b9026a8 692 DumpGasStruct (Ptr, 2, sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE));\r
ee4dc24f
RN
693}\r
694\r
a6eaba4d
DB
695/**\r
696 This function traces the ACPI header as described by the AcpiHeaderParser.\r
ee4dc24f
RN
697\r
698 @param [in] Ptr Pointer to the start of the buffer.\r
699\r
700 @retval Number of bytes parsed.\r
a6eaba4d 701**/\r
ee4dc24f
RN
702UINT32\r
703EFIAPI\r
704DumpAcpiHeader (\r
47d20b54 705 IN UINT8 *Ptr\r
ee4dc24f
RN
706 )\r
707{\r
ee4dc24f
RN
708 return ParseAcpi (\r
709 TRUE,\r
710 0,\r
711 "ACPI Table Header",\r
712 Ptr,\r
0b9026a8 713 sizeof (EFI_ACPI_DESCRIPTION_HEADER),\r
ee4dc24f
RN
714 PARSER_PARAMS (AcpiHeaderParser)\r
715 );\r
716}\r
717\r
a6eaba4d
DB
718/**\r
719 This function parses the ACPI header as described by the AcpiHeaderParser.\r
ee4dc24f
RN
720\r
721 This function optionally returns the signature, length and revision of the\r
722 ACPI table.\r
723\r
724 @param [in] Ptr Pointer to the start of the buffer.\r
725 @param [out] Signature Gets location of the ACPI table signature.\r
726 @param [out] Length Gets location of the length of the ACPI table.\r
727 @param [out] Revision Gets location of the revision of the ACPI table.\r
728\r
729 @retval Number of bytes parsed.\r
a6eaba4d 730**/\r
ee4dc24f
RN
731UINT32\r
732EFIAPI\r
733ParseAcpiHeader (\r
47d20b54
MK
734 IN UINT8 *Ptr,\r
735 OUT CONST UINT32 **Signature,\r
736 OUT CONST UINT32 **Length,\r
737 OUT CONST UINT8 **Revision\r
ee4dc24f
RN
738 )\r
739{\r
47d20b54 740 UINT32 BytesParsed;\r
ee4dc24f
RN
741\r
742 BytesParsed = ParseAcpi (\r
743 FALSE,\r
744 0,\r
745 NULL,\r
746 Ptr,\r
0b9026a8 747 sizeof (EFI_ACPI_DESCRIPTION_HEADER),\r
ee4dc24f
RN
748 PARSER_PARAMS (AcpiHeaderParser)\r
749 );\r
750\r
751 *Signature = AcpiHdrInfo.Signature;\r
47d20b54
MK
752 *Length = AcpiHdrInfo.Length;\r
753 *Revision = AcpiHdrInfo.Revision;\r
ee4dc24f
RN
754\r
755 return BytesParsed;\r
756}\r
691b1786
ALA
757\r
758/**\r
759 This function is used to parse an ACPI table bitfield buffer.\r
760\r
761 The ACPI table buffer is parsed using the ACPI table parser information\r
762 specified by a pointer to an array of ACPI_PARSER elements. This parser\r
763 function iterates through each item on the ACPI_PARSER array and logs the ACPI table bitfields.\r
764\r
765 This function can optionally be used to parse ACPI tables and fetch specific\r
766 field values. The ItemPtr member of the ACPI_PARSER structure (where used)\r
767 is updated by this parser function to point to the selected field data\r
768 (e.g. useful for variable length nested fields).\r
769\r
770 ItemPtr member of ACPI_PARSER is not supported with this function.\r
771\r
772 @param [in] Trace Trace the ACPI fields TRUE else only parse the\r
773 table.\r
774 @param [in] Indent Number of spaces to indent the output.\r
775 @param [in] AsciiName Optional pointer to an ASCII string that describes\r
776 the table being parsed.\r
777 @param [in] Ptr Pointer to the start of the buffer.\r
778 @param [in] Length Length in bytes of the buffer pointed by Ptr.\r
779 @param [in] Parser Pointer to an array of ACPI_PARSER structure that\r
780 describes the table being parsed.\r
781 @param [in] ParserItems Number of items in the ACPI_PARSER array.\r
782\r
783 @retval Number of bits parsed.\r
784**/\r
785UINT32\r
786EFIAPI\r
787ParseAcpiBitFields (\r
788 IN BOOLEAN Trace,\r
789 IN UINT32 Indent,\r
790 IN CONST CHAR8 *AsciiName OPTIONAL,\r
791 IN UINT8 *Ptr,\r
792 IN UINT32 Length,\r
793 IN CONST ACPI_PARSER *Parser,\r
794 IN UINT32 ParserItems\r
795 )\r
796{\r
797 UINT32 Index;\r
798 UINT32 Offset;\r
799 BOOLEAN HighLight;\r
800 UINTN OriginalAttribute;\r
801\r
802 UINT64 Data;\r
803 UINT64 BitsData;\r
804\r
805 if ((Length == 0) || (Length > 8)) {\r
806 IncrementErrorCount ();\r
807 Print (\r
808 L"\nERROR: Bitfield Length(%d) is zero or exceeding the 64 bit limit.\n",\r
809 Length\r
810 );\r
811 return 0;\r
812 }\r
813\r
814 //\r
815 // set local variables to suppress incorrect compiler/analyzer warnings\r
816 //\r
817 OriginalAttribute = 0;\r
818 Offset = 0;\r
819\r
820 // Increment the Indent\r
821 gIndent += Indent;\r
822\r
823 CopyMem ((VOID *)&BitsData, (VOID *)Ptr, Length);\r
824 if (Trace && (AsciiName != NULL)) {\r
825 HighLight = GetColourHighlighting ();\r
826\r
827 if (HighLight) {\r
828 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
829 gST->ConOut->SetAttribute (\r
830 gST->ConOut,\r
831 EFI_TEXT_ATTR (\r
832 EFI_YELLOW,\r
833 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
834 )\r
835 );\r
836 }\r
837\r
838 Print (\r
839 L"%*a%-*a :\n",\r
840 gIndent,\r
841 "",\r
842 (OUTPUT_FIELD_COLUMN_WIDTH - gIndent),\r
843 AsciiName\r
844 );\r
845 if (HighLight) {\r
846 gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute);\r
847 }\r
848 }\r
849\r
850 for (Index = 0; Index < ParserItems; Index++) {\r
851 if ((Offset + Parser[Index].Length) > (Length * 8)) {\r
852 // For fields outside the buffer length provided, reset any pointers\r
853 // which were supposed to be updated by this function call\r
854 if (Parser[Index].ItemPtr != NULL) {\r
855 *Parser[Index].ItemPtr = NULL;\r
856 }\r
857\r
858 // We don't parse past the end of the max length specified\r
859 continue;\r
860 }\r
861\r
862 if (Parser[Index].Length == 0) {\r
863 IncrementErrorCount ();\r
864 // don't parse the bitfield whose length is zero\r
865 Print (\r
866 L"\nERROR: %a: Cannot parse this field, Field Length = %d\n",\r
867 Parser[Index].Length\r
868 );\r
869 continue;\r
870 }\r
871\r
872 if (GetConsistencyChecking () &&\r
873 (Offset != Parser[Index].Offset))\r
874 {\r
875 IncrementErrorCount ();\r
876 Print (\r
877 L"\nERROR: %a: Offset Mismatch for %s\n"\r
878 L"CurrentOffset = %d FieldOffset = %d\n",\r
879 AsciiName,\r
880 Parser[Index].NameStr,\r
881 Offset,\r
882 Parser[Index].Offset\r
883 );\r
884 }\r
885\r
886 // extract Bitfield data for the current item\r
40004ff9 887 Data = RShiftU64 (BitsData, Parser[Index].Offset) & ~(LShiftU64 (~0ULL, Parser[Index].Length));\r
691b1786
ALA
888\r
889 if (Trace) {\r
890 // if there is a Formatter function let the function handle\r
891 // the printing else if a Format is specified in the table use\r
892 // the Format for printing\r
893 PrintFieldName (2, Parser[Index].NameStr);\r
894 if (Parser[Index].PrintFormatter != NULL) {\r
895 Parser[Index].PrintFormatter (Parser[Index].Format, (UINT8 *)&Data);\r
896 } else if (Parser[Index].Format != NULL) {\r
897 // convert bit length to byte length\r
898 switch ((Parser[Index].Length + 7) >> 3) {\r
899 // print the data depends on byte size\r
900 case 1:\r
901 DumpUint8 (Parser[Index].Format, (UINT8 *)&Data);\r
902 break;\r
903 case 2:\r
904 DumpUint16 (Parser[Index].Format, (UINT8 *)&Data);\r
905 break;\r
906 case 3:\r
907 case 4:\r
908 DumpUint32 (Parser[Index].Format, (UINT8 *)&Data);\r
909 break;\r
910 case 5:\r
911 case 6:\r
912 case 7:\r
913 case 8:\r
914 DumpUint64 (Parser[Index].Format, (UINT8 *)&Data);\r
915 break;\r
916 default:\r
917 Print (\r
918 L"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",\r
919 AsciiName,\r
920 Parser[Index].Length\r
921 );\r
922 } // switch\r
923 }\r
924\r
925 // Validating only makes sense if we are tracing\r
926 // the parsed table entries, to report by table name.\r
927 if (GetConsistencyChecking () &&\r
928 (Parser[Index].FieldValidator != NULL))\r
929 {\r
930 Parser[Index].FieldValidator ((UINT8 *)&Data, Parser[Index].Context);\r
931 }\r
932\r
933 Print (L"\n");\r
934 } // if (Trace)\r
935\r
936 Offset += Parser[Index].Length;\r
937 } // for\r
938\r
939 // Decrement the Indent\r
940 gIndent -= Indent;\r
941 return Offset;\r
942}\r