Merge tag 'nfs-for-3.20-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs
[linux-2.6-block.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/*
82a80941 8 * Copyright (C) 2000 - 2015, 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
71 if (!acpi_ut_valid_acpi_name(table->signature)) {
dcaff16d
LZ
72 acpi_log_error("Table signature (0x%8.8X) is invalid\n",
73 *(u32 *)table->signature);
506f57dd
LZ
74 return (FALSE);
75 }
76
77 /* Check for minimum table length */
78
79 if (table->length < sizeof(struct acpi_table_header)) {
dcaff16d
LZ
80 acpi_log_error("Table length (0x%8.8X) is invalid\n",
81 table->length);
506f57dd
LZ
82 return (FALSE);
83 }
84 }
85
86 return (TRUE);
87}
88
89/******************************************************************************
90 *
91 * FUNCTION: ap_is_valid_checksum
92 *
93 * PARAMETERS: table - Pointer to table to be validated
94 *
95 * RETURN: TRUE if the checksum appears to be valid. FALSE otherwise.
96 *
97 * DESCRIPTION: Check for a valid ACPI table checksum.
98 *
99 ******************************************************************************/
100
101u8 ap_is_valid_checksum(struct acpi_table_header *table)
102{
103 acpi_status status;
104 struct acpi_table_rsdp *rsdp;
105
106 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
107 /*
108 * Checksum for RSDP.
109 * Note: Other checksums are computed during the table dump.
110 */
111 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
112 status = acpi_tb_validate_rsdp(rsdp);
113 } else {
114 status = acpi_tb_verify_checksum(table, table->length);
115 }
116
117 if (ACPI_FAILURE(status)) {
dcaff16d
LZ
118 acpi_log_error("%4.4s: Warning: wrong checksum in table\n",
119 table->signature);
506f57dd
LZ
120 }
121
122 return (AE_OK);
123}
124
125/******************************************************************************
126 *
127 * FUNCTION: ap_get_table_length
128 *
129 * PARAMETERS: table - Pointer to the table
130 *
131 * RETURN: Table length
132 *
133 * DESCRIPTION: Obtain table length according to table signature.
134 *
135 ******************************************************************************/
136
137u32 ap_get_table_length(struct acpi_table_header *table)
138{
139 struct acpi_table_rsdp *rsdp;
140
141 /* Check if table is valid */
142
143 if (!ap_is_valid_header(table)) {
144 return (0);
145 }
146
147 if (ACPI_VALIDATE_RSDP_SIG(table->signature)) {
148 rsdp = ACPI_CAST_PTR(struct acpi_table_rsdp, table);
f1b69752 149 return (acpi_tb_get_rsdp_length(rsdp));
506f57dd
LZ
150 }
151
152 /* Normal ACPI table */
153
154 return (table->length);
155}
156
157/******************************************************************************
158 *
159 * FUNCTION: ap_dump_table_buffer
160 *
161 * PARAMETERS: table - ACPI table to be dumped
162 * instance - ACPI table instance no. to be dumped
163 * address - Physical address of the table
164 *
165 * RETURN: None
166 *
167 * DESCRIPTION: Dump an ACPI table in standard ASCII hex format, with a
168 * header that is compatible with the acpi_xtract utility.
169 *
170 ******************************************************************************/
171
172static int
173ap_dump_table_buffer(struct acpi_table_header *table,
174 u32 instance, acpi_physical_address address)
175{
176 u32 table_length;
177
178 table_length = ap_get_table_length(table);
179
180 /* Print only the header if requested */
181
182 if (gbl_summary_mode) {
183 acpi_tb_print_table_header(address, table);
184 return (0);
185 }
186
187 /* Dump to binary file if requested */
188
189 if (gbl_binary_mode) {
190 return (ap_write_to_binary_file(table, instance));
191 }
192
193 /*
194 * Dump the table with header for use with acpixtract utility.
195 * Note: simplest to just always emit a 64-bit address. acpi_xtract
196 * utility can handle this.
197 */
846d6ef4
LZ
198 acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
199 table->signature, ACPI_FORMAT_UINT64(address));
506f57dd 200
846d6ef4
LZ
201 acpi_ut_dump_buffer_to_file(gbl_output_file,
202 ACPI_CAST_PTR(u8, table), table_length,
203 DB_BYTE_DISPLAY, 0);
204 acpi_ut_file_printf(gbl_output_file, "\n");
506f57dd
LZ
205 return (0);
206}
207
208/******************************************************************************
209 *
210 * FUNCTION: ap_dump_all_tables
211 *
212 * PARAMETERS: None
213 *
214 * RETURN: Status
215 *
216 * DESCRIPTION: Get all tables from the RSDT/XSDT (or at least all of the
217 * tables that we can possibly get).
218 *
219 ******************************************************************************/
220
221int ap_dump_all_tables(void)
222{
223 struct acpi_table_header *table;
224 u32 instance = 0;
225 acpi_physical_address address;
226 acpi_status status;
227 int table_status;
228 u32 i;
229
230 /* Get and dump all available ACPI tables */
231
232 for (i = 0; i < AP_MAX_ACPI_FILES; i++) {
233 status =
234 acpi_os_get_table_by_index(i, &table, &instance, &address);
235 if (ACPI_FAILURE(status)) {
236
237 /* AE_LIMIT means that no more tables are available */
238
239 if (status == AE_LIMIT) {
240 return (0);
241 } else if (i == 0) {
dcaff16d
LZ
242 acpi_log_error
243 ("Could not get ACPI tables, %s\n",
244 acpi_format_exception(status));
506f57dd
LZ
245 return (-1);
246 } else {
dcaff16d
LZ
247 acpi_log_error
248 ("Could not get ACPI table at index %u, %s\n",
249 i, acpi_format_exception(status));
506f57dd
LZ
250 continue;
251 }
252 }
253
254 table_status = ap_dump_table_buffer(table, instance, address);
fbee6b21 255 ACPI_FREE(table);
506f57dd
LZ
256
257 if (table_status) {
258 break;
259 }
260 }
261
262 /* Something seriously bad happened if the loop terminates here */
263
264 return (-1);
265}
266
267/******************************************************************************
268 *
269 * FUNCTION: ap_dump_table_by_address
270 *
271 * PARAMETERS: ascii_address - Address for requested ACPI table
272 *
273 * RETURN: Status
274 *
275 * DESCRIPTION: Get an ACPI table via a physical address and dump it.
276 *
277 ******************************************************************************/
278
279int ap_dump_table_by_address(char *ascii_address)
280{
281 acpi_physical_address address;
282 struct acpi_table_header *table;
283 acpi_status status;
284 int table_status;
285 u64 long_address;
286
287 /* Convert argument to an integer physical address */
288
289 status = acpi_ut_strtoul64(ascii_address, 0, &long_address);
290 if (ACPI_FAILURE(status)) {
dcaff16d
LZ
291 acpi_log_error("%s: Could not convert to a physical address\n",
292 ascii_address);
506f57dd
LZ
293 return (-1);
294 }
295
296 address = (acpi_physical_address) long_address;
297 status = acpi_os_get_table_by_address(address, &table);
298 if (ACPI_FAILURE(status)) {
dcaff16d
LZ
299 acpi_log_error("Could not get table at 0x%8.8X%8.8X, %s\n",
300 ACPI_FORMAT_UINT64(address),
301 acpi_format_exception(status));
506f57dd
LZ
302 return (-1);
303 }
304
305 table_status = ap_dump_table_buffer(table, 0, address);
fbee6b21 306 ACPI_FREE(table);
506f57dd
LZ
307 return (table_status);
308}
309
310/******************************************************************************
311 *
312 * FUNCTION: ap_dump_table_by_name
313 *
314 * PARAMETERS: signature - Requested ACPI table signature
315 *
316 * RETURN: Status
317 *
318 * DESCRIPTION: Get an ACPI table via a signature and dump it. Handles
319 * multiple tables with the same signature (SSDTs).
320 *
321 ******************************************************************************/
322
323int ap_dump_table_by_name(char *signature)
324{
325 char local_signature[ACPI_NAME_SIZE + 1];
326 u32 instance;
327 struct acpi_table_header *table;
328 acpi_physical_address address;
329 acpi_status status;
330 int table_status;
331
fbee6b21 332 if (ACPI_STRLEN(signature) != ACPI_NAME_SIZE) {
dcaff16d
LZ
333 acpi_log_error
334 ("Invalid table signature [%s]: must be exactly 4 characters\n",
335 signature);
506f57dd
LZ
336 return (-1);
337 }
338
339 /* Table signatures are expected to be uppercase */
340
fbee6b21 341 ACPI_STRCPY(local_signature, signature);
506f57dd
LZ
342 acpi_ut_strupr(local_signature);
343
344 /* To be friendly, handle tables whose signatures do not match the name */
345
346 if (ACPI_COMPARE_NAME(local_signature, "FADT")) {
fbee6b21 347 ACPI_STRCPY(local_signature, ACPI_SIG_FADT);
506f57dd 348 } else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
fbee6b21 349 ACPI_STRCPY(local_signature, ACPI_SIG_MADT);
506f57dd
LZ
350 }
351
352 /* Dump all instances of this signature (to handle multiple SSDTs) */
353
354 for (instance = 0; instance < AP_MAX_ACPI_FILES; instance++) {
355 status = acpi_os_get_table_by_name(local_signature, instance,
356 &table, &address);
357 if (ACPI_FAILURE(status)) {
358
359 /* AE_LIMIT means that no more tables are available */
360
361 if (status == AE_LIMIT) {
362 return (0);
363 }
364
dcaff16d
LZ
365 acpi_log_error
366 ("Could not get ACPI table with signature [%s], %s\n",
367 local_signature, acpi_format_exception(status));
506f57dd
LZ
368 return (-1);
369 }
370
371 table_status = ap_dump_table_buffer(table, instance, address);
fbee6b21 372 ACPI_FREE(table);
506f57dd
LZ
373
374 if (table_status) {
375 break;
376 }
377 }
378
379 /* Something seriously bad happened if the loop terminates here */
380
381 return (-1);
382}
383
384/******************************************************************************
385 *
386 * FUNCTION: ap_dump_table_from_file
387 *
388 * PARAMETERS: pathname - File containing the binary ACPI table
389 *
390 * RETURN: Status
391 *
392 * DESCRIPTION: Dump an ACPI table from a binary file
393 *
394 ******************************************************************************/
395
396int ap_dump_table_from_file(char *pathname)
397{
398 struct acpi_table_header *table;
399 u32 file_size = 0;
400 int table_status = -1;
401
402 /* Get the entire ACPI table from the file */
403
404 table = ap_get_table_from_file(pathname, &file_size);
405 if (!table) {
406 return (-1);
407 }
408
409 /* File must be at least as long as the table length */
410
411 if (table->length > file_size) {
dcaff16d
LZ
412 acpi_log_error
413 ("Table length (0x%X) is too large for input file (0x%X) %s\n",
414 table->length, file_size, pathname);
506f57dd
LZ
415 goto exit;
416 }
417
418 if (gbl_verbose_mode) {
dcaff16d
LZ
419 acpi_log_error
420 ("Input file: %s contains table [%4.4s], 0x%X (%u) bytes\n",
421 pathname, table->signature, file_size, file_size);
506f57dd
LZ
422 }
423
424 table_status = ap_dump_table_buffer(table, 0, 0);
425
426exit:
fbee6b21 427 ACPI_FREE(table);
506f57dd
LZ
428 return (table_status);
429}