linux/drivers/acpi/acpica/tbprint.c
<<
>>
Prefs
   1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
   2/******************************************************************************
   3 *
   4 * Module Name: tbprint - Table output utilities
   5 *
   6 * Copyright (C) 2000 - 2020, Intel Corp.
   7 *
   8 *****************************************************************************/
   9
  10#include <acpi/acpi.h>
  11#include "accommon.h"
  12#include "actables.h"
  13
  14#define _COMPONENT          ACPI_TABLES
  15ACPI_MODULE_NAME("tbprint")
  16
  17/* Local prototypes */
  18static void acpi_tb_fix_string(char *string, acpi_size length);
  19
  20static void
  21acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
  22                             struct acpi_table_header *header);
  23
  24/*******************************************************************************
  25 *
  26 * FUNCTION:    acpi_tb_fix_string
  27 *
  28 * PARAMETERS:  string              - String to be repaired
  29 *              length              - Maximum length
  30 *
  31 * RETURN:      None
  32 *
  33 * DESCRIPTION: Replace every non-printable or non-ascii byte in the string
  34 *              with a question mark '?'.
  35 *
  36 ******************************************************************************/
  37
  38static void acpi_tb_fix_string(char *string, acpi_size length)
  39{
  40
  41        while (length && *string) {
  42                if (!isprint((int)*string)) {
  43                        *string = '?';
  44                }
  45
  46                string++;
  47                length--;
  48        }
  49}
  50
  51/*******************************************************************************
  52 *
  53 * FUNCTION:    acpi_tb_cleanup_table_header
  54 *
  55 * PARAMETERS:  out_header          - Where the cleaned header is returned
  56 *              header              - Input ACPI table header
  57 *
  58 * RETURN:      Returns the cleaned header in out_header
  59 *
  60 * DESCRIPTION: Copy the table header and ensure that all "string" fields in
  61 *              the header consist of printable characters.
  62 *
  63 ******************************************************************************/
  64
  65static void
  66acpi_tb_cleanup_table_header(struct acpi_table_header *out_header,
  67                             struct acpi_table_header *header)
  68{
  69
  70        memcpy(out_header, header, sizeof(struct acpi_table_header));
  71
  72        acpi_tb_fix_string(out_header->signature, ACPI_NAMESEG_SIZE);
  73        acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE);
  74        acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE);
  75        acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAMESEG_SIZE);
  76}
  77
  78/*******************************************************************************
  79 *
  80 * FUNCTION:    acpi_tb_print_table_header
  81 *
  82 * PARAMETERS:  address             - Table physical address
  83 *              header              - Table header
  84 *
  85 * RETURN:      None
  86 *
  87 * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP.
  88 *
  89 ******************************************************************************/
  90
  91void
  92acpi_tb_print_table_header(acpi_physical_address address,
  93                           struct acpi_table_header *header)
  94{
  95        struct acpi_table_header local_header;
  96
  97        if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) {
  98
  99                /* FACS only has signature and length fields */
 100
 101                ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X",
 102                           header->signature, ACPI_FORMAT_UINT64(address),
 103                           header->length));
 104        } else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) {
 105
 106                /* RSDP has no common fields */
 107
 108                memcpy(local_header.oem_id,
 109                       ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id,
 110                       ACPI_OEM_ID_SIZE);
 111                acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE);
 112
 113                ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)",
 114                           ACPI_FORMAT_UINT64(address),
 115                           (ACPI_CAST_PTR(struct acpi_table_rsdp, header)->
 116                            revision >
 117                            0) ? ACPI_CAST_PTR(struct acpi_table_rsdp,
 118                                               header)->length : 20,
 119                           ACPI_CAST_PTR(struct acpi_table_rsdp,
 120                                         header)->revision,
 121                           local_header.oem_id));
 122        } else {
 123                /* Standard ACPI table with full common header */
 124
 125                acpi_tb_cleanup_table_header(&local_header, header);
 126
 127                ACPI_INFO(("%-4.4s 0x%8.8X%8.8X"
 128                           " %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)",
 129                           local_header.signature, ACPI_FORMAT_UINT64(address),
 130                           local_header.length, local_header.revision,
 131                           local_header.oem_id, local_header.oem_table_id,
 132                           local_header.oem_revision,
 133                           local_header.asl_compiler_id,
 134                           local_header.asl_compiler_revision));
 135        }
 136}
 137
 138/*******************************************************************************
 139 *
 140 * FUNCTION:    acpi_tb_validate_checksum
 141 *
 142 * PARAMETERS:  table               - ACPI table to verify
 143 *              length              - Length of entire table
 144 *
 145 * RETURN:      Status
 146 *
 147 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
 148 *              exception on bad checksum.
 149 *
 150 ******************************************************************************/
 151
 152acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length)
 153{
 154        u8 checksum;
 155
 156        /*
 157         * FACS/S3PT:
 158         * They are the odd tables, have no standard ACPI header and no checksum
 159         */
 160
 161        if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) ||
 162            ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) {
 163                return (AE_OK);
 164        }
 165
 166        /* Compute the checksum on the table */
 167
 168        checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length);
 169
 170        /* Checksum ok? (should be zero) */
 171
 172        if (checksum) {
 173                ACPI_BIOS_WARNING((AE_INFO,
 174                                   "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
 175                                   "should be 0x%2.2X",
 176                                   table->signature, table->checksum,
 177                                   (u8)(table->checksum - checksum)));
 178
 179#if (ACPI_CHECKSUM_ABORT)
 180                return (AE_BAD_CHECKSUM);
 181#endif
 182        }
 183
 184        return (AE_OK);
 185}
 186
 187/*******************************************************************************
 188 *
 189 * FUNCTION:    acpi_tb_checksum
 190 *
 191 * PARAMETERS:  buffer          - Pointer to memory region to be checked
 192 *              length          - Length of this memory region
 193 *
 194 * RETURN:      Checksum (u8)
 195 *
 196 * DESCRIPTION: Calculates circular checksum of memory region.
 197 *
 198 ******************************************************************************/
 199
 200u8 acpi_tb_checksum(u8 *buffer, u32 length)
 201{
 202        u8 sum = 0;
 203        u8 *end = buffer + length;
 204
 205        while (buffer < end) {
 206                sum = (u8)(sum + *(buffer++));
 207        }
 208
 209        return (sum);
 210}
 211