195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 242f47869SBob Moore /****************************************************************************** 342f47869SBob Moore * 442f47869SBob Moore * Module Name: tbprint - Table output utilities 542f47869SBob Moore * 6840c02caSBob Moore * Copyright (C) 2000 - 2019, Intel Corp. 742f47869SBob Moore * 895857638SErik Schmauss *****************************************************************************/ 942f47869SBob Moore 1042f47869SBob Moore #include <acpi/acpi.h> 1142f47869SBob Moore #include "accommon.h" 1242f47869SBob Moore #include "actables.h" 1342f47869SBob Moore 1442f47869SBob Moore #define _COMPONENT ACPI_TABLES 1542f47869SBob Moore ACPI_MODULE_NAME("tbprint") 1642f47869SBob Moore 1742f47869SBob Moore /* Local prototypes */ 1842f47869SBob Moore static void acpi_tb_fix_string(char *string, acpi_size length); 1942f47869SBob Moore 2042f47869SBob Moore static void 2142f47869SBob Moore acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, 2242f47869SBob Moore struct acpi_table_header *header); 2342f47869SBob Moore 2442f47869SBob Moore /******************************************************************************* 2542f47869SBob Moore * 2642f47869SBob Moore * FUNCTION: acpi_tb_fix_string 2742f47869SBob Moore * 2842f47869SBob Moore * PARAMETERS: string - String to be repaired 2942f47869SBob Moore * length - Maximum length 3042f47869SBob Moore * 3142f47869SBob Moore * RETURN: None 3242f47869SBob Moore * 3342f47869SBob Moore * DESCRIPTION: Replace every non-printable or non-ascii byte in the string 3442f47869SBob Moore * with a question mark '?'. 3542f47869SBob Moore * 3642f47869SBob Moore ******************************************************************************/ 3742f47869SBob Moore 3842f47869SBob Moore static void acpi_tb_fix_string(char *string, acpi_size length) 3942f47869SBob Moore { 4042f47869SBob Moore 4142f47869SBob Moore while (length && *string) { 424fa4616eSBob Moore if (!isprint((int)*string)) { 4342f47869SBob Moore *string = '?'; 4442f47869SBob Moore } 451fad8738SBob Moore 4642f47869SBob Moore string++; 4742f47869SBob Moore length--; 4842f47869SBob Moore } 4942f47869SBob Moore } 5042f47869SBob Moore 5142f47869SBob Moore /******************************************************************************* 5242f47869SBob Moore * 5342f47869SBob Moore * FUNCTION: acpi_tb_cleanup_table_header 5442f47869SBob Moore * 5542f47869SBob Moore * PARAMETERS: out_header - Where the cleaned header is returned 5642f47869SBob Moore * header - Input ACPI table header 5742f47869SBob Moore * 5842f47869SBob Moore * RETURN: Returns the cleaned header in out_header 5942f47869SBob Moore * 6042f47869SBob Moore * DESCRIPTION: Copy the table header and ensure that all "string" fields in 6142f47869SBob Moore * the header consist of printable characters. 6242f47869SBob Moore * 6342f47869SBob Moore ******************************************************************************/ 6442f47869SBob Moore 6542f47869SBob Moore static void 6642f47869SBob Moore acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, 6742f47869SBob Moore struct acpi_table_header *header) 6842f47869SBob Moore { 6942f47869SBob Moore 704fa4616eSBob Moore memcpy(out_header, header, sizeof(struct acpi_table_header)); 7142f47869SBob Moore 7242f47869SBob Moore acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE); 7342f47869SBob Moore acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); 7442f47869SBob Moore acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); 7542f47869SBob Moore acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE); 7642f47869SBob Moore } 7742f47869SBob Moore 7842f47869SBob Moore /******************************************************************************* 7942f47869SBob Moore * 8042f47869SBob Moore * FUNCTION: acpi_tb_print_table_header 8142f47869SBob Moore * 8242f47869SBob Moore * PARAMETERS: address - Table physical address 8342f47869SBob Moore * header - Table header 8442f47869SBob Moore * 8542f47869SBob Moore * RETURN: None 8642f47869SBob Moore * 8742f47869SBob Moore * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 8842f47869SBob Moore * 8942f47869SBob Moore ******************************************************************************/ 9042f47869SBob Moore 9142f47869SBob Moore void 9242f47869SBob Moore acpi_tb_print_table_header(acpi_physical_address address, 9342f47869SBob Moore struct acpi_table_header *header) 9442f47869SBob Moore { 9542f47869SBob Moore struct acpi_table_header local_header; 9642f47869SBob Moore 975599fb69SBob Moore if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) { 9842f47869SBob Moore 9942f47869SBob Moore /* FACS only has signature and length fields */ 10042f47869SBob Moore 10105fb04b5SBob Moore ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X", 1021d0a0b2fSLv Zheng header->signature, ACPI_FORMAT_UINT64(address), 10342f47869SBob Moore header->length)); 104cacba865SLv Zheng } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { 10542f47869SBob Moore 10642f47869SBob Moore /* RSDP has no common fields */ 10742f47869SBob Moore 1084fa4616eSBob Moore memcpy(local_header.oem_id, 1094fa4616eSBob Moore ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id, 1104fa4616eSBob Moore ACPI_OEM_ID_SIZE); 11142f47869SBob Moore acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); 11242f47869SBob Moore 11305fb04b5SBob Moore ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", 1141d0a0b2fSLv Zheng ACPI_FORMAT_UINT64(address), 11542f47869SBob Moore (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> 11642f47869SBob Moore revision > 11742f47869SBob Moore 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, 11842f47869SBob Moore header)->length : 20, 11942f47869SBob Moore ACPI_CAST_PTR(struct acpi_table_rsdp, 12042f47869SBob Moore header)->revision, 12142f47869SBob Moore local_header.oem_id)); 12242f47869SBob Moore } else { 12342f47869SBob Moore /* Standard ACPI table with full common header */ 12442f47869SBob Moore 12542f47869SBob Moore acpi_tb_cleanup_table_header(&local_header, header); 12642f47869SBob Moore 12705fb04b5SBob Moore ACPI_INFO(("%-4.4s 0x%8.8X%8.8X" 128c03775c0SBob Moore " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", 1291d0a0b2fSLv Zheng local_header.signature, ACPI_FORMAT_UINT64(address), 13042f47869SBob Moore local_header.length, local_header.revision, 13142f47869SBob Moore local_header.oem_id, local_header.oem_table_id, 13242f47869SBob Moore local_header.oem_revision, 13342f47869SBob Moore local_header.asl_compiler_id, 13442f47869SBob Moore local_header.asl_compiler_revision)); 13542f47869SBob Moore } 13642f47869SBob Moore } 13742f47869SBob Moore 13842f47869SBob Moore /******************************************************************************* 13942f47869SBob Moore * 14042f47869SBob Moore * FUNCTION: acpi_tb_validate_checksum 14142f47869SBob Moore * 14242f47869SBob Moore * PARAMETERS: table - ACPI table to verify 14342f47869SBob Moore * length - Length of entire table 14442f47869SBob Moore * 14542f47869SBob Moore * RETURN: Status 14642f47869SBob Moore * 14742f47869SBob Moore * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 14842f47869SBob Moore * exception on bad checksum. 14942f47869SBob Moore * 15042f47869SBob Moore ******************************************************************************/ 15142f47869SBob Moore 15242f47869SBob Moore acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) 15342f47869SBob Moore { 15442f47869SBob Moore u8 checksum; 15542f47869SBob Moore 15694d4be67SLv Zheng /* 15794d4be67SLv Zheng * FACS/S3PT: 15894d4be67SLv Zheng * They are the odd tables, have no standard ACPI header and no checksum 15994d4be67SLv Zheng */ 16094d4be67SLv Zheng 1615599fb69SBob Moore if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || 1625599fb69SBob Moore ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { 16394d4be67SLv Zheng return (AE_OK); 16494d4be67SLv Zheng } 16594d4be67SLv Zheng 16642f47869SBob Moore /* Compute the checksum on the table */ 16742f47869SBob Moore 16842f47869SBob Moore checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); 16942f47869SBob Moore 17042f47869SBob Moore /* Checksum ok? (should be zero) */ 17142f47869SBob Moore 17242f47869SBob Moore if (checksum) { 17342f47869SBob Moore ACPI_BIOS_WARNING((AE_INFO, 17442f47869SBob Moore "Incorrect checksum in table [%4.4s] - 0x%2.2X, " 17542f47869SBob Moore "should be 0x%2.2X", 17642f47869SBob Moore table->signature, table->checksum, 17742f47869SBob Moore (u8)(table->checksum - checksum))); 17842f47869SBob Moore 17942f47869SBob Moore #if (ACPI_CHECKSUM_ABORT) 18042f47869SBob Moore return (AE_BAD_CHECKSUM); 18142f47869SBob Moore #endif 18242f47869SBob Moore } 18342f47869SBob Moore 18442f47869SBob Moore return (AE_OK); 18542f47869SBob Moore } 18642f47869SBob Moore 18742f47869SBob Moore /******************************************************************************* 18842f47869SBob Moore * 18942f47869SBob Moore * FUNCTION: acpi_tb_checksum 19042f47869SBob Moore * 19142f47869SBob Moore * PARAMETERS: buffer - Pointer to memory region to be checked 19242f47869SBob Moore * length - Length of this memory region 19342f47869SBob Moore * 19442f47869SBob Moore * RETURN: Checksum (u8) 19542f47869SBob Moore * 19642f47869SBob Moore * DESCRIPTION: Calculates circular checksum of memory region. 19742f47869SBob Moore * 19842f47869SBob Moore ******************************************************************************/ 19942f47869SBob Moore 20042f47869SBob Moore u8 acpi_tb_checksum(u8 *buffer, u32 length) 20142f47869SBob Moore { 20242f47869SBob Moore u8 sum = 0; 20342f47869SBob Moore u8 *end = buffer + length; 20442f47869SBob Moore 20542f47869SBob Moore while (buffer < end) { 20642f47869SBob Moore sum = (u8)(sum + *(buffer++)); 20742f47869SBob Moore } 20842f47869SBob Moore 20942f47869SBob Moore return (sum); 21042f47869SBob Moore } 211