linux/drivers/acpi/acpica/tbprint.c
<<
>>
Prefs
   1/******************************************************************************
   2 *
   3 * Module Name: tbprint - Table output utilities
   4 *
   5 *****************************************************************************/
   6
   7/*
   8 * Copyright (C) 2000 - 2014, 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 <acpi/acpi.h>
  45#include "accommon.h"
  46#include "actables.h"
  47
  48#define _COMPONENT          ACPI_TABLES
  49ACPI_MODULE_NAME("tbprint")
  50
  51/* Local prototypes */
  52static void acpi_tb_fix_string(char *string, acpi_size length);
  53
  54static void
  55acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
  56                             struct acpi_table_header *header);
  57
  58/*******************************************************************************
  59 *
  60 * FUNCTION:    acpi_tb_fix_string
  61 *
  62 * PARAMETERS:  string              - String to be repaired
  63 *              length              - Maximum length
  64 *
  65 * RETURN:      None
  66 *
  67 * DESCRIPTION: Replace every non-printable or non-ascii byte in the string
  68 *              with a question mark '?'.
  69 *
  70 ******************************************************************************/
  71
  72static void acpi_tb_fix_string(char *string, acpi_size length)
  73{
  74
  75        while (length && *string) {
  76                if (!ACPI_IS_PRINT(*string)) {
  77                        *string = '?';
  78                }
  79                string++;
  80                length--;
  81        }
  82}
  83
  84/*******************************************************************************
  85 *
  86 * FUNCTION:    acpi_tb_cleanup_table_header
  87 *
  88 * PARAMETERS:  out_header          - Where the cleaned header is returned
  89 *              header              - Input ACPI table header
  90 *
  91 * RETURN:      Returns the cleaned header in out_header
  92 *
  93 * DESCRIPTION: Copy the table header and ensure that all "string" fields in
  94 *              the header consist of printable characters.
  95 *
  96 ******************************************************************************/
  97
  98static void
  99acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
 100                             struct acpi_table_header *header)
 101{
 102
 103        ACPI_MEMCPY(out_header, header, sizeof(struct acpi_table_header));
 104
 105        acpi_tb_fix_string(out_header->signature, ACPI_NAME_SIZE);
 106        acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE);
 107        acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
 108        acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAME_SIZE);
 109}
 110
 111/*******************************************************************************
 112 *
 113 * FUNCTION:    acpi_tb_print_table_header
 114 *
 115 * PARAMETERS:  address             - Table physical address
 116 *              header              - Table header
 117 *
 118 * RETURN:      None
 119 *
 120 * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP.
 121 *
 122 ******************************************************************************/
 123
 124void
 125acpi_tb_print_table_header(acpi_physical_address address,
 126                           struct acpi_table_header *header)
 127{
 128        struct acpi_table_header local_header;
 129
 130        /*
 131         * The reason that we use ACPI_PRINTF_UINT and ACPI_FORMAT_TO_UINT is to
 132         * support both 32-bit and 64-bit hosts/addresses in a consistent manner.
 133         * The %p specifier does not emit uniform output on all hosts. On some,
 134         * leading zeros are not supported.
 135         */
 136        if (ACPI_COMPARE_NAME(header->signature, ACPI_SIG_FACS)) {
 137
 138                /* FACS only has signature and length fields */
 139
 140                ACPI_INFO((AE_INFO, "%-4.4s " ACPI_PRINTF_UINT " %06X",
 141                           header->signature, ACPI_FORMAT_TO_UINT(address),
 142                           header->length));
 143        } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 144
 145                /* RSDP has no common fields */
 146
 147                ACPI_MEMCPY(local_header.oem_id,
 148                            ACPI_CAST_PTR(struct acpi_table_rsdp,
 149                                          header)->oem_id, ACPI_OEM_ID_SIZE);
 150                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 151
 152                ACPI_INFO((AE_INFO,
 153                           "RSDP " ACPI_PRINTF_UINT " %06X (v%.2d %-6.6s)",
 154                           ACPI_FORMAT_TO_UINT(address),
 155                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
 156                            revision >
 157                            0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
 158                                               header)->length : 20,
 159                           ACPI_CAST_PTR(struct acpi_table_rsdp,
 160                                         header)->revision,
 161                           local_header.oem_id));
 162        } else {
 163                /* Standard ACPI table with full common header */
 164
 165                acpi_tb_cleanup_table_header(&local_header, header);
 166
 167                ACPI_INFO((AE_INFO,
 168                           "%-4.4s " ACPI_PRINTF_UINT
 169                           " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
 170                           local_header.signature, ACPI_FORMAT_TO_UINT(address),
 171                           local_header.length, local_header.revision,
 172                           local_header.oem_id, local_header.oem_table_id,
 173                           local_header.oem_revision,
 174                           local_header.asl_compiler_id,
 175                           local_header.asl_compiler_revision));
 176        }
 177}
 178
 179/*******************************************************************************
 180 *
 181 * FUNCTION:    acpi_tb_validate_checksum
 182 *
 183 * PARAMETERS:  table               - ACPI table to verify
 184 *              length              - Length of entire table
 185 *
 186 * RETURN:      Status
 187 *
 188 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
 189 *              exception on bad checksum.
 190 *
 191 ******************************************************************************/
 192
 193acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
 194{
 195        u8 checksum;
 196
 197        /*
 198         * FACS/S3PT:
 199         * They are the odd tables, have no standard ACPI header and no checksum
 200         */
 201
 202        if (ACPI_COMPARE_NAME(table->signature, ACPI_SIG_S3PT) ||
 203            ACPI_COMPARE_NAME(table->signature, ACPI_SIG_FACS)) {
 204                return (AE_OK);
 205        }
 206
 207        /* Compute the checksum on the table */
 208
 209        checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
 210
 211        /* Checksum ok? (should be zero) */
 212
 213        if (checksum) {
 214                ACPI_BIOS_WARNING((AE_INFO,
 215                                   "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
 216                                   "should be 0x%2.2X",
 217                                   table->signature, table->checksum,
 218                                   (u8)(table->checksum - checksum)));
 219
 220#if (ACPI_CHECKSUM_ABORT)
 221                return (AE_BAD_CHECKSUM);
 222#endif
 223        }
 224
 225        return (AE_OK);
 226}
 227
 228/*******************************************************************************
 229 *
 230 * FUNCTION:    acpi_tb_checksum
 231 *
 232 * PARAMETERS:  buffer          - Pointer to memory region to be checked
 233 *              length          - Length of this memory region
 234 *
 235 * RETURN:      Checksum (u8)
 236 *
 237 * DESCRIPTION: Calculates circular checksum of memory region.
 238 *
 239 ******************************************************************************/
 240
 241u8 acpi_tb_checksum(u8 *buffer, u32 length)
 242{
 243        u8 sum = 0;
 244        u8 *end = buffer + length;
 245
 246        while (buffer < end) {
 247                sum = (u8)(sum + *(buffer++));
 248        }
 249
 250        return (sum);
 251}
 252