/** @file Copyright (c) 2016 - 2020, ARM Limited. All rights reserved. SPDX-License-Identifier: BSD-2-Clause-Patent @par Glossary: - Sbbr or SBBR - Server Base Boot Requirements @par Reference(s): - Arm Server Base Boot Requirements 1.2, September 2019 **/ #include #include #include #include #include #include #include #include #include "AcpiParser.h" #include "AcpiTableParser.h" #include "AcpiView.h" #include "AcpiViewConfig.h" #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) #include "Arm/SbbrValidator.h" #endif STATIC UINT32 mTableCount; STATIC UINT32 mBinTableCount; /** This function dumps the ACPI table to a file. @param [in] Ptr Pointer to the ACPI table data. @param [in] Length The length of the ACPI table. @retval TRUE Success. @retval FALSE Failure. **/ STATIC BOOLEAN DumpAcpiTableToFile ( IN CONST UINT8* Ptr, IN CONST UINTN Length ) { CHAR16 FileNameBuffer[MAX_FILE_NAME_LEN]; UINTN TransferBytes; SELECTED_ACPI_TABLE *SelectedTable; GetSelectedAcpiTable (&SelectedTable); UnicodeSPrint ( FileNameBuffer, sizeof (FileNameBuffer), L".\\%s%04d.bin", SelectedTable->Name, mBinTableCount++ ); Print (L"Dumping ACPI table to : %s ... ", FileNameBuffer); TransferBytes = ShellDumpBufferToFile (FileNameBuffer, Ptr, Length); return (Length == TransferBytes); } /** This function processes the table reporting options for the ACPI table. @param [in] Signature The ACPI table Signature. @param [in] TablePtr Pointer to the ACPI table data. @param [in] Length The length fo the ACPI table. @retval Returns TRUE if the ACPI table should be traced. **/ BOOLEAN ProcessTableReportOptions ( IN CONST UINT32 Signature, IN CONST UINT8* TablePtr, IN CONST UINT32 Length ) { UINTN OriginalAttribute; UINT8 *SignaturePtr; BOOLEAN Log; BOOLEAN HighLight; SELECTED_ACPI_TABLE *SelectedTable; // // set local variables to suppress incorrect compiler/analyzer warnings // OriginalAttribute = 0; SignaturePtr = (UINT8*)(UINTN)&Signature; Log = FALSE; HighLight = GetColourHighlighting (); GetSelectedAcpiTable (&SelectedTable); switch (GetReportOption ()) { case ReportAll: Log = TRUE; break; case ReportSelected: if (Signature == SelectedTable->Type) { Log = TRUE; SelectedTable->Found = TRUE; } break; case ReportTableList: if (mTableCount == 0) { if (HighLight) { OriginalAttribute = gST->ConOut->Mode->Attribute; gST->ConOut->SetAttribute ( gST->ConOut, EFI_TEXT_ATTR(EFI_CYAN, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) ); } Print (L"\nInstalled Table(s):\n"); if (HighLight) { gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); } } Print ( L"\t%4d. %c%c%c%c\n", ++mTableCount, SignaturePtr[0], SignaturePtr[1], SignaturePtr[2], SignaturePtr[3] ); break; case ReportDumpBinFile: if (Signature == SelectedTable->Type) { SelectedTable->Found = TRUE; DumpAcpiTableToFile (TablePtr, Length); } break; case ReportMax: // We should never be here. // This case is only present to prevent compiler warning. break; } // switch if (Log) { if (HighLight) { OriginalAttribute = gST->ConOut->Mode->Attribute; gST->ConOut->SetAttribute ( gST->ConOut, EFI_TEXT_ATTR(EFI_LIGHTBLUE, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4)) ); } Print ( L"\n\n --------------- %c%c%c%c Table --------------- \n\n", SignaturePtr[0], SignaturePtr[1], SignaturePtr[2], SignaturePtr[3] ); if (HighLight) { gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); } } return Log; } /** This function iterates the configuration table entries in the system table, retrieves the RSDP pointer and starts parsing the ACPI tables. @param [in] SystemTable Pointer to the EFI system table. @retval Returns EFI_NOT_FOUND if the RSDP pointer is not found. Returns EFI_UNSUPPORTED if the RSDP version is less than 2. Returns EFI_SUCCESS if successful. **/ EFI_STATUS EFIAPI AcpiView ( IN EFI_SYSTEM_TABLE* SystemTable ) { EFI_STATUS Status; UINTN Index; EFI_CONFIGURATION_TABLE* EfiConfigurationTable; BOOLEAN FoundAcpiTable; UINTN OriginalAttribute; UINTN PrintAttribute; EREPORT_OPTION ReportOption; UINT8* RsdpPtr; UINT32 RsdpLength; UINT8 RsdpRevision; PARSE_ACPI_TABLE_PROC RsdpParserProc; BOOLEAN Trace; SELECTED_ACPI_TABLE *SelectedTable; // // set local variables to suppress incorrect compiler/analyzer warnings // EfiConfigurationTable = NULL; OriginalAttribute = 0; // Reset Table counts mTableCount = 0; mBinTableCount = 0; // Reset The error/warning counters ResetErrorCount (); ResetWarningCount (); // Retrieve the user selection of ACPI table to process GetSelectedAcpiTable (&SelectedTable); // Search the table for an entry that matches the ACPI Table Guid FoundAcpiTable = FALSE; for (Index = 0; Index < SystemTable->NumberOfTableEntries; Index++) { if (CompareGuid (&gEfiAcpiTableGuid, &(SystemTable->ConfigurationTable[Index].VendorGuid))) { EfiConfigurationTable = &SystemTable->ConfigurationTable[Index]; FoundAcpiTable = TRUE; break; } } if (FoundAcpiTable) { RsdpPtr = (UINT8*)EfiConfigurationTable->VendorTable; // The RSDP revision is 1 byte starting at offset 15 RsdpRevision = *(RsdpPtr + RSDP_REVISION_OFFSET); if (RsdpRevision < 2) { Print ( L"ERROR: RSDP version less than 2 is not supported.\n" ); return EFI_UNSUPPORTED; } #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) if (GetMandatoryTableValidate ()) { ArmSbbrResetTableCounts (); } #endif // The RSDP length is 4 bytes starting at offset 20 RsdpLength = *(UINT32*)(RsdpPtr + RSDP_LENGTH_OFFSET); Trace = ProcessTableReportOptions (RSDP_TABLE_INFO, RsdpPtr, RsdpLength); Status = GetParser (RSDP_TABLE_INFO, &RsdpParserProc); if (EFI_ERROR (Status)) { Print ( L"ERROR: No registered parser found for RSDP.\n" ); return Status; } RsdpParserProc ( Trace, RsdpPtr, RsdpLength, RsdpRevision ); } else { IncrementErrorCount (); Print ( L"ERROR: Failed to find ACPI Table Guid in System Configuration Table.\n" ); return EFI_NOT_FOUND; } #if defined(MDE_CPU_ARM) || defined (MDE_CPU_AARCH64) if (GetMandatoryTableValidate ()) { ArmSbbrReqsValidate ((ARM_SBBR_VERSION)GetMandatoryTableSpec ()); } #endif ReportOption = GetReportOption (); if (ReportTableList != ReportOption) { if (((ReportSelected == ReportOption) || (ReportDumpBinFile == ReportOption)) && (!SelectedTable->Found)) { Print (L"\nRequested ACPI Table not found.\n"); } else if (GetConsistencyChecking () && (ReportDumpBinFile != ReportOption)) { OriginalAttribute = gST->ConOut->Mode->Attribute; Print (L"\nTable Statistics:\n"); if (GetColourHighlighting ()) { PrintAttribute = (GetErrorCount () > 0) ? EFI_TEXT_ATTR ( EFI_RED, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) ) : OriginalAttribute; gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); } Print (L"\t%d Error(s)\n", GetErrorCount ()); if (GetColourHighlighting ()) { PrintAttribute = (GetWarningCount () > 0) ? EFI_TEXT_ATTR ( EFI_RED, ((OriginalAttribute&(BIT4|BIT5|BIT6))>>4) ) : OriginalAttribute; gST->ConOut->SetAttribute (gST->ConOut, PrintAttribute); } Print (L"\t%d Warning(s)\n", GetWarningCount ()); if (GetColourHighlighting ()) { gST->ConOut->SetAttribute (gST->ConOut, OriginalAttribute); } } } return EFI_SUCCESS; }