REF: https://bugzilla.tianocore.org/show_bug.cgi?id=3737 Apply uncrustify changes to .c/.h files in the ShellPkg package Cc: Andrew Fish <afish@apple.com> Cc: Leif Lindholm <leif@nuviainc.com> Cc: Michael D Kinney <michael.d.kinney@intel.com> Signed-off-by: Michael Kubacki <michael.kubacki@microsoft.com> Reviewed-by: Ray Ni <ray.ni@intel.com>
		
			
				
	
	
		
			761 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			761 lines
		
	
	
		
			21 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   AEST table parser
 | |
| 
 | |
|   Copyright (c) 2020, Arm Limited.
 | |
|   SPDX-License-Identifier: BSD-2-Clause-Patent
 | |
| 
 | |
|   @par Reference(s):
 | |
|     - ACPI for the Armv8 RAS Extensions 1.1 Platform Design Document,
 | |
|       dated 28 September 2020.
 | |
|       (https://developer.arm.com/documentation/den0085/0101/)
 | |
| **/
 | |
| 
 | |
| #include <Library/PrintLib.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include <IndustryStandard/ArmErrorSourceTable.h>
 | |
| #include "AcpiParser.h"
 | |
| #include "AcpiView.h"
 | |
| #include "AcpiViewConfig.h"
 | |
| 
 | |
| // Local variables
 | |
| STATIC ACPI_DESCRIPTION_HEADER_INFO  AcpiHdrInfo;
 | |
| STATIC UINT8                         *AestNodeType;
 | |
| STATIC UINT16                        *AestNodeLength;
 | |
| STATIC UINT32                        *NodeDataOffset;
 | |
| STATIC UINT32                        *NodeInterfaceOffset;
 | |
| STATIC UINT32                        *NodeInterruptArrayOffset;
 | |
| STATIC UINT32                        *NodeInterruptCount;
 | |
| STATIC UINT32                        *ProcessorId;
 | |
| STATIC UINT8                         *ProcessorFlags;
 | |
| STATIC UINT8                         *ProcessorResourceType;
 | |
| 
 | |
| /**
 | |
|   Validate Processor Flags.
 | |
| 
 | |
|   @param [in] Ptr       Pointer to the start of the field data.
 | |
|   @param [in] Context   Pointer to context specific information e.g. this
 | |
|                         could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateProcessorFlags (
 | |
|   IN UINT8  *Ptr,
 | |
|   IN VOID   *Context
 | |
|   )
 | |
| {
 | |
|   // If the global or shared node flag is set then the ACPI Processor ID
 | |
|   // field must be set to 0 and ignored.
 | |
|   if (((*Ptr & 0x3) != 0) && (*ProcessorId != 0)) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"\nERROR: 'ACPI Processor ID' field must be set to 0 for global"
 | |
|       L" or shared nodes."
 | |
|       );
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate GIC Interface Type.
 | |
| 
 | |
|   @param [in] Ptr       Pointer to the start of the field data.
 | |
|   @param [in] Context   Pointer to context specific information e.g. this
 | |
|                         could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateGicInterfaceType (
 | |
|   IN UINT8  *Ptr,
 | |
|   IN VOID   *Context
 | |
|   )
 | |
| {
 | |
|   UINT32  GicInterfaceType;
 | |
| 
 | |
|   GicInterfaceType = *(UINT32 *)Ptr;
 | |
|   if (GicInterfaceType > 3) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nError: Invalid GIC Interface type %d", GicInterfaceType);
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate Interface Type.
 | |
| 
 | |
|   @param [in] Ptr       Pointer to the start of the field data.
 | |
|   @param [in] Context   Pointer to context specific information e.g. this
 | |
|                         could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateInterfaceType (
 | |
|   IN UINT8  *Ptr,
 | |
|   IN VOID   *Context
 | |
|   )
 | |
| {
 | |
|   if (*Ptr > 1) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nError: Interface type should be 0 or 1");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate Interrupt Type.
 | |
| 
 | |
|   @param [in] Ptr       Pointer to the start of the field data.
 | |
|   @param [in] Context   Pointer to context specific information e.g. this
 | |
|                         could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateInterruptType (
 | |
|   IN UINT8  *Ptr,
 | |
|   IN VOID   *Context
 | |
|   )
 | |
| {
 | |
|   if (*Ptr > 1) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nError: Interrupt type should be 0 or 1");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Validate interrupt flags.
 | |
| 
 | |
|   @param [in] Ptr       Pointer to the start of the field data.
 | |
|   @param [in] Context   Pointer to context specific information e.g. this
 | |
|                         could be a pointer to the ACPI table header.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| EFIAPI
 | |
| ValidateInterruptFlags (
 | |
|   IN UINT8  *Ptr,
 | |
|   IN VOID   *Context
 | |
|   )
 | |
| {
 | |
|   if ((*Ptr & 0xfe) != 0) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (L"\nError: Reserved Flag bits not set to 0");
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Dumps 16 bytes of data.
 | |
| 
 | |
|   @param [in] Format  Optional format string for tracing the data.
 | |
|   @param [in] Ptr     Pointer to the start of the buffer.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| DumpVendorSpecificData (
 | |
|   IN CONST CHAR16  *Format OPTIONAL,
 | |
|   IN UINT8         *Ptr
 | |
|   )
 | |
| {
 | |
|   Print (
 | |
|     L"%02X %02X %02X %02X %02X %02X %02X %02X\n",
 | |
|     Ptr[0],
 | |
|     Ptr[1],
 | |
|     Ptr[2],
 | |
|     Ptr[3],
 | |
|     Ptr[4],
 | |
|     Ptr[5],
 | |
|     Ptr[6],
 | |
|     Ptr[7]
 | |
|     );
 | |
| 
 | |
|   Print (
 | |
|     L"%*a   %02X %02X %02X %02X %02X %02X %02X %02X",
 | |
|     OUTPUT_FIELD_COLUMN_WIDTH,
 | |
|     "",
 | |
|     Ptr[8],
 | |
|     Ptr[9],
 | |
|     Ptr[10],
 | |
|     Ptr[11],
 | |
|     Ptr[12],
 | |
|     Ptr[13],
 | |
|     Ptr[14],
 | |
|     Ptr[15]
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the ACPI AEST Table.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestParser[] = {
 | |
|   PARSE_ACPI_HEADER (&AcpiHdrInfo)
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the AEST Node Header.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestNodeHeaderParser[] = {
 | |
|   { L"Type",                           1, 0,  L"%d",    NULL, (VOID **)&AestNodeType,   NULL, NULL },
 | |
|   { L"Length",                         2, 1,  L"%d",    NULL, (VOID **)&AestNodeLength, NULL, NULL },
 | |
|   { L"Reserved",                       1, 3,  L"0x%x",  NULL, NULL,                     NULL, NULL },
 | |
|   { L"Node Data Offset",               4, 4,  L"%d",    NULL, (VOID **)&NodeDataOffset, NULL, NULL },
 | |
|   { L"Node Interface Offset",          4, 8,  L"%d",    NULL,
 | |
|     (VOID **)&NodeInterfaceOffset, NULL, NULL },
 | |
|   { L"Node Interrupt Array Offset",    4, 12, L"%d",    NULL,
 | |
|     (VOID **)&NodeInterruptArrayOffset, NULL, NULL },
 | |
|   { L"Node Interrupt Count",           4, 16, L"%d",    NULL,
 | |
|     (VOID **)&NodeInterruptCount, NULL, NULL },
 | |
|   { L"Timestamp Rate",                 8, 20, L"%ld",   NULL, NULL,                     NULL, NULL },
 | |
|   { L"Reserved1",                      8, 28, L"0x%lx", NULL, NULL,                     NULL, NULL },
 | |
|   { L"Error Injection Countdown Rate", 8, 36, L"%ld",   NULL, NULL,                     NULL, NULL }
 | |
|   // Node specific data...
 | |
|   // Node interface...
 | |
|   // Node interrupt array...
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the Processor error node specific data.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestProcessorStructure[] = {
 | |
|   { L"ACPI Processor ID",                  4, 0, L"0x%x",  NULL, (VOID **)&ProcessorId,           NULL, NULL },
 | |
|   { L"Resource Type",                      1, 4, L"%d",    NULL, (VOID **)&ProcessorResourceType, NULL,
 | |
|     NULL },
 | |
|   { L"Reserved",                           1, 5, L"0x%x",  NULL, NULL,                            NULL, NULL },
 | |
|   { L"Flags",                              1, 6, L"0x%x",  NULL, (VOID **)&ProcessorFlags,
 | |
|     ValidateProcessorFlags, NULL },
 | |
|   { L"Revision",                           1, 7, L"%d",    NULL, NULL,                            NULL, NULL },
 | |
|   { L"Processor Affinity Level Indicator", 8, 8, L"0x%lx", NULL, NULL,                            NULL,
 | |
|     NULL },
 | |
|   // Resource specific data...
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the processor cache resource substructure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestProcessorCacheResourceSubstructure[] = {
 | |
|   { L"Cache reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
 | |
|   { L"Reserved",           4, 4, L"%d",   NULL, NULL, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the processor TLB resource substructure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestProcessorTlbResourceSubstructure[] = {
 | |
|   { L"TLB reference ID", 4, 0, L"0x%x", NULL, NULL, NULL, NULL },
 | |
|   { L"Reserved",         4, 4, L"%d",   NULL, NULL, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the processor generic resource substructure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestProcessorGenericResourceSubstructure[] = {
 | |
|   { L"Vendor-defined data", 4, 0, L"%x", NULL, NULL, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the memory controller structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestMemoryControllerStructure[] = {
 | |
|   { L"Proximity Domain", 4, 0, L"0x%x", NULL, NULL, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the SMMU structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestSmmuStructure[] = {
 | |
|   { L"IORT Node reference ID",    4, 0, L"0x%x", NULL, NULL, NULL, NULL },
 | |
|   { L"SubComponent reference ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the vendor-defined structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestVendorDefinedStructure[] = {
 | |
|   { L"Hardware ID",          4,  0, L"0x%x", NULL,                   NULL, NULL, NULL },
 | |
|   { L"Unique ID",            4,  4, L"0x%x", NULL,                   NULL, NULL, NULL },
 | |
|   { L"Vendor-specific data", 16, 8, NULL,    DumpVendorSpecificData, NULL, NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the GIC structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestGicStructure[] = {
 | |
|   { L"GIC Interface Type",         4, 0, L"0x%x", NULL, NULL, ValidateGicInterfaceType,
 | |
|     NULL },
 | |
|   { L"GIC Interface reference ID", 4, 4, L"0x%x", NULL, NULL, NULL,                    NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the node interface.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestNodeInterface[] = {
 | |
|   { L"Interface Type",            1, 0,  L"%d",       NULL,       NULL, ValidateInterfaceType, NULL },
 | |
|   { L"Reserved",                  3, 1,  L"%x %x %x", Dump3Chars, NULL, NULL,                  NULL },
 | |
|   { L"Flags",                     4, 4,  L"0x%x",     NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Base Address",              8, 8,  L"0x%lx",    NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Start Error Record Index",  4, 16, L"0x%x",     NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Number of Error Records",   4, 20, L"0x%x",     NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Error Records Implemented", 8, 24, L"0x%lx",    NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Error Records Support",     8, 32, L"0x%lx",    NULL,       NULL, NULL,                  NULL },
 | |
|   { L"Addressing mode",           8, 40, L"0x%lx",    NULL,       NULL, NULL,                  NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the node interrupts.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER  AestNodeInterrupt[] = {
 | |
|   { L"Interrupt Type",  1, 0, L"%d",       NULL,       NULL, ValidateInterruptType,  NULL },
 | |
|   { L"Reserved",        2, 1, L"0x%x",     NULL,       NULL, NULL,                   NULL },
 | |
|   { L"Interrupt Flags", 1, 3, L"0x%x",     NULL,       NULL, ValidateInterruptFlags, NULL },
 | |
|   { L"Interrupt GSIV",  4, 4, L"0x%x",     NULL,       NULL, NULL,                   NULL },
 | |
|   { L"ID",              1, 8, L"0x%x",     NULL,       NULL, NULL,                   NULL },
 | |
|   { L"Reserved1",       3, 9, L"%x %x %x", Dump3Chars, NULL, NULL,                   NULL }
 | |
| };
 | |
| 
 | |
| /**
 | |
|   Parses the Processor Error Node structure along with its resource
 | |
|   specific data.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the Processor node.
 | |
|   @param [in] Length  Maximum length of the Processor node.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpProcessorNode (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   UINT32  Offset;
 | |
| 
 | |
|   Offset = ParseAcpi (
 | |
|              TRUE,
 | |
|              2,
 | |
|              "Processor",
 | |
|              Ptr,
 | |
|              Length,
 | |
|              PARSER_PARAMS (AestProcessorStructure)
 | |
|              );
 | |
| 
 | |
|   // Check if the values used to control the parsing logic have been
 | |
|   // successfully read.
 | |
|   if ((ProcessorId == NULL)           ||
 | |
|       (ProcessorResourceType == NULL) ||
 | |
|       (ProcessorFlags == NULL))
 | |
|   {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"ERROR: Insufficient Processor Error Node length. Length = %d.\n",
 | |
|       Length
 | |
|       );
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   switch (*ProcessorResourceType) {
 | |
|     case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_CACHE:
 | |
|       ParseAcpi (
 | |
|         TRUE,
 | |
|         2,
 | |
|         "Cache Resource",
 | |
|         Ptr + Offset,
 | |
|         Length - Offset,
 | |
|         PARSER_PARAMS (AestProcessorCacheResourceSubstructure)
 | |
|         );
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_TLB:
 | |
|       ParseAcpi (
 | |
|         TRUE,
 | |
|         2,
 | |
|         "TLB Resource",
 | |
|         Ptr + Offset,
 | |
|         Length - Offset,
 | |
|         PARSER_PARAMS (AestProcessorTlbResourceSubstructure)
 | |
|         );
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_PROCESSOR_RESOURCE_TYPE_GENERIC:
 | |
|       ParseAcpi (
 | |
|         TRUE,
 | |
|         2,
 | |
|         "Generic Resource",
 | |
|         Ptr + Offset,
 | |
|         Length - Offset,
 | |
|         PARSER_PARAMS (AestProcessorGenericResourceSubstructure)
 | |
|         );
 | |
|       break;
 | |
|     default:
 | |
|       IncrementErrorCount ();
 | |
|       Print (L"ERROR: Invalid Processor Resource Type.");
 | |
|       return;
 | |
|   } // switch
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the Memory Controller node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the Memory Controller node.
 | |
|   @param [in] Length  Maximum length of the Memory Controller node.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpMemoryControllerNode (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "Memory Controller",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (AestMemoryControllerStructure)
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the SMMU node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the SMMU node.
 | |
|   @param [in] Length  Maximum length of the SMMU node.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpSmmuNode (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "SMMU",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (AestSmmuStructure)
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the Vendor-defined structure.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the Vendor-defined node.
 | |
|   @param [in] Length  Maximum length of the Vendor-defined node.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpVendorDefinedNode (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "Vendor-defined",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (AestVendorDefinedStructure)
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the GIC node.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the GIC node.
 | |
|   @param [in] Length  Maximum length of the GIC node.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpGicNode (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "GIC",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (AestGicStructure)
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the Node Interface structure.
 | |
| 
 | |
|   @param [in] Ptr     Pointer to the start of the Node Interface Structure.
 | |
|   @param [in] Length  Maximum length of the Node Interface Structure.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpNodeInterface (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length
 | |
|   )
 | |
| {
 | |
|   ParseAcpi (
 | |
|     TRUE,
 | |
|     2,
 | |
|     "Node Interface",
 | |
|     Ptr,
 | |
|     Length,
 | |
|     PARSER_PARAMS (AestNodeInterface)
 | |
|     );
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses the Node Interrupts Structure.
 | |
| 
 | |
|   @param [in] Ptr             Pointer to the start of the Node Interrupt array.
 | |
|   @param [in] Length          Maximum length of the Node Interrupt array.
 | |
|   @param [in] InterruptCount  Number if interrupts in the Node Interrupts array.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpNodeInterrupts (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length,
 | |
|   IN UINT32  InterruptCount
 | |
|   )
 | |
| {
 | |
|   UINT32  Offset;
 | |
|   UINT32  Index;
 | |
|   CHAR8   Buffer[64];
 | |
| 
 | |
|   if (Length < (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT))) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"ERROR: Node not long enough for Interrupt Array.\n" \
 | |
|       L"       Length left = %d, Required = %d, Interrupt Count = %d\n",
 | |
|       Length,
 | |
|       (InterruptCount * sizeof (EFI_ACPI_AEST_INTERRUPT_STRUCT)),
 | |
|       InterruptCount
 | |
|       );
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Offset = 0;
 | |
|   for (Index = 0; Index < InterruptCount; Index++) {
 | |
|     AsciiSPrint (
 | |
|       Buffer,
 | |
|       sizeof (Buffer),
 | |
|       "Node Interrupt [%d]",
 | |
|       Index
 | |
|       );
 | |
| 
 | |
|     Offset += ParseAcpi (
 | |
|                 TRUE,
 | |
|                 4,
 | |
|                 Buffer,
 | |
|                 Ptr + Offset,
 | |
|                 Length - Offset,
 | |
|                 PARSER_PARAMS (AestNodeInterrupt)
 | |
|                 );
 | |
|   } // for
 | |
| }
 | |
| 
 | |
| /**
 | |
|   Parses a single AEST Node Structure.
 | |
| 
 | |
|   @param [in] Ptr                   Pointer to the start of the Node.
 | |
|   @param [in] Length                Maximum length of the Node.
 | |
|   @param [in] NodeType              AEST node type.
 | |
|   @param [in] DataOffset            Offset to the node data.
 | |
|   @param [in] InterfaceOffset       Offset to the node interface data.
 | |
|   @param [in] InterruptArrayOffset  Offset to the node interrupt array.
 | |
|   @param [in] InterruptCount        Number of interrupts.
 | |
| **/
 | |
| STATIC
 | |
| VOID
 | |
| DumpAestNodeStructure (
 | |
|   IN UINT8   *Ptr,
 | |
|   IN UINT32  Length,
 | |
|   IN UINT8   NodeType,
 | |
|   IN UINT32  DataOffset,
 | |
|   IN UINT32  InterfaceOffset,
 | |
|   IN UINT32  InterruptArrayOffset,
 | |
|   IN UINT32  InterruptCount
 | |
|   )
 | |
| {
 | |
|   UINT32  Offset;
 | |
|   UINT32  RemainingLength;
 | |
|   UINT8   *NodeDataPtr;
 | |
| 
 | |
|   Offset = ParseAcpi (
 | |
|              TRUE,
 | |
|              2,
 | |
|              "Node Structure",
 | |
|              Ptr,
 | |
|              Length,
 | |
|              PARSER_PARAMS (AestNodeHeaderParser)
 | |
|              );
 | |
| 
 | |
|   if ((Offset > DataOffset) || (DataOffset > Length)) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"ERROR: Invalid Node Data Offset: %d.\n" \
 | |
|       L"       It should be between %d and %d.\n",
 | |
|       DataOffset,
 | |
|       Offset,
 | |
|       Length
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if ((Offset > InterfaceOffset) || (InterfaceOffset > Length)) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"ERROR: Invalid Node Interface Offset: %d.\n" \
 | |
|       L"       It should be between %d and %d.\n",
 | |
|       InterfaceOffset,
 | |
|       Offset,
 | |
|       Length
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   if ((Offset > InterruptArrayOffset) || (InterruptArrayOffset > Length)) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"ERROR: Invalid Node Interrupt Array Offset: %d.\n" \
 | |
|       L"       It should be between %d and %d.\n",
 | |
|       InterruptArrayOffset,
 | |
|       Offset,
 | |
|       Length
 | |
|       );
 | |
|   }
 | |
