ACPICA: Rename nameseg length macro/define for clarity
[linux-2.6-microblaze.git] / drivers / acpi / acpica / tbprint.c
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 - 2019, 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 }