1. Separate variable definition and initialization. 2. Make the variable naming following Edk2 rule. V2: Remove the updates of guard macros in header files. Cc: Sami Mujawar <sami.mujawar@arm.com> Cc: Evan Lloyd <evan.lloyd@arm.com> Cc: Jaben Carsey <jaben.carsey@intel.com> Cc: Ruiyu Ni <ruiyu.ni@intel.com> Contributed-under: TianoCore Contribution Agreement 1.1 Signed-off-by: Dandan Bi <dandan.bi@intel.com> Reviewed-by: Ruiyu Ni <ruiyu.ni@intel.com>
		
			
				
	
	
		
			325 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
			
		
		
	
	
			325 lines
		
	
	
		
			9.6 KiB
		
	
	
	
		
			C
		
	
	
	
	
	
| /** @file
 | |
|   MADT table parser
 | |
| 
 | |
|   Copyright (c) 2016 - 2018, ARM Limited. All rights reserved.
 | |
|   This program and the accompanying materials
 | |
|   are licensed and made available under the terms and conditions of the BSD License
 | |
|   which accompanies this distribution.  The full text of the license may be found at
 | |
|   http://opensource.org/licenses/bsd-license.php
 | |
| 
 | |
|   THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
 | |
|   WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
 | |
| 
 | |
|   @par Reference(s):
 | |
|     - ACPI 6.2 Specification - Errata A, September 2017
 | |
| **/
 | |
| 
 | |
| #include <IndustryStandard/Acpi.h>
 | |
| #include <Library/UefiLib.h>
 | |
| #include "AcpiParser.h"
 | |
| #include "AcpiTableParser.h"
 | |
| 
 | |
| // Local Variables
 | |
| STATIC CONST UINT8* MadtInterruptControllerType;
 | |
| STATIC CONST UINT8* MadtInterruptControllerLength;
 | |
| STATIC ACPI_DESCRIPTION_HEADER_INFO AcpiHdrInfo;
 | |
| 
 | |
| /**
 | |
|   This function validates the System Vector Base in the GICD.
 | |
| 
 | |
|   @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
 | |
| ValidateGICDSystemVectorBase (
 | |
|   IN UINT8* Ptr,
 | |
|   IN VOID*  Context
 | |
|   );
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the GICC Interrupt Controller Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER GicCParser[] = {
 | |
|   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"CPU Interface Number", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"ACPI Processor UID", 4, 8, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 12, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Parking Protocol Version", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"Performance Interrupt GSIV", 4, 20, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Parked Address", 8, 24, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Physical Base Address", 8, 32, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"GICV", 8, 40, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"GICH", 8, 48, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"VGIC Maintenance interrupt", 4, 56, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"GICR Base Address", 8, 60, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"MPIDR", 8, 68, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Processor Power Efficiency Class", 1, 76, L"0x%x", NULL, NULL, NULL,
 | |
|    NULL},
 | |
|   {L"Reserved", 3, 77, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the GICD Interrupt Controller Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER GicDParser[] = {
 | |
|   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"GIC ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"System Vector Base", 4, 16, L"0x%x", NULL, NULL,
 | |
|     ValidateGICDSystemVectorBase, NULL},
 | |
|   {L"GIC Version", 1, 20, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 3, 21, L"%x %x %x", Dump3Chars, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the MSI Frame Interrupt Controller Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER GicMSIFrameParser[] = {
 | |
|   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"MSI Frame ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Flags", 4, 16, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"SPI Count", 2, 20, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"SPI Base", 2, 22, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the GICR Interrupt Controller Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER GicRParser[] = {
 | |
|   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"Discovery Range Base Address", 8, 4, L"0x%lx", NULL, NULL, NULL,
 | |
|    NULL},
 | |
|   {L"Discovery Range Length", 4, 12, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the GIC ITS Interrupt Controller Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER GicITSParser[] = {
 | |
|   {L"Type", 1, 0, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Length", 1, 1, L"%d", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 2, 2, L"0x%x", NULL, NULL, NULL, NULL},
 | |
| 
 | |
|   {L"GIC ITS ID", 4, 4, L"0x%x", NULL, NULL, NULL, NULL},
 | |
|   {L"Physical Base Address", 8, 8, L"0x%lx", NULL, NULL, NULL, NULL},
 | |
|   {L"Reserved", 4, 16, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the ACPI MADT Table.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER MadtParser[] = {
 | |
|   PARSE_ACPI_HEADER (&AcpiHdrInfo),
 | |
|   {L"Local Interrupt Controller Address", 4, 36, L"0x%x", NULL, NULL, NULL,
 | |
|    NULL},
 | |
|   {L"Flags", 4, 40, L"0x%x", NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   An ACPI_PARSER array describing the MADT Interrupt Controller Structure Header Structure.
 | |
| **/
 | |
| STATIC CONST ACPI_PARSER MadtInterruptControllerHeaderParser[] = {
 | |
|   {NULL, 1, 0, NULL, NULL, (VOID**)&MadtInterruptControllerType, NULL, NULL},
 | |
|   {L"Length", 1, 1, NULL, NULL, (VOID**)&MadtInterruptControllerLength, NULL,
 | |
|    NULL},
 | |
|   {L"Reserved", 2, 2, NULL, NULL, NULL, NULL, NULL}
 | |
| };
 | |
| 
 | |
