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