4 Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
5 This program and the accompanying materials
6 are licensed and made available under the terms and conditions of the BSD License
7 which accompanies this distribution. The full text of the license may be found at
8 http://opensource.org/licenses/bsd-license.php
10 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
11 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
15 #include <Library/UefiLib.h>
16 #include <Library/UefiBootServicesTableLib.h>
17 #include "AcpiParser.h"
20 STATIC UINT32 gIndent
;
21 STATIC UINT32 mTableErrorCount
;
22 STATIC UINT32 mTableWarningCount
;
24 STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo
;
27 An ACPI_PARSER array describing the ACPI header.
29 STATIC CONST ACPI_PARSER AcpiHeaderParser
[] = {
30 PARSE_ACPI_HEADER (&AcpiHdrInfo
)
34 This function resets the ACPI table error counter to Zero.
45 This function returns the ACPI table error count.
47 @retval Returns the count of errors detected in the ACPI tables.
54 return mTableErrorCount
;
58 This function resets the ACPI table warning counter to Zero.
65 mTableWarningCount
= 0;
69 This function returns the ACPI table warning count.
71 @retval Returns the count of warning detected in the ACPI tables.
78 return mTableWarningCount
;
82 This function increments the ACPI table error counter.
94 This function increments the ACPI table warning counter.
98 IncrementWarningCount (
102 mTableWarningCount
++;
106 This function verifies the ACPI table checksum.
108 This function verifies the checksum for the ACPI table and optionally
111 @param [in] Log If TRUE log the status of the checksum.
112 @param [in] Ptr Pointer to the start of the table buffer.
113 @param [in] Length The length of the buffer.
115 @retval TRUE The checksum is OK.
116 @retval FALSE The checksum failed.
128 UINTN OriginalAttribute
;
133 while (ByteCount
< Length
) {
134 Checksum
+= *(Ptr
++);
139 OriginalAttribute
= gST
->ConOut
->Mode
->Attribute
;
141 if (GetColourHighlighting ()) {
142 gST
->ConOut
->SetAttribute (
144 EFI_TEXT_ATTR (EFI_GREEN
,
145 ((OriginalAttribute
&(BIT4
|BIT5
|BIT6
))>>4))
148 Print (L
"\n\nTable Checksum : OK\n\n");
150 IncrementErrorCount ();
151 if (GetColourHighlighting ()) {
152 gST
->ConOut
->SetAttribute (
154 EFI_TEXT_ATTR (EFI_RED
,
155 ((OriginalAttribute
&(BIT4
|BIT5
|BIT6
))>>4))
158 Print (L
"\n\nTable Checksum : FAILED (0x%X)\n\n", Checksum
);
160 if (GetColourHighlighting ()) {
161 gST
->ConOut
->SetAttribute (gST
->ConOut
, OriginalAttribute
);
165 return (Checksum
== 0);
169 This function performs a raw data dump of the ACPI table.
171 @param [in] Ptr Pointer to the start of the table buffer.
172 @param [in] Length The length of the buffer.
183 UINTN AsciiBufferIndex
;
184 CHAR8 AsciiBuffer
[17];
187 AsciiBufferIndex
= 0;
189 Print (L
"Address : 0x%p\n", Ptr
);
190 Print (L
"Length : %d\n", Length
);
192 while (ByteCount
< Length
) {
193 if ((ByteCount
& 0x0F) == 0) {
194 AsciiBuffer
[AsciiBufferIndex
] = '\0';
195 Print (L
" %a\n%08X : ", AsciiBuffer
, ByteCount
);
196 AsciiBufferIndex
= 0;
197 } else if ((ByteCount
& 0x07) == 0) {
201 if ((*Ptr
>= ' ') && (*Ptr
< 0x7F)) {
202 AsciiBuffer
[AsciiBufferIndex
++] = *Ptr
;
204 AsciiBuffer
[AsciiBufferIndex
++] = '.';
207 Print (L
"%02X ", *Ptr
++);
212 // Justify the final line using spaces before printing
214 PartLineChars
= (Length
& 0x0F);
215 if (PartLineChars
!= 0) {
216 PartLineChars
= 48 - (PartLineChars
* 3);
217 if ((Length
& 0x0F) <= 8) {
220 while (PartLineChars
> 0) {
226 // Print ASCII data for the final line.
227 AsciiBuffer
[AsciiBufferIndex
] = '\0';
228 Print (L
" %a", AsciiBuffer
);
232 This function traces 1 byte of data as specified in the format string.
234 @param [in] Format The format string for tracing the data.
235 @param [in] Ptr Pointer to the start of the buffer.
240 IN CONST CHAR16
* Format
,
244 Print (Format
, *Ptr
);
248 This function traces 2 bytes of data as specified in the format string.
250 @param [in] Format The format string for tracing the data.
251 @param [in] Ptr Pointer to the start of the buffer.
256 IN CONST CHAR16
* Format
,
260 Print (Format
, *(UINT16
*)Ptr
);
264 This function traces 4 bytes of data as specified in the format string.
266 @param [in] Format The format string for tracing the data.
267 @param [in] Ptr Pointer to the start of the buffer.
272 IN CONST CHAR16
* Format
,
276 Print (Format
, *(UINT32
*)Ptr
);
280 This function traces 8 bytes of data as specified by the format string.
282 @param [in] Format The format string for tracing the data.
283 @param [in] Ptr Pointer to the start of the buffer.
288 IN CONST CHAR16
* Format
,
292 // Some fields are not aligned and this causes alignment faults
293 // on ARM platforms if the compiler generates LDRD instructions.
294 // Perform word access so that LDRD instructions are not generated.
297 Val
= *(UINT32
*)(Ptr
+ sizeof (UINT32
));
300 Val
|= (UINT64
)*(UINT32
*)Ptr
;
306 This function traces 3 characters which can be optionally
307 formated using the format string if specified.
309 If no format string is specified the Format must be NULL.
311 @param [in] Format Optional format string for tracing the data.
312 @param [in] Ptr Pointer to the start of the buffer.
317 IN CONST CHAR16
* Format OPTIONAL
,
322 (Format
!= NULL
) ? Format
: L
"%c%c%c",
330 This function traces 4 characters which can be optionally
331 formated using the format string if specified.
333 If no format string is specified the Format must be NULL.
335 @param [in] Format Optional format string for tracing the data.
336 @param [in] Ptr Pointer to the start of the buffer.
341 IN CONST CHAR16
* Format OPTIONAL
,
346 (Format
!= NULL
) ? Format
: L
"%c%c%c%c",
355 This function traces 6 characters which can be optionally
356 formated using the format string if specified.
358 If no format string is specified the Format must be NULL.
360 @param [in] Format Optional format string for tracing the data.
361 @param [in] Ptr Pointer to the start of the buffer.
366 IN CONST CHAR16
* Format OPTIONAL
,
371 (Format
!= NULL
) ? Format
: L
"%c%c%c%c%c%c",
382 This function traces 8 characters which can be optionally
383 formated using the format string if specified.
385 If no format string is specified the Format must be NULL.
387 @param [in] Format Optional format string for tracing the data.
388 @param [in] Ptr Pointer to the start of the buffer.
393 IN CONST CHAR16
* Format OPTIONAL
,
398 (Format
!= NULL
) ? Format
: L
"%c%c%c%c%c%c%c%c",
411 This function indents and prints the ACPI table Field Name.
413 @param [in] Indent Number of spaces to add to the global table indent.
414 The global table indent is 0 by default; however
415 this value is updated on entry to the ParseAcpi()
416 by adding the indent value provided to ParseAcpi()
417 and restored back on exit.
418 Therefore the total indent in the output is
419 dependent on from where this function is called.
420 @param [in] FieldName Pointer to the Field Name.
426 IN CONST CHAR16
* FieldName
433 (OUTPUT_FIELD_COLUMN_WIDTH
- gIndent
- Indent
),
439 This function is used to parse an ACPI table buffer.
441 The ACPI table buffer is parsed using the ACPI table parser information
442 specified by a pointer to an array of ACPI_PARSER elements. This parser
443 function iterates through each item on the ACPI_PARSER array and logs the
446 This function can optionally be used to parse ACPI tables and fetch specific
447 field values. The ItemPtr member of the ACPI_PARSER structure (where used)
448 is updated by this parser function to point to the selected field data
449 (e.g. useful for variable length nested fields).
451 @param [in] Trace Trace the ACPI fields TRUE else only parse the
453 @param [in] Indent Number of spaces to indent the output.
454 @param [in] AsciiName Optional pointer to an ASCII string that describes
455 the table being parsed.
456 @param [in] Ptr Pointer to the start of the buffer.
457 @param [in] Length Length of the buffer pointed by Ptr.
458 @param [in] Parser Pointer to an array of ACPI_PARSER structure that
459 describes the table being parsed.
460 @param [in] ParserItems Number of items in the ACPI_PARSER array.
462 @retval Number of bytes parsed.
469 IN CONST CHAR8
* AsciiName OPTIONAL
,
472 IN CONST ACPI_PARSER
* Parser
,
473 IN UINT32 ParserItems
479 UINTN OriginalAttribute
;
483 // Increment the Indent
486 if (Trace
&& (AsciiName
!= NULL
)){
487 HighLight
= GetColourHighlighting ();
490 OriginalAttribute
= gST
->ConOut
->Mode
->Attribute
;
491 gST
->ConOut
->SetAttribute (
493 EFI_TEXT_ATTR(EFI_YELLOW
,
494 ((OriginalAttribute
&(BIT4
|BIT5
|BIT6
))>>4))
501 (OUTPUT_FIELD_COLUMN_WIDTH
- gIndent
),
505 gST
->ConOut
->SetAttribute (gST
->ConOut
, OriginalAttribute
);
509 for (Index
= 0; Index
< ParserItems
; Index
++) {
510 if ((Offset
+ Parser
[Index
].Length
) > Length
) {
511 // We don't parse past the end of the max length specified
515 if (Offset
!= Parser
[Index
].Offset
) {
516 IncrementErrorCount ();
518 L
"\nERROR: %a: Offset Mismatch for %s\n"
519 L
"CurrentOffset = %d FieldOffset = %d\n",
521 Parser
[Index
].NameStr
,
528 // if there is a Formatter function let the function handle
529 // the printing else if a Format is specified in the table use
530 // the Format for printing
531 PrintFieldName (2, Parser
[Index
].NameStr
);
532 if (Parser
[Index
].PrintFormatter
!= NULL
) {
533 Parser
[Index
].PrintFormatter (Parser
[Index
].Format
, Ptr
);
534 } else if (Parser
[Index
].Format
!= NULL
) {
535 switch (Parser
[Index
].Length
) {
537 DumpUint8 (Parser
[Index
].Format
, Ptr
);
540 DumpUint16 (Parser
[Index
].Format
, Ptr
);
543 DumpUint32 (Parser
[Index
].Format
, Ptr
);
546 DumpUint64 (Parser
[Index
].Format
, Ptr
);
550 L
"\nERROR: %a: CANNOT PARSE THIS FIELD, Field Length = %d\n",
556 // Validating only makes sense if we are tracing
557 // the parsed table entries, to report by table name.
558 if (Parser
[Index
].FieldValidator
!= NULL
) {
559 Parser
[Index
].FieldValidator (Ptr
, Parser
[Index
].Context
);
565 if (Parser
[Index
].ItemPtr
!= NULL
) {
566 *Parser
[Index
].ItemPtr
= (VOID
*)Ptr
;
569 Ptr
+= Parser
[Index
].Length
;
570 Offset
+= Parser
[Index
].Length
;
573 // Decrement the Indent
579 An array describing the ACPI Generic Address Structure.
580 The GasParser array is used by the ParseAcpi function to parse and/or trace
583 STATIC CONST ACPI_PARSER GasParser
[] = {
584 {L
"Address Space ID", 1, 0, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
585 {L
"Register Bit Width", 1, 1, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
586 {L
"Register Bit Offset", 1, 2, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
587 {L
"Address Size", 1, 3, L
"0x%x", NULL
, NULL
, NULL
, NULL
},
588 {L
"Address", 8, 4, L
"0x%lx", NULL
, NULL
, NULL
, NULL
}
592 This function indents and traces the GAS structure as described by the GasParser.
594 @param [in] Ptr Pointer to the start of the buffer.
595 @param [in] Indent Number of spaces to indent the output.
611 PARSER_PARAMS (GasParser
)
616 This function traces the GAS structure as described by the GasParser.
618 @param [in] Format Optional format string for tracing the data.
619 @param [in] Ptr Pointer to the start of the buffer.
624 IN CONST CHAR16
* Format OPTIONAL
,
628 DumpGasStruct (Ptr
, 2);
632 This function traces the ACPI header as described by the AcpiHeaderParser.
634 @param [in] Ptr Pointer to the start of the buffer.
636 @retval Number of bytes parsed.
649 ACPI_DESCRIPTION_HEADER_LENGTH
,
650 PARSER_PARAMS (AcpiHeaderParser
)
655 This function parses the ACPI header as described by the AcpiHeaderParser.
657 This function optionally returns the signature, length and revision of the
660 @param [in] Ptr Pointer to the start of the buffer.
661 @param [out] Signature Gets location of the ACPI table signature.
662 @param [out] Length Gets location of the length of the ACPI table.
663 @param [out] Revision Gets location of the revision of the ACPI table.
665 @retval Number of bytes parsed.
671 OUT CONST UINT32
** Signature
,
672 OUT CONST UINT32
** Length
,
673 OUT CONST UINT8
** Revision
678 BytesParsed
= ParseAcpi (
683 ACPI_DESCRIPTION_HEADER_LENGTH
,
684 PARSER_PARAMS (AcpiHeaderParser
)
687 *Signature
= AcpiHdrInfo
.Signature
;
688 *Length
= AcpiHdrInfo
.Length
;
689 *Revision
= AcpiHdrInfo
.Revision
;