| /**
 | |
|   This function validates the System Vector Base in the GICD.
 | |
| 
 | |
|   @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
 | |
| ValidateGICDSystemVectorBase (
 | |
|   IN UINT8* Ptr,
 | |
|   IN VOID*  Context
 | |
| )
 | |
| {
 | |
|   if (*(UINT32*)Ptr != 0) {
 | |
|     IncrementErrorCount ();
 | |
|     Print (
 | |
|       L"\nERROR: System Vector Base must be zero."
 | |
|     );
 | |
|   }
 | |
| }
 | |
| 
 | |
| /**
 | |
|   This function parses the ACPI MADT table.
 | |
|   When trace is enabled this function parses the MADT table and
 | |
|   traces the ACPI table fields.
 | |
| 
 | |
|   This function currently parses the following Interrupt Controller
 | |
|   Structures:
 | |
|     - GICC
 | |
|     - GICD
 | |
|     - GIC MSI Frame
 | |
|     - GICR
 | |
|     - GIC ITS
 | |
| 
 | |
|   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
 | |
| ParseAcpiMadt (
 | |
|   IN BOOLEAN Trace,
 | |
|   IN UINT8*  Ptr,
 | |
|   IN UINT32  AcpiTableLength,
 | |
|   IN UINT8   AcpiTableRevision
 | |
|   )
 | |
| {
 | |
|   UINT32 Offset;
 | |
|   UINT8* InterruptContollerPtr;
 | |
|   UINT32 GICDCount;
 | |
| 
 | |
|   GICDCount = 0;
 | |
| 
 | |
|   if (!Trace) {
 | |
|     return;
 | |
|   }
 | |
| 
 | |
|   Offset = ParseAcpi (
 | |
|              TRUE,
 | |
|              0,
 | |
|              "MADT",
 | |
|              Ptr,
 | |
|              AcpiTableLength,
 | |
|              PARSER_PARAMS (MadtParser)
 | |
|              );
 | |
|   InterruptContollerPtr = Ptr + Offset;
 | |
| 
 | |
|   while (Offset < AcpiTableLength) {
 | |
|     // Parse Interrupt Controller Structure to obtain Length.
 | |
|     ParseAcpi (
 | |
|       FALSE,
 | |
|       0,
 | |
|       NULL,
 | |
|       InterruptContollerPtr,
 | |
|       2,  //  Length is 1 byte at offset 1
 | |
|       PARSER_PARAMS (MadtInterruptControllerHeaderParser)
 | |
|       );
 | |
| 
 | |
|     if (((Offset + (*MadtInterruptControllerLength)) > AcpiTableLength) ||
 | |
|         (*MadtInterruptControllerLength < 4)) {
 | |
|       IncrementErrorCount ();
 | |
|       Print (
 | |
|          L"ERROR: Invalid Interrupt Controller Length,"
 | |
|           " Type = %d, Length = %d\n",
 | |
|          *MadtInterruptControllerType,
 | |
|          *MadtInterruptControllerLength
 | |
|          );
 | |
|       break;
 | |
|     }
 | |
| 
 | |
|     switch (*MadtInterruptControllerType) {
 | |
|       case EFI_ACPI_6_2_GIC: {
 | |
|         ParseAcpi (
 | |
|           TRUE,
 | |
|           2,
 | |
|           "GICC",
 | |
|           InterruptContollerPtr,
 | |
|           *MadtInterruptControllerLength,
 | |
|           PARSER_PARAMS (GicCParser)
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case EFI_ACPI_6_2_GICD: {
 | |
|         if (++GICDCount > 1) {
 | |
|           IncrementErrorCount ();
 | |
|           Print (
 | |
|             L"ERROR: Only one GICD must be present,"
 | |
|               " GICDCount = %d\n",
 | |
|             GICDCount
 | |
|             );
 | |
|         }
 | |
|         ParseAcpi (
 | |
|           TRUE,
 | |
|           2,
 | |
|           "GICD",
 | |
|           InterruptContollerPtr,
 | |
|           *MadtInterruptControllerLength,
 | |
|           PARSER_PARAMS (GicDParser)
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case EFI_ACPI_6_2_GIC_MSI_FRAME: {
 | |
|         ParseAcpi (
 | |
|           TRUE,
 | |
|           2,
 | |
|           "GIC MSI Frame",
 | |
|           InterruptContollerPtr,
 | |
|           *MadtInterruptControllerLength,
 | |
|           PARSER_PARAMS (GicMSIFrameParser)
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case EFI_ACPI_6_2_GICR: {
 | |
|         ParseAcpi (
 | |
|           TRUE,
 | |
|           2,
 | |
|           "GICR",
 | |
|           InterruptContollerPtr,
 | |
|           *MadtInterruptControllerLength,
 | |
|           PARSER_PARAMS (GicRParser)
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       case EFI_ACPI_6_2_GIC_ITS: {
 | |
|         ParseAcpi (
 | |
|           TRUE,
 | |
|           2,
 | |
|           "GIC ITS",
 | |
|           InterruptContollerPtr,
 | |
|           *MadtInterruptControllerLength,
 | |
|           PARSER_PARAMS (GicITSParser)
 | |
|           );
 | |
|         break;
 | |
|       }
 | |
| 
 | |
|       default: {
 | |
|         IncrementErrorCount ();
 | |
|         Print (
 | |
|           L"ERROR: Unknown Interrupt Controller Structure,"
 | |
|             " Type = %d, Length = %d\n",
 | |
|           *MadtInterruptControllerType,
 | |
|           *MadtInterruptControllerLength
 | |
|           );
 | |
|       }
 | |
|     } // switch
 | |
| 
 | |
|     InterruptContollerPtr += *MadtInterruptControllerLength;
 | |
|     Offset += *MadtInterruptControllerLength;
 | |
|   } // while
 | |
| }
 |