1 /******************************************************************************
2  *
3  * Module Name: apdump - Dump routines for ACPI tables (acpidump)
4  *
5  *****************************************************************************/
6 
7 /*
8  * Copyright (C) 2000 - 2015, Intel Corp.
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 
48 static int
49 ap_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 
ap_is_valid_header(struct acpi_table_header * table)64 u8 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)) {
72 			acpi_log_error("Table signature (0x%8.8X) is invalid\n",
73 				       *(u32 *)table->signature);
74 			return (FALSE);
75 		}
76 
77 		/* Check for minimum table length */
78 
79 		if (table->length < sizeof(struct acpi_table_header)) {
80 			acpi_log_error("Table length (0x%8.8X) is invalid\n",
81 				       table->length);
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 
ap_is_valid_checksum(struct acpi_table_header * table)101 u8 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)) {
118 		acpi_log_error("%4.4s: Warning: wrong checksum in table\n",
119 			       table->signature);
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 
ap_get_table_length(struct acpi_table_header * table)137 u32 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);
149 		return (acpi_tb_get_rsdp_length(rsdp));
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 
172 static int
ap_dump_table_buffer(struct acpi_table_header * table,u32 instance,acpi_physical_address address)173 ap_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 	 */
198 	acpi_ut_file_printf(gbl_output_file, "%4.4s @ 0x%8.8X%8.8X\n",
199 			    table->signature, ACPI_FORMAT_UINT64(address));
200 
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");
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 
ap_dump_all_tables(void)221 int 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) {
242 				acpi_log_error
243 				    ("Could not get ACPI tables, %s\n",
244 				     acpi_format_exception(status));
245 				return (-1);
246 			} else {
247 				acpi_log_error
248 				    ("Could not get ACPI table at index %u, %s\n",
249 				     i, acpi_format_exception(status));
250 				continue;
251 			}
252 		}
253 
254 		table_status = ap_dump_table_buffer(table, instance, address);
255 		ACPI_FREE(table);
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 
ap_dump_table_by_address(char * ascii_address)279 int 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)) {
291 		acpi_log_error("%s: Could not convert to a physical address\n",
292 			       ascii_address);
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)) {
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));
302 		return (-1);
303 	}
304 
305 	table_status = ap_dump_table_buffer(table, 0, address);
306 	ACPI_FREE(table);
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 
ap_dump_table_by_name(char * signature)323 int 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 
332 	if (ACPI_STRLEN(signature) != ACPI_NAME_SIZE) {
333 		acpi_log_error
334 		    ("Invalid table signature [%s]: must be exactly 4 characters\n",
335 		     signature);
336 		return (-1);
337 	}
338 
339 	/* Table signatures are expected to be uppercase */
340 
341 	ACPI_STRCPY(local_signature, signature);
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")) {
347 		ACPI_STRCPY(local_signature, ACPI_SIG_FADT);
348 	} else if (ACPI_COMPARE_NAME(local_signature, "MADT")) {
349 		ACPI_STRCPY(local_signature, ACPI_SIG_MADT);
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 
365 			acpi_log_error
366 			    ("Could not get ACPI table with signature [%s], %s\n",
367 			     local_signature, acpi_format_exception(status));
368 			return (-1);
369 		}
370 
371 		table_status = ap_dump_table_buffer(table, instance, address);
372 		ACPI_FREE(table);
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 
ap_dump_table_from_file(char * pathname)396 int 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) {
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);
415 		goto exit;
416 	}
417 
418 	if (gbl_verbose_mode) {
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);
422 	}
423 
424 	table_status = ap_dump_table_buffer(table, 0, 0);
425 
426 exit:
427 	ACPI_FREE(table);
428 	return (table_status);
429 }
430