]> git.proxmox.com Git - mirror_edk2.git/blame_incremental - ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c
UefiCpuPkg: Move AsmRelocateApLoopStart from Mpfuncs.nasm to AmdSev.nasm
[mirror_edk2.git] / ShellPkg / Library / UefiShellAcpiViewCommandLib / AcpiParser.c
... / ...
CommitLineData
1/** @file\r
2 ACPI parser\r
3\r
4 Copyright (c) 2016 - 2021, Arm Limited. All rights reserved.\r
5 Copyright (c) 2022, AMD Incorporated. All rights reserved.\r
6 SPDX-License-Identifier: BSD-2-Clause-Patent\r
7**/\r
8\r
9#include <Uefi.h>\r
10#include <Library/UefiLib.h>\r
11#include <Library/UefiBootServicesTableLib.h>\r
12#include <Library/BaseMemoryLib.h>\r
13#include "AcpiParser.h"\r
14#include "AcpiView.h"\r
15#include "AcpiViewConfig.h"\r
16\r
17STATIC UINT32 gIndent;\r
18STATIC UINT32 mTableErrorCount;\r
19STATIC UINT32 mTableWarningCount;\r
20\r
21STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;\r
22\r
23/**\r
24 An ACPI_PARSER array describing the ACPI header.\r
25**/\r
26STATIC CONST ACPI_PARSER AcpiHeaderParser[] = {\r
27 PARSE_ACPI_HEADER (&AcpiHdrInfo)\r
28};\r
29\r
30/**\r
31 This function resets the ACPI table error counter to Zero.\r
32**/\r
33VOID\r
34ResetErrorCount (\r
35 VOID\r
36 )\r
37{\r
38 mTableErrorCount = 0;\r
39}\r
40\r
41/**\r
42 This function returns the ACPI table error count.\r
43\r
44 @retval Returns the count of errors detected in the ACPI tables.\r
45**/\r
46UINT32\r
47GetErrorCount (\r
48 VOID\r
49 )\r
50{\r
51 return mTableErrorCount;\r
52}\r
53\r
54/**\r
55 This function resets the ACPI table warning counter to Zero.\r
56**/\r
57VOID\r
58ResetWarningCount (\r
59 VOID\r
60 )\r
61{\r
62 mTableWarningCount = 0;\r
63}\r
64\r
65/**\r
66 This function returns the ACPI table warning count.\r
67\r
68 @retval Returns the count of warning detected in the ACPI tables.\r
69**/\r
70UINT32\r
71GetWarningCount (\r
72 VOID\r
73 )\r
74{\r
75 return mTableWarningCount;\r
76}\r
77\r
78/**\r
79 This function increments the ACPI table error counter.\r
80**/\r
81VOID\r
82EFIAPI\r
83IncrementErrorCount (\r
84 VOID\r
85 )\r
86{\r
87 mTableErrorCount++;\r
88}\r
89\r
90/**\r
91 This function increments the ACPI table warning counter.\r
92**/\r
93VOID\r
94EFIAPI\r
95IncrementWarningCount (\r
96 VOID\r
97 )\r
98{\r
99 mTableWarningCount++;\r
100}\r
101\r
102/**\r
103 This function verifies the ACPI table checksum.\r
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
114**/\r
115BOOLEAN\r
116EFIAPI\r
117VerifyChecksum (\r
118 IN BOOLEAN Log,\r
119 IN UINT8 *Ptr,\r
120 IN UINT32 Length\r
121 )\r
122{\r
123 UINTN ByteCount;\r
124 UINT8 Checksum;\r
125 UINTN OriginalAttribute;\r
126\r
127 //\r
128 // set local variables to suppress incorrect compiler/analyzer warnings\r
129 //\r
130 OriginalAttribute = 0;\r
131 ByteCount = 0;\r
132 Checksum = 0;\r
133\r
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
145 EFI_TEXT_ATTR (\r
146 EFI_GREEN,\r
147 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
148 )\r
149 );\r
150 }\r
151\r
152 Print (L"Table Checksum : OK\n\n");\r
153 } else {\r
154 IncrementErrorCount ();\r
155 if (GetColourHighlighting ()) {\r
156 gST->ConOut->SetAttribute (\r
157 gST->ConOut,\r
158 EFI_TEXT_ATTR (\r
159 EFI_RED,\r
160 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
161 )\r
162 );\r
163 }\r
164\r
165 Print (L"Table Checksum : FAILED (0x%X)\n\n", Checksum);\r
166 }\r
167\r
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
176/**\r
177 This function performs a raw data dump of the ACPI table.\r
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
181**/\r
182VOID\r
183EFIAPI\r
184DumpRaw (\r
185 IN UINT8 *Ptr,\r
186 IN UINT32 Length\r
187 )\r
188{\r
189 UINTN ByteCount;\r
190 UINTN PartLineChars;\r
191 UINTN AsciiBufferIndex;\r
192 CHAR8 AsciiBuffer[17];\r
193\r
194 ByteCount = 0;\r
195 AsciiBufferIndex = 0;\r
196\r
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
228\r
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
237 Print (L" %a\n\n", AsciiBuffer);\r
238}\r
239\r
240/**\r
241 This function traces 1 byte of data as specified in the format string.\r
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
245**/\r
246VOID\r
247EFIAPI\r
248DumpUint8 (\r
249 IN CONST CHAR16 *Format,\r
250 IN UINT8 *Ptr\r
251 )\r
252{\r
253 Print (Format, *Ptr);\r
254}\r
255\r
256/**\r
257 This function traces 2 bytes of data as specified in the format string.\r
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
261**/\r
262VOID\r
263EFIAPI\r
264DumpUint16 (\r
265 IN CONST CHAR16 *Format,\r
266 IN UINT8 *Ptr\r
267 )\r
268{\r
269 Print (Format, *(UINT16 *)Ptr);\r
270}\r
271\r
272/**\r
273 This function traces 4 bytes of data as specified in the format string.\r
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
277**/\r
278VOID\r
279EFIAPI\r
280DumpUint32 (\r
281 IN CONST CHAR16 *Format,\r
282 IN UINT8 *Ptr\r
283 )\r
284{\r
285 Print (Format, *(UINT32 *)Ptr);\r
286}\r
287\r
288/**\r
289 This function traces 8 bytes of data as specified by the format string.\r
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
293**/\r
294VOID\r
295EFIAPI\r
296DumpUint64 (\r
297 IN CONST CHAR16 *Format,\r
298 IN UINT8 *Ptr\r
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
304 UINT64 Val;\r
305\r
306 Val = *(UINT32 *)(Ptr + sizeof (UINT32));\r
307\r
308 Val = LShiftU64 (Val, 32);\r
309 Val |= (UINT64)*(UINT32 *)Ptr;\r
310\r
311 Print (Format, Val);\r
312}\r
313\r
314/**\r
315 This function traces 3 characters which can be optionally\r
316 formated using the format string if specified.\r
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
322**/\r
323VOID\r
324EFIAPI\r
325Dump3Chars (\r
326 IN CONST CHAR16 *Format OPTIONAL,\r
327 IN UINT8 *Ptr\r
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
338/**\r
339 This function traces 4 characters which can be optionally\r
340 formated using the format string if specified.\r
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
346**/\r
347VOID\r
348EFIAPI\r
349Dump4Chars (\r
350 IN CONST CHAR16 *Format OPTIONAL,\r
351 IN UINT8 *Ptr\r
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
363/**\r
364 This function traces 6 characters which can be optionally\r
365 formated using the format string if specified.\r
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
371**/\r
372VOID\r
373EFIAPI\r
374Dump6Chars (\r
375 IN CONST CHAR16 *Format OPTIONAL,\r
376 IN UINT8 *Ptr\r
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
390/**\r
391 This function traces 8 characters which can be optionally\r
392 formated using the format string if specified.\r
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
398**/\r
399VOID\r
400EFIAPI\r
401Dump8Chars (\r
402 IN CONST CHAR16 *Format OPTIONAL,\r
403 IN UINT8 *Ptr\r
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
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
431 IN CONST CHAR16 *Format OPTIONAL,\r
432 IN UINT8 *Ptr\r
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
452/**\r
453 This function indents and prints the ACPI table Field Name.\r
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
463**/\r
464VOID\r
465EFIAPI\r
466PrintFieldName (\r
467 IN UINT32 Indent,\r
468 IN CONST CHAR16 *FieldName\r
469 )\r
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
480/**\r
481 This function is used to parse an ACPI table buffer.\r
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
505**/\r
506UINT32\r
507EFIAPI\r
508ParseAcpi (\r
509 IN BOOLEAN Trace,\r
510 IN UINT32 Indent,\r
511 IN CONST CHAR8 *AsciiName OPTIONAL,\r
512 IN UINT8 *Ptr,\r
513 IN UINT32 Length,\r
514 IN CONST ACPI_PARSER *Parser,\r
515 IN UINT32 ParserItems\r
516 )\r
517{\r
518 UINT32 Index;\r
519 UINT32 Offset;\r
520 BOOLEAN HighLight;\r
521 UINTN OriginalAttribute;\r
522\r
523 //\r
524 // set local variables to suppress incorrect compiler/analyzer warnings\r
525 //\r
526 OriginalAttribute = 0;\r
527 Offset = 0;\r
528\r
529 // Increment the Indent\r
530 gIndent += Indent;\r
531\r
532 if (Trace && (AsciiName != NULL)) {\r
533 HighLight = GetColourHighlighting ();\r
534\r
535 if (HighLight) {\r
536 OriginalAttribute = gST->ConOut->Mode->Attribute;\r
537 gST->ConOut->SetAttribute (\r
538 gST->ConOut,\r
539 EFI_TEXT_ATTR (\r
540 EFI_YELLOW,\r
541 ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)\r
542 )\r
543 );\r
544 }\r
545\r
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
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
566 // We don't parse past the end of the max length specified\r
567 continue;\r
568 }\r
569\r
570 if (GetConsistencyChecking () &&\r
571 (Offset != Parser[Index].Offset))\r
572 {\r
573 IncrementErrorCount ();\r
574 Print (\r
575 L"\nERROR: %a: Offset Mismatch for %s\n"\r
576 L"CurrentOffset = %d FieldOffset = %d\n",\r
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
612 }\r
613\r
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
617 (Parser[Index].FieldValidator != NULL))\r
618 {\r
619 Parser[Index].FieldValidator (Ptr, Parser[Index].Context);\r
620 }\r
621\r
622 Print (L"\n");\r
623 } // if (Trace)\r
624\r
625 if (Parser[Index].ItemPtr != NULL) {\r
626 *Parser[Index].ItemPtr = (VOID *)Ptr;\r
627 }\r
628\r
629 Ptr += Parser[Index].Length;\r
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
638/**\r
639 An array describing the ACPI Generic Address Structure.\r
640 The GasParser array is used by the ParseAcpi function to parse and/or trace\r
641 the GAS structure.\r
642**/\r
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
649};\r
650\r
651/**\r
652 This function indents and traces the GAS structure as described by the GasParser.\r
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
656 @param [in] Length Length of the GAS structure buffer.\r
657\r
658 @retval Number of bytes parsed.\r
659**/\r
660UINT32\r
661EFIAPI\r
662DumpGasStruct (\r
663 IN UINT8 *Ptr,\r
664 IN UINT32 Indent,\r
665 IN UINT32 Length\r
666 )\r
667{\r
668 Print (L"\n");\r
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
677}\r
678\r
679/**\r
680 This function traces the GAS structure as described by the GasParser.\r
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
684**/\r
685VOID\r
686EFIAPI\r
687DumpGas (\r
688 IN CONST CHAR16 *Format OPTIONAL,\r
689 IN UINT8 *Ptr\r
690 )\r
691{\r
692 DumpGasStruct (Ptr, 2, sizeof (EFI_ACPI_6_3_GENERIC_ADDRESS_STRUCTURE));\r
693}\r
694\r
695/**\r
696 This function traces the ACPI header as described by the AcpiHeaderParser.\r
697\r
698 @param [in] Ptr Pointer to the start of the buffer.\r
699\r
700 @retval Number of bytes parsed.\r
701**/\r
702UINT32\r
703EFIAPI\r
704DumpAcpiHeader (\r
705 IN UINT8 *Ptr\r
706 )\r
707{\r
708 return ParseAcpi (\r
709 TRUE,\r
710 0,\r
711 "ACPI Table Header",\r
712 Ptr,\r
713 sizeof (EFI_ACPI_DESCRIPTION_HEADER),\r
714 PARSER_PARAMS (AcpiHeaderParser)\r
715 );\r
716}\r
717\r
718/**\r
719 This function parses the ACPI header as described by the AcpiHeaderParser.\r
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
730**/\r
731UINT32\r
732EFIAPI\r
733ParseAcpiHeader (\r
734 IN UINT8 *Ptr,\r
735 OUT CONST UINT32 **Signature,\r
736 OUT CONST UINT32 **Length,\r
737 OUT CONST UINT8 **Revision\r
738 )\r
739{\r
740 UINT32 BytesParsed;\r
741\r
742 BytesParsed = ParseAcpi (\r
743 FALSE,\r
744 0,\r
745 NULL,\r
746 Ptr,\r
747 sizeof (EFI_ACPI_DESCRIPTION_HEADER),\r
748 PARSER_PARAMS (AcpiHeaderParser)\r
749 );\r
750\r
751 *Signature = AcpiHdrInfo.Signature;\r
752 *Length = AcpiHdrInfo.Length;\r
753 *Revision = AcpiHdrInfo.Revision;\r
754\r
755 return BytesParsed;\r
756}\r
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
887 Data = RShiftU64 (BitsData, Parser[Index].Offset) & ~(LShiftU64 (~0ULL, Parser[Index].Length));\r
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