1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: tbprint - Table output utilities 5 * 6 * Copyright (C) 2000 - 2021, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "actables.h" 13 14 #define _COMPONENT ACPI_TABLES 15 ACPI_MODULE_NAME("tbprint") 16 17 /* Local prototypes */ 18 static void acpi_tb_fix_string(char *string, acpi_size length); 19 20 static void 21 acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, 22 struct acpi_table_header *header); 23 24 /******************************************************************************* 25 * 26 * FUNCTION: acpi_tb_fix_string 27 * 28 * PARAMETERS: string - String to be repaired 29 * length - Maximum length 30 * 31 * RETURN: None 32 * 33 * DESCRIPTION: Replace every non-printable or non-ascii byte in the string 34 * with a question mark '?'. 35 * 36 ******************************************************************************/ 37 38 static void acpi_tb_fix_string(char *string, acpi_size length) 39 { 40 41 while (length && *string) { 42 if (!isprint((int)*string)) { 43 *string = '?'; 44 } 45 46 string++; 47 length--; 48 } 49 } 50 51 /******************************************************************************* 52 * 53 * FUNCTION: acpi_tb_cleanup_table_header 54 * 55 * PARAMETERS: out_header - Where the cleaned header is returned 56 * header - Input ACPI table header 57 * 58 * RETURN: Returns the cleaned header in out_header 59 * 60 * DESCRIPTION: Copy the table header and ensure that all "string" fields in 61 * the header consist of printable characters. 62 * 63 ******************************************************************************/ 64 65 static void 66 acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, 67 struct acpi_table_header *header) 68 { 69 70 memcpy(out_header, header, sizeof(struct acpi_table_header)); 71 72 acpi_tb_fix_string(out_header->signature, ACPI_NAMESEG_SIZE); 73 acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); 74 acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); 75 acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAMESEG_SIZE); 76 } 77 78 /******************************************************************************* 79 * 80 * FUNCTION: acpi_tb_print_table_header 81 * 82 * PARAMETERS: address - Table physical address 83 * header - Table header 84 * 85 * RETURN: None 86 * 87 * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 88 * 89 ******************************************************************************/ 90 91 void 92 acpi_tb_print_table_header(acpi_physical_address address, 93 struct acpi_table_header *header) 94 { 95 struct acpi_table_header local_header; 96 97 if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) { 98 99 /* FACS only has signature and length fields */ 100 101 ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X", 102 header->signature, ACPI_FORMAT_UINT64(address), 103 header->length)); 104 } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { 105 106 /* RSDP has no common fields */ 107 108 memcpy(local_header.oem_id, 109 ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id, 110 ACPI_OEM_ID_SIZE); 111 acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); 112 113 ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", 114 ACPI_FORMAT_UINT64(address), 115 (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> 116 revision > 117 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, 118 header)->length : 20, 119 ACPI_CAST_PTR(struct acpi_table_rsdp, 120 header)->revision, 121 local_header.oem_id)); 122 } else { 123 /* Standard ACPI table with full common header */ 124 125 acpi_tb_cleanup_table_header(&local_header, header); 126 127 ACPI_INFO(("%-4.4s 0x%8.8X%8.8X" 128 " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", 129 local_header.signature, ACPI_FORMAT_UINT64(address), 130 local_header.length, local_header.revision, 131 local_header.oem_id, local_header.oem_table_id, 132 local_header.oem_revision, 133 local_header.asl_compiler_id, 134 local_header.asl_compiler_revision)); 135 } 136 } 137 138 /******************************************************************************* 139 * 140 * FUNCTION: acpi_tb_validate_checksum 141 * 142 * PARAMETERS: table - ACPI table to verify 143 * length - Length of entire table 144 * 145 * RETURN: Status 146 * 147 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 148 * exception on bad checksum. 149 * 150 ******************************************************************************/ 151 152 acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) 153 { 154 u8 checksum; 155 156 /* 157 * FACS/S3PT: 158 * They are the odd tables, have no standard ACPI header and no checksum 159 */ 160 161 if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || 162 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { 163 return (AE_OK); 164 } 165 166 /* Compute the checksum on the table */ 167 168 checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); 169 170 /* Checksum ok? (should be zero) */ 171 172 if (checksum) { 173 ACPI_BIOS_WARNING((AE_INFO, 174 "Incorrect checksum in table [%4.4s] - 0x%2.2X, " 175 "should be 0x%2.2X", 176 table->signature, table->checksum, 177 (u8)(table->checksum - checksum))); 178 179 #if (ACPI_CHECKSUM_ABORT) 180 return (AE_BAD_CHECKSUM); 181 #endif 182 } 183 184 return (AE_OK); 185 } 186 187 /******************************************************************************* 188 * 189 * FUNCTION: acpi_tb_checksum 190 * 191 * PARAMETERS: buffer - Pointer to memory region to be checked 192 * length - Length of this memory region 193 * 194 * RETURN: Checksum (u8) 195 * 196 * DESCRIPTION: Calculates circular checksum of memory region. 197 * 198 ******************************************************************************/ 199 200 u8 acpi_tb_checksum(u8 *buffer, u32 length) 201 { 202 u8 sum = 0; 203 u8 *end = buffer + length; 204 205 while (buffer < end) { 206 sum = (u8)(sum + *(buffer++)); 207 } 208 209 return (sum); 210 } 211