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(ACPI_CAST_PTR(struct acpi_table_rsdp, 105 header)->signature)) { 106 107 /* RSDP has no common fields */ 108 109 memcpy(local_header.oem_id, 110 ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id, 111 ACPI_OEM_ID_SIZE); 112 acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); 113 114 ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", 115 ACPI_FORMAT_UINT64(address), 116 (ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> 117 revision > 118 0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, 119 header)->length : 20, 120 ACPI_CAST_PTR(struct acpi_table_rsdp, 121 header)->revision, 122 local_header.oem_id)); 123 } else { 124 /* Standard ACPI table with full common header */ 125 126 acpi_tb_cleanup_table_header(&local_header, header); 127 128 ACPI_INFO(("%-4.4s 0x%8.8X%8.8X" 129 " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", 130 local_header.signature, ACPI_FORMAT_UINT64(address), 131 local_header.length, local_header.revision, 132 local_header.oem_id, local_header.oem_table_id, 133 local_header.oem_revision, 134 local_header.asl_compiler_id, 135 local_header.asl_compiler_revision)); 136 } 137 } 138 139 /******************************************************************************* 140 * 141 * FUNCTION: acpi_tb_validate_checksum 142 * 143 * PARAMETERS: table - ACPI table to verify 144 * length - Length of entire table 145 * 146 * RETURN: Status 147 * 148 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 149 * exception on bad checksum. 150 * 151 ******************************************************************************/ 152 153 acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) 154 { 155 u8 checksum; 156 157 /* 158 * FACS/S3PT: 159 * They are the odd tables, have no standard ACPI header and no checksum 160 */ 161 162 if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || 163 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { 164 return (AE_OK); 165 } 166 167 /* Compute the checksum on the table */ 168 169 checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); 170 171 /* Checksum ok? (should be zero) */ 172 173 if (checksum) { 174 ACPI_BIOS_WARNING((AE_INFO, 175 "Incorrect checksum in table [%4.4s] - 0x%2.2X, " 176 "should be 0x%2.2X", 177 table->signature, table->checksum, 178 (u8)(table->checksum - checksum))); 179 180 #if (ACPI_CHECKSUM_ABORT) 181 return (AE_BAD_CHECKSUM); 182 #endif 183 } 184 185 return (AE_OK); 186 } 187 188 /******************************************************************************* 189 * 190 * FUNCTION: acpi_tb_checksum 191 * 192 * PARAMETERS: buffer - Pointer to memory region to be checked 193 * length - Length of this memory region 194 * 195 * RETURN: Checksum (u8) 196 * 197 * DESCRIPTION: Calculates circular checksum of memory region. 198 * 199 ******************************************************************************/ 200 201 u8 acpi_tb_checksum(u8 *buffer, u32 length) 202 { 203 u8 sum = 0; 204 u8 *end = buffer + length; 205 206 while (buffer < end) { 207 sum = (u8)(sum + *(buffer++)); 208 } 209 210 return (sum); 211 } 212