| 
 | |
|   // Parse Node Data Field.
 | |
|   NodeDataPtr     = Ptr + DataOffset;
 | |
|   RemainingLength = Length - DataOffset;
 | |
|   switch (NodeType) {
 | |
|     case EFI_ACPI_AEST_NODE_TYPE_PROCESSOR:
 | |
|       DumpProcessorNode (NodeDataPtr, RemainingLength);
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_NODE_TYPE_MEMORY:
 | |
|       DumpMemoryControllerNode (NodeDataPtr, RemainingLength);
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_NODE_TYPE_SMMU:
 | |
|       DumpSmmuNode (NodeDataPtr, RemainingLength);
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_NODE_TYPE_VENDOR_DEFINED:
 | |
|       DumpVendorDefinedNode (NodeDataPtr, RemainingLength);
 | |
|       break;
 | |
|     case EFI_ACPI_AEST_NODE_TYPE_GIC:
 | |
|       DumpGicNode (NodeDataPtr, RemainingLength);
 | |
|       break;
 | |
|     default:
 | |
|       IncrementErrorCount ();
 | |
|       Print (L"ERROR: Invalid Error Node Type.\n");
 | |
|       return;
 | |
|   } // switch
 | |
| 
 | |
|   // Parse the Interface Field.
 | |
