Branch data Line data Source code
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 - 2020, 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 : 273 : static void acpi_tb_fix_string(char *string, acpi_size length)
39 : : {
40 : :
41 [ + + + - ]: 1781 : while (length && *string) {
42 [ - + ]: 1508 : if (!isprint((int)*string)) {
43 : 0 : *string = '?';
44 : : }
45 : :
46 : 1508 : string++;
47 : 1508 : length--;
48 : : }
49 : 273 : }
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 : 65 : acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
67 : : struct acpi_table_header *header)
68 : : {
69 : :
70 : 65 : memcpy(out_header, header, sizeof(struct acpi_table_header));
71 : :
72 : 65 : acpi_tb_fix_string(out_header->signature, ACPI_NAMESEG_SIZE);
73 : 65 : acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE);
74 : 65 : acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
75 : 65 : acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAMESEG_SIZE);
76 : 65 : }
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 : 91 : acpi_tb_print_table_header(acpi_physical_address address,
93 : : struct acpi_table_header *header)
94 : : {
95 : 91 : struct acpi_table_header local_header;
96 : :
97 [ + + ]: 91 : if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) {
98 : :
99 : : /* FACS only has signature and length fields */
100 : :
101 : 13 : ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X",
102 : : header->signature, ACPI_FORMAT_UINT64(address),
103 : : header->length));
104 [ + + ]: 78 : } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
105 : :
106 : : /* RSDP has no common fields */
107 : :
108 : 13 : memcpy(local_header.oem_id,
109 : : ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id,
110 : : ACPI_OEM_ID_SIZE);
111 : 13 : acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
112 : :
113 [ - + ]: 13 : 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 : 65 : acpi_tb_cleanup_table_header(&local_header, header);
126 : :
127 : 65 : 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 : 91 : }
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 : 91 : acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
153 : : {
154 : 91 : u8 checksum;
155 : :
156 : : /*
157 : : * FACS/S3PT:
158 : : * They are the odd tables, have no standard ACPI header and no checksum
159 : : */
160 : :
161 [ + - + + ]: 91 : 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 : 78 : checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
169 : :
170 : : /* Checksum ok? (should be zero) */
171 : :
172 [ - + ]: 78 : if (checksum) {
173 : 0 : 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 : 78 : u8 acpi_tb_checksum(u8 *buffer, u32 length)
201 : : {
202 : 78 : u8 sum = 0;
203 : 78 : u8 *end = buffer + length;
204 : :
205 [ + + ]: 72280 : while (buffer < end) {
206 : 72202 : sum = (u8)(sum + *(buffer++));
207 : : }
208 : :
209 : 78 : return (sum);
210 : : }
|