VirtualBox

source: vbox/trunk/src/VBox/Devices/EFI/FirmwareNew/ShellPkg/Library/UefiShellAcpiViewCommandLib/AcpiParser.c@ 108794

Last change on this file since 108794 was 108794, checked in by vboxsync, 2 weeks ago

Devices/EFI/FirmwareNew: Merge edk2-stable202502 from the vendor branch and make it build for the important platforms, bugref:4643

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

© 2025 Oracle Support Privacy / Do Not Sell My Info Terms of Use Trademark Policy Automated Access Etiquette