GNU Linux-libre 4.19.286-gnu1
[releases.git] / tools / power / acpi / tools / acpidump / apdump.c
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3  *
4  * Module Name: apdump - Dump routines for ACPI tables (acpidump)
5  *
6  * Copyright (C) 2000 - 2018, Intel Corp.
7  *
8  *****************************************************************************/
9
10 #include "acpidump.h"
11
12 /* Local prototypes */
13
14 static int
15 ap_dump_table_buffer(struct acpi_table_header *table,
16                      u32 instance, acpi_physical_address address);
17
18 /******************************************************************************
19  *
20  * FUNCTION:    ap_is_valid_header
21  *
22  * PARAMETERS:  table               - Pointer to table to be validated
23  *
24  * RETURN:      TRUE if the header appears to be valid. FALSE otherwise
25  *
26  * DESCRIPTION: Check for a valid ACPI table header
27  *
28  ******************************************************************************/
29
30 u8 ap_is_valid_header(struct acpi_table_header *table)
31 {
32
33         if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) {
34
35                 /* Make sure signature is all ASCII and a valid ACPI name */
36
37                 if (!acpi_ut_valid_nameseg(table->signature)) {
38                         fprintf(stderr,
39                                 "Table signature (0x%8.8X) is invalid\n",
40                                 *(u32 *)table->signature);
41                         return (FALSE);
42                 }
43
44                 /* Check for minimum table length */
45
46                 if (table->length < sizeof(struct acpi_table_header)) {
47                         fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
48                                 table->length);
49                         return (FALSE);
50                 }
51         }
52
53         return (TRUE);
54 }
55
56 /******************************************************************************
57  *
58  * FUNCTION:    ap_is_valid_checksum
59  *
60  * PARAMETERS:  table               - Pointer to table to be validated
61  *
62  * RETURN:      TRUE if the checksum appears to be valid. FALSE otherwise.
63  *
64  * DESCRIPTION: Check for a valid ACPI table checksum.
65  *
66  ******************************************************************************/
67
68 u8 ap_is_valid_checksum(struct acpi_table_header *table)
69 {
70         acpi_status status;
71         struct acpi_table_rsdp *rsdp;
72
73         if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
74                 /*
75                  * Checksum for RSDP.
76                  * Note: Other checksums are computed during the table dump.
77                  */
78                 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
79                 status = acpi_tb_validate_rsdp(rsdp);
80         } else {
81                 status = acpi_tb_verify_checksum(table, table->length);
82         }
83
84         if (ACPI_FAILURE(status)) {
85                 fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
86                         table->signature);
87         }
88
89         return (AE_OK);
90 }
91
92 /******************************************************************************
93  *
94  * FUNCTION:    ap_get_table_length
95  *
96  * PARAMETERS:  table               - Pointer to the table
97  *
98  * RETURN:      Table length
99  *
100  * DESCRIPTION: Obtain table length according to table signature.
101  *
102  ******************************************************************************/
103
104 u32 ap_get_table_length(struct acpi_table_header *table)
105 {
106         struct acpi_table_rsdp *rsdp;
107
108         /* Check if table is valid */
109
110         if (!ap_is_valid_header(table)) {
111                 return (0);
112         }
113
114         if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
115                 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
116                 return (acpi_tb_get_rsdp_length(rsdp));
117         }
118
119         /* Normal ACPI table */
120
121         return (table->length);
122 }
123
124 /******************************************************************************
125  *
126  * FUNCTION:    ap_dump_table_buffer
127  *
128  * PARAMETERS:  table               - ACPI table to be dumped
129  *              instance            - ACPI table instance no. to be dumped
130  *              address             - Physical address of the table
131  *
132  * RETURN:      None
133  *
134  * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
135  *              header that is compatible with the acpi_xtract utility.
136  *
137  ******************************************************************************/
138
139 static int
140 ap_dump_table_buffer(struct acpi_table_header *table,
141                      u32 instance, acpi_physical_address address)
142 {
143         u32 table_length;
144
145         table_length = ap_get_table_length(table);
146
147         /* Print only the header if requested */
148
149         if (gbl_summary_mode) {
150                 acpi_tb_print_table_header(address, table);
151                 return (0);
152         }
153
154         /* Dump to binary file if requested */
155
156         if (gbl_binary_mode) {
157                 return (ap_write_to_binary_file(table, instance));
158         }
159
160         /*
161          * Dump the table with header for use with acpixtract utility.
162          * Note: simplest to just always emit a 64-bit address. acpi_xtract
163          * utility can handle this.
164          */
165         fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
166                 table->signature, ACPI_FORMAT_UINT64(address));
167
168         acpi_ut_dump_buffer_to_file(gbl_output_file,
169                                     ACPI_CAST_PTR(u8, table), table_length,
170                                     DB_BYTE_DISPLAY, 0);
171         fprintf(gbl_output_file, "\n");
172         return (0);
173 }
174
175 /******************************************************************************
176  *
177  * FUNCTION:    ap_dump_all_tables
178  *
179  * PARAMETERS:  None
180  *
181  * RETURN:      Status
182  *
183  * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
184  *              tables that we can possibly get).
185  *
186  ******************************************************************************/
187
188 int ap_dump_all_tables(void)
189 {
190         struct acpi_table_header *table;
191         u32 instance = 0;
192         acpi_physical_address address;
193         acpi_status status;
194         int table_status;
195         u32 i;
196
197         /* Get and dump all available ACPI tables */
198
199         for (i = 0; i < AP_MAX_ACPI_FILES; i++) {
200                 status =
201                     acpi_os_get_table_by_index(i, &table, &instance, &address);
202                 if (ACPI_FAILURE(status)) {
203
204                         /* AE_LIMIT means that no more tables are available */
205
206                         if (status == AE_LIMIT) {
207                                 return (0);
208                         } else if (i == 0) {
209                                 fprintf(stderr,
210                                         "Could not get ACPI tables, %s\n",
211                                         acpi_format_exception(status));
212                                 return (-1);
213                         } else {
214                                 fprintf(stderr,
215                                         "Could not get ACPI table at index %u, %s\n",
216                                         i, acpi_format_exception(status));
217                                 continue;
218                         }
219                 }
220
221                 table_status = ap_dump_table_buffer(table, instance, address);
222                 ACPI_FREE(table);
223
224                 if (table_status) {
225                         break;
226                 }
227         }
228
229         /* Something seriously bad happened if the loop terminates here */
230
231         return (-1);
232 }
233
234 /******************************************************************************
235  *
236  * FUNCTION:    ap_dump_table_by_address
237  *
238  * PARAMETERS:  ascii_address       - Address for requested ACPI table
239  *
240  * RETURN:      Status
241  *
242  * DESCRIPTION: Get an ACPI table via a physical address and dump it.
243  *
244  ******************************************************************************/
245
246 int ap_dump_table_by_address(char *ascii_address)
247 {
248         acpi_physical_address address;
249         struct acpi_table_header *table;
250         acpi_status status;
251         int table_status;
252         u64 long_address;
253
254         /* Convert argument to an integer physical address */
255
256         status = acpi_ut_strtoul64(ascii_address, &long_address);
257         if (ACPI_FAILURE(status)) {
258                 fprintf(stderr, "%s: Could not convert to a physical address\n",
259                         ascii_address);
260                 return (-1);
261         }
262
263         address = (acpi_physical_address)long_address;
264         status = acpi_os_get_table_by_address(address, &table);
265         if (ACPI_FAILURE(status)) {
266                 fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
267                         ACPI_FORMAT_UINT64(address),
268                         acpi_format_exception(status));
269                 return (-1);
270         }
271
272         table_status = ap_dump_table_buffer(table, 0, address);
273         ACPI_FREE(table);
274         return (table_status);
275 }
276
277 /******************************************************************************
278  *
279  * FUNCTION:    ap_dump_table_by_name
280  *
281  * PARAMETERS:  signature           - Requested ACPI table signature
282  *
283  * RETURN:      Status
284  *
285  * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
286  *              multiple tables with the same signature (SSDTs).
287  *
288  ******************************************************************************/
289
290 int ap_dump_table_by_name(char *signature)
291 {
292         char local_signature[ACPI_NAME_SIZE + 1];
293         u32 instance;
294         struct acpi_table_header *table;
295         acpi_physical_address address;
296         acpi_status status;
297         int table_status;
298
299         if (strlen(signature) != ACPI_NAME_SIZE) {
300                 fprintf(stderr,
301                         "Invalid table signature [%s]: must be exactly 4 characters\n",
302                         signature);
303                 return (-1);
304         }
305
306         /* Table signatures are expected to be uppercase */
307
308         strcpy(local_signature, signature);
309         acpi_ut_strupr(local_signature);
310
311         /* To be friendly, handle tables whose signatures do not match the name */
312
313         if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
314                 strcpy(local_signature, ACPI_SIG_FADT);
315         } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
316                 strcpy(local_signature, ACPI_SIG_MADT);
317         }
318
319         /* Dump all instances of this signature (to handle multiple SSDTs) */
320
321         for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) {
322                 status = acpi_os_get_table_by_name(local_signature, instance,
323                                                    &table, &address);
324                 if (ACPI_FAILURE(status)) {
325
326                         /* AE_LIMIT means that no more tables are available */
327
328                         if (status == AE_LIMIT) {
329                                 return (0);
330                         }
331
332                         fprintf(stderr,
333                                 "Could not get ACPI table with signature [%s], %s\n",
334                                 local_signature, acpi_format_exception(status));
335                         return (-1);
336                 }
337
338                 table_status = ap_dump_table_buffer(table, instance, address);
339                 ACPI_FREE(table);
340
341                 if (table_status) {
342                         break;
343                 }
344         }
345
346         /* Something seriously bad happened if the loop terminates here */
347
348         return (-1);
349 }
350
351 /******************************************************************************
352  *
353  * FUNCTION:    ap_dump_table_from_file
354  *
355  * PARAMETERS:  pathname            - File containing the binary ACPI table
356  *
357  * RETURN:      Status
358  *
359  * DESCRIPTION: Dump an ACPI table from a binary file
360  *
361  ******************************************************************************/
362
363 int ap_dump_table_from_file(char *pathname)
364 {
365         struct acpi_table_header *table;
366         u32 file_size = 0;
367         int table_status = -1;
368
369         /* Get the entire ACPI table from the file */
370
371         table = ap_get_table_from_file(pathname, &file_size);
372         if (!table) {
373                 return (-1);
374         }
375
376         if (!acpi_ut_valid_nameseg(table->signature)) {
377                 fprintf(stderr,
378                         "No valid ACPI signature was found in input file %s\n",
379                         pathname);
380         }
381
382         /* File must be at least as long as the table length */
383
384         if (table->length > file_size) {
385                 fprintf(stderr,
386                         "Table length (0x%X) is too large for input file (0x%X) %s\n",
387                         table->length, file_size, pathname);
388                 goto exit;
389         }
390
391         if (gbl_verbose_mode) {
392                 fprintf(stderr,
393                         "Input file:  %s contains table [%4.4s], 0x%X (%u) bytes\n",
394                         pathname, table->signature, file_size, file_size);
395         }
396
397         table_status = ap_dump_table_buffer(table, 0, 0);
398
399 exit:
400         ACPI_FREE(table);
401         return (table_status);
402 }