root/tools/power/acpi/tools/acpidump/apdump.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. ap_is_valid_header
  2. ap_is_valid_checksum
  3. ap_get_table_length
  4. ap_dump_table_buffer
  5. ap_dump_all_tables
  6. ap_dump_table_by_address
  7. ap_dump_table_by_name
  8. ap_dump_table_from_file

   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 - 2019, 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_NAMESEG_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_NAMESEG_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_NAMESEG(local_signature, "FADT")) {
 314                 strcpy(local_signature, ACPI_SIG_FADT);
 315         } else if (ACPI_COMPARE_NAMESEG(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 }

/* [<][>][^][v][top][bottom][index][help] */