|   DumpNodeInterface (
 | |
|     Ptr + InterfaceOffset,
 | |
|     Length - InterfaceOffset
 | |
|     );
 | |
| 
 | |
|   // Parse the Node Interrupt Array.
 | |
|   DumpNodeInterrupts (
 | |
|     Ptr + InterruptArrayOffset,
 | |
|     Length - InterruptArrayOffset,
 | |
|     InterruptCount
 | |
|     );
 | |
| 
 | |
|   return;
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the ACPI AEST table.
 | |
|   When trace is enabled this function parses the AEST table and
 | |
|   traces the ACPI table fields.
 | |
| 
 | |
|   This function also performs validation of the ACPI table fields.
 | |
| 
 | |
|   @param [in] Trace              If TRUE, trace the ACPI fields.
 | |
|   @param [in] Ptr                Pointer to the start of the buffer.
 | |
|   @param [in] AcpiTableLength    Length of the ACPI table.
 | |
|   @param [in] AcpiTableRevision  Revision of the ACPI table.
 | |
| **/
 | |
| VOID
 | |
| EFIAPI
 | |
| ParseAcpiAest (
 | |
|   IN BOOLEAN  Trace,
 | |
|   IN UINT8    *Ptr,
 | |
|   IN UINT32   AcpiTableLength,
 | |
|   IN UINT8    AcpiTableRevision
 | |
|   )
 | |
