]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blame - tools/power/acpi/tools/acpidump/apdump.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / tools / power / acpi / tools / acpidump / apdump.c
CommitLineData
506f57dd
LZ
1/******************************************************************************
2 *
3 * Module Name: apdump - Dump routines for ACPI tables (acpidump)
4 *
5 *****************************************************************************/
6
7/*
7735ca0e 8 * Copyright (C) 2000 - 2017, Intel Corp.
506f57dd
LZ
9 * All rights reserved.
10 *
11 * Redistribution and use in source and binary forms, with or without
12 * modification, are permitted provided that the following conditions
13 * are met:
14 * 1. Redistributions of source code must retain the above copyright
15 * notice, this list of conditions, and the following disclaimer,
16 * without modification.
17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
18 * substantially similar to the "NO WARRANTY" disclaimer below
19 * ("Disclaimer") and any redistribution must be conditioned upon
20 * including a substantially similar Disclaimer requirement for further
21 * binary redistribution.
22 * 3. Neither the names of the above-listed copyright holders nor the names
23 * of any contributors may be used to endorse or promote products derived
24 * from this software without specific prior written permission.
25 *
26 * Alternatively, this software may be distributed under the terms of the
27 * GNU General Public License ("GPL") version 2 as published by the Free
28 * Software Foundation.
29 *
30 * NO WARRANTY
31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
41 * POSSIBILITY OF SUCH DAMAGES.
42 */
43
44#include "acpidump.h"
45
46/* Local prototypes */
47
48static int
49ap_dump_table_buffer(struct acpi_table_header *table,
50 u32 instance, acpi_physical_address address);
51
52/******************************************************************************
53 *
54 * FUNCTION: ap_is_valid_header
55 *
56 * PARAMETERS: table - Pointer to table to be validated
57 *
58 * RETURN: TRUE if the header appears to be valid. FALSE otherwise
59 *
60 * DESCRIPTION: Check for a valid ACPI table header
61 *
62 ******************************************************************************/
63
64u8 ap_is_valid_header(struct acpi_table_header *table)
65{
66
67 if (!ACPI_VALIDATE_RSDP_SIG(table->signature)) {
68
69 /* Make sure signature is all ASCII and a valid ACPI name */
70
6a0df32c 71 if (!acpi_ut_valid_nameseg(table->signature)) {
dd99cbcc
LZ
72 fprintf(stderr,
73 "Table signature (0x%8.8X) is invalid\n",
74 *(u32 *)table->signature);
506f57dd
LZ
75 return (FALSE);
76 }
77
78 /* Check for minimum table length */
79
80 if (table->length < sizeof(struct acpi_table_header)) {
dd99cbcc
LZ
81 fprintf(stderr, "Table length (0x%8.8X) is invalid\n",
82 table->length);
506f57dd
LZ
83 return (FALSE);
84 }
85 }
86
87 return (TRUE);
88}
89
90/******************************************************************************
91 *
92 * FUNCTION: ap_is_valid_checksum
93 *
94 * PARAMETERS: table - Pointer to table to be validated
95 *
96 * RETURN: TRUE if the checksum appears to be valid. FALSE otherwise.
97 *
98 * DESCRIPTION: Check for a valid ACPI table checksum.
99 *
100 ******************************************************************************/
101
102u8 ap_is_valid_checksum(struct acpi_table_header *table)
103{
104 acpi_status status;
105 struct acpi_table_rsdp *rsdp;
106
107 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
108 /*
109 * Checksum for RSDP.
110 * Note: Other checksums are computed during the table dump.
111 */
112 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
113 status = acpi_tb_validate_rsdp(rsdp);
114 } else {
115 status = acpi_tb_verify_checksum(table, table->length);
116 }
117
118 if (ACPI_FAILURE(status)) {
dd99cbcc
LZ
119 fprintf(stderr, "%4.4s: Warning: wrong checksum in table\n",
120 table->signature);
506f57dd
LZ
121 }
122
123 return (AE_OK);
124}
125
126/******************************************************************************
127 *
128 * FUNCTION: ap_get_table_length
129 *
130 * PARAMETERS: table - Pointer to the table
131 *
132 * RETURN: Table length
133 *
134 * DESCRIPTION: Obtain table length according to table signature.
135 *
136 ******************************************************************************/
137
138u32 ap_get_table_length(struct acpi_table_header *table)
139{
140 struct acpi_table_rsdp *rsdp;
141
142 /* Check if table is valid */
143
144 if (!ap_is_valid_header(table)) {
145 return (0);
146 }
147
148 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
149 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
f1b69752 150 return (acpi_tb_get_rsdp_length(rsdp));
506f57dd
LZ
151 }
152
153 /* Normal ACPI table */
154
155 return (table->length);
156}
157
158/******************************************************************************
159 *
160 * FUNCTION: ap_dump_table_buffer
161 *
162 * PARAMETERS: table - ACPI table to be dumped
163 * instance - ACPI table instance no. to be dumped
164 * address - Physical address of the table
165 *
166 * RETURN: None
167 *
168 * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
169 * header that is compatible with the acpi_xtract utility.
170 *
171 ******************************************************************************/
172
173static int
174ap_dump_table_buffer(struct acpi_table_header *table,
175 u32 instance, acpi_physical_address address)
176{
177 u32 table_length;
178
179 table_length = ap_get_table_length(table);
180
181 /* Print only the header if requested */
182
183 if (gbl_summary_mode) {
184 acpi_tb_print_table_header(address, table);
185 return (0);
186 }
187
188 /* Dump to binary file if requested */
189
190 if (gbl_binary_mode) {
191 return (ap_write_to_binary_file(table, instance));
192 }
193
194 /*
195 * Dump the table with header for use with acpixtract utility.
196 * Note: simplest to just always emit a 64-bit address. acpi_xtract
197 * utility can handle this.
198 */
f173a775
LZ
199 fprintf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
200 table->signature, ACPI_FORMAT_UINT64(address));
506f57dd 201
846d6ef4
LZ
202 acpi_ut_dump_buffer_to_file(gbl_output_file,
203 ACPI_CAST_PTR(u8, table), table_length,
204 DB_BYTE_DISPLAY, 0);
f173a775 205 fprintf(gbl_output_file, "\n");
506f57dd
LZ
206 return (0);
207}
208
209/******************************************************************************
210 *
211 * FUNCTION: ap_dump_all_tables
212 *
213 * PARAMETERS: None
214 *
215 * RETURN: Status
216 *
217 * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
218 * tables that we can possibly get).
219 *
220 ******************************************************************************/
221
222int ap_dump_all_tables(void)
223{
224 struct acpi_table_header *table;
225 u32 instance = 0;
226 acpi_physical_address address;
227 acpi_status status;
228 int table_status;
229 u32 i;
230
231 /* Get and dump all available ACPI tables */
232
233 for (i = 0; i < AP_MAX_ACPI_FILES; i++) {
234 status =
235 acpi_os_get_table_by_index(i, &table, &instance, &address);
236 if (ACPI_FAILURE(status)) {
237
238 /* AE_LIMIT means that no more tables are available */
239
240 if (status == AE_LIMIT) {
241 return (0);
242 } else if (i == 0) {
dd99cbcc
LZ
243 fprintf(stderr,
244 "Could not get ACPI tables, %s\n",
245 acpi_format_exception(status));
506f57dd
LZ
246 return (-1);
247 } else {
dd99cbcc
LZ
248 fprintf(stderr,
249 "Could not get ACPI table at index %u, %s\n",
250 i, acpi_format_exception(status));
506f57dd
LZ
251 continue;
252 }
253 }
254
255 table_status = ap_dump_table_buffer(table, instance, address);
fbee6b21 256 ACPI_FREE(table);
506f57dd
LZ
257
258 if (table_status) {
259 break;
260 }
261 }
262
263 /* Something seriously bad happened if the loop terminates here */
264
265 return (-1);
266}
267
268/******************************************************************************
269 *
270 * FUNCTION: ap_dump_table_by_address
271 *
272 * PARAMETERS: ascii_address - Address for requested ACPI table
273 *
274 * RETURN: Status
275 *
276 * DESCRIPTION: Get an ACPI table via a physical address and dump it.
277 *
278 ******************************************************************************/
279
280int ap_dump_table_by_address(char *ascii_address)
281{
282 acpi_physical_address address;
283 struct acpi_table_header *table;
284 acpi_status status;
285 int table_status;
286 u64 long_address;
287
288 /* Convert argument to an integer physical address */
289
5ebd2eaa
BM
290 status = acpi_ut_strtoul64(ascii_address, ACPI_STRTOUL_64BIT,
291 &long_address);
506f57dd 292 if (ACPI_FAILURE(status)) {
dd99cbcc
LZ
293 fprintf(stderr, "%s: Could not convert to a physical address\n",
294 ascii_address);
506f57dd
LZ
295 return (-1);
296 }
297
f5c1e1c5 298 address = (acpi_physical_address)long_address;
506f57dd
LZ
299 status = acpi_os_get_table_by_address(address, &table);
300 if (ACPI_FAILURE(status)) {
dd99cbcc
LZ
301 fprintf(stderr, "Could not get table at 0x%8.8X%8.8X, %s\n",
302 ACPI_FORMAT_UINT64(address),
303 acpi_format_exception(status));
506f57dd
LZ
304 return (-1);
305 }
306
307 table_status = ap_dump_table_buffer(table, 0, address);
fbee6b21 308 ACPI_FREE(table);
506f57dd
LZ
309 return (table_status);
310}
311
312/******************************************************************************
313 *
314 * FUNCTION: ap_dump_table_by_name
315 *
316 * PARAMETERS: signature - Requested ACPI table signature
317 *
318 * RETURN: Status
319 *
320 * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
321 * multiple tables with the same signature (SSDTs).
322 *
323 ******************************************************************************/
324
325int ap_dump_table_by_name(char *signature)
326{
327 char local_signature[ACPI_NAME_SIZE + 1];
328 u32 instance;
329 struct acpi_table_header *table;
330 acpi_physical_address address;
331 acpi_status status;
332 int table_status;
333
4fa4616e 334 if (strlen(signature) != ACPI_NAME_SIZE) {
dd99cbcc
LZ
335 fprintf(stderr,
336 "Invalid table signature [%s]: must be exactly 4 characters\n",
337 signature);
506f57dd
LZ
338 return (-1);
339 }
340
341 /* Table signatures are expected to be uppercase */
342
4fa4616e 343 strcpy(local_signature, signature);
506f57dd
LZ
344 acpi_ut_strupr(local_signature);
345
346 /* To be friendly, handle tables whose signatures do not match the name */
347
348 if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
4fa4616e 349 strcpy(local_signature, ACPI_SIG_FADT);
506f57dd 350 } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
4fa4616e 351 strcpy(local_signature, ACPI_SIG_MADT);
506f57dd
LZ
352 }
353
354 /* Dump all instances of this signature (to handle multiple SSDTs) */
355
356 for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) {
357 status = acpi_os_get_table_by_name(local_signature, instance,
358 &table, &address);
359 if (ACPI_FAILURE(status)) {
360
361 /* AE_LIMIT means that no more tables are available */
362
363 if (status == AE_LIMIT) {
364 return (0);
365 }
366
dd99cbcc
LZ
367 fprintf(stderr,
368 "Could not get ACPI table with signature [%s], %s\n",
369 local_signature, acpi_format_exception(status));
506f57dd
LZ
370 return (-1);
371 }
372
373 table_status = ap_dump_table_buffer(table, instance, address);
fbee6b21 374 ACPI_FREE(table);
506f57dd
LZ
375
376 if (table_status) {
377 break;
378 }
379 }
380
381 /* Something seriously bad happened if the loop terminates here */
382
383 return (-1);
384}
385
386/******************************************************************************
387 *
388 * FUNCTION: ap_dump_table_from_file
389 *
390 * PARAMETERS: pathname - File containing the binary ACPI table
391 *
392 * RETURN: Status
393 *
394 * DESCRIPTION: Dump an ACPI table from a binary file
395 *
396 ******************************************************************************/
397
398int ap_dump_table_from_file(char *pathname)
399{
400 struct acpi_table_header *table;
401 u32 file_size = 0;
402 int table_status = -1;
403
404 /* Get the entire ACPI table from the file */
405
406 table = ap_get_table_from_file(pathname, &file_size);
407 if (!table) {
408 return (-1);
409 }
410
6a0df32c 411 if (!acpi_ut_valid_nameseg(table->signature)) {
dd99cbcc
LZ
412 fprintf(stderr,
413 "No valid ACPI signature was found in input file %s\n",
414 pathname);
6a0df32c
BM
415 }
416
506f57dd
LZ
417 /* File must be at least as long as the table length */
418
419 if (table->length > file_size) {
dd99cbcc
LZ
420 fprintf(stderr,
421 "Table length (0x%X) is too large for input file (0x%X) %s\n",
422 table->length, file_size, pathname);
506f57dd
LZ
423 goto exit;
424 }
425
426 if (gbl_verbose_mode) {
dd99cbcc
LZ
427 fprintf(stderr,
428 "Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
429 pathname, table->signature, file_size, file_size);
506f57dd
LZ
430 }
431
432 table_status = ap_dump_table_buffer(table, 0, 0);
433
434exit:
fbee6b21 435 ACPI_FREE(table);
506f57dd
LZ
436 return (table_status);
437}