| {
 | |
|   UINT32  Offset;
 | |
|   UINT8   *NodePtr;
 | |
| 
 | |
|   if (!Trace) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Offset = ParseAcpi (
 | |
|              TRUE,
 | |
|              0,
 | |
|              "AEST",
 | |
|              Ptr,
 | |
|              AcpiTableLength,
 | |
|              PARSER_PARAMS (AestParser)
 | |
|              );
 | |
| 
 | |
|   while (Offset < AcpiTableLength) {
 | |
|     NodePtr = Ptr + Offset;
 | |
| 
 | |
|     ParseAcpi (
 | |
|       FALSE,
 | |
|       0,
 | |
|       NULL,
 | |
|       NodePtr,
 | |
|       AcpiTableLength - Offset,
 | |
|       PARSER_PARAMS (AestNodeHeaderParser)
 | |
|       );
 | |
| 
 | |
|     // Check if the values used to control the parsing logic have been
 | |
|     // successfully read.
 | |
|     if ((AestNodeType == NULL)             ||
 | |
|         (AestNodeLength == NULL)           ||
 | |
|         (NodeDataOffset == NULL)           ||
 | |
|         (NodeInterfaceOffset == NULL)      ||
 | |
|         (NodeInterruptArrayOffset == NULL) ||
 | |
|         (NodeInterruptCount == NULL))
 | |
|     {
 | |
|       IncrementErrorCount ();
 | |
|       Print (
 | |
|         L"ERROR: Insufficient length left for Node Structure.\n" \
 | |
|         L"       Length left = %d.\n",
 | |
|         AcpiTableLength - Offset
 | |
|         );
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     // Validate AEST Node length
 | |
|     if ((*AestNodeLength == 0) ||
 | |
|         ((Offset + (*AestNodeLength)) > AcpiTableLength))
 | |
|     {
 | |
|       IncrementErrorCount ();
 | |
|       Print (
 | |
|         L"ERROR: Invalid AEST Node length. " \
 | |
|         L"Length = %d. Offset = %d. AcpiTableLength = %d.\n",
 | |
|         *AestNodeLength,
 | |
|         Offset,
 | |
|         AcpiTableLength
 | |
|         );
 | |
|       return;
 | |
|     }
 | |
| 
 | |
|     DumpAestNodeStructure (
 | |
|       NodePtr,
 | |
|       *AestNodeLength,
 | |
|       *AestNodeType,
 | |
|       *NodeDataOffset,
 | |
|       *NodeInterfaceOffset,
 | |
|       *NodeInterruptArrayOffset,
 | |
|       *NodeInterruptCount
 | |
|       );
 | |
| 
 | |
|     Offset += *AestNodeLength;
 | |
|   } // while
 | |
| }
 |