mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
210 lines
6.0 KiB
210 lines
6.0 KiB
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
|
/****************************************************************************** |
|
* |
|
* Module Name: tbprint - Table output utilities |
|
* |
|
* Copyright (C) 2000 - 2021, Intel Corp. |
|
* |
|
*****************************************************************************/ |
|
|
|
#include <acpi/acpi.h> |
|
#include "accommon.h" |
|
#include "actables.h" |
|
|
|
#define _COMPONENT ACPI_TABLES |
|
ACPI_MODULE_NAME("tbprint") |
|
|
|
/* Local prototypes */ |
|
static void acpi_tb_fix_string(char *string, acpi_size length); |
|
|
|
static void |
|
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, |
|
struct acpi_table_header *header); |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_tb_fix_string |
|
* |
|
* PARAMETERS: string - String to be repaired |
|
* length - Maximum length |
|
* |
|
* RETURN: None |
|
* |
|
* DESCRIPTION: Replace every non-printable or non-ascii byte in the string |
|
* with a question mark '?'. |
|
* |
|
******************************************************************************/ |
|
|
|
static void acpi_tb_fix_string(char *string, acpi_size length) |
|
{ |
|
|
|
while (length && *string) { |
|
if (!isprint((int)*string)) { |
|
*string = '?'; |
|
} |
|
|
|
string++; |
|
length--; |
|
} |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_tb_cleanup_table_header |
|
* |
|
* PARAMETERS: out_header - Where the cleaned header is returned |
|
* header - Input ACPI table header |
|
* |
|
* RETURN: Returns the cleaned header in out_header |
|
* |
|
* DESCRIPTION: Copy the table header and ensure that all "string" fields in |
|
* the header consist of printable characters. |
|
* |
|
******************************************************************************/ |
|
|
|
static void |
|
acpi_tb_cleanup_table_header(struct acpi_table_header *out_header, |
|
struct acpi_table_header *header) |
|
{ |
|
|
|
memcpy(out_header, header, sizeof(struct acpi_table_header)); |
|
|
|
acpi_tb_fix_string(out_header->signature, ACPI_NAMESEG_SIZE); |
|
acpi_tb_fix_string(out_header->oem_id, ACPI_OEM_ID_SIZE); |
|
acpi_tb_fix_string(out_header->oem_table_id, ACPI_OEM_TABLE_ID_SIZE); |
|
acpi_tb_fix_string(out_header->asl_compiler_id, ACPI_NAMESEG_SIZE); |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_tb_print_table_header |
|
* |
|
* PARAMETERS: address - Table physical address |
|
* header - Table header |
|
* |
|
* RETURN: None |
|
* |
|
* DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. |
|
* |
|
******************************************************************************/ |
|
|
|
void |
|
acpi_tb_print_table_header(acpi_physical_address address, |
|
struct acpi_table_header *header) |
|
{ |
|
struct acpi_table_header local_header; |
|
|
|
if (ACPI_COMPARE_NAMESEG(header->signature, ACPI_SIG_FACS)) { |
|
|
|
/* FACS only has signature and length fields */ |
|
|
|
ACPI_INFO(("%-4.4s 0x%8.8X%8.8X %06X", |
|
header->signature, ACPI_FORMAT_UINT64(address), |
|
header->length)); |
|
} else if (ACPI_VALIDATE_RSDP_SIG(header->signature)) { |
|
|
|
/* RSDP has no common fields */ |
|
|
|
memcpy(local_header.oem_id, |
|
ACPI_CAST_PTR(struct acpi_table_rsdp, header)->oem_id, |
|
ACPI_OEM_ID_SIZE); |
|
acpi_tb_fix_string(local_header.oem_id, ACPI_OEM_ID_SIZE); |
|
|
|
ACPI_INFO(("RSDP 0x%8.8X%8.8X %06X (v%.2d %-6.6s)", |
|
ACPI_FORMAT_UINT64(address), |
|
(ACPI_CAST_PTR(struct acpi_table_rsdp, header)-> |
|
revision > |
|
0) ? ACPI_CAST_PTR(struct acpi_table_rsdp, |
|
header)->length : 20, |
|
ACPI_CAST_PTR(struct acpi_table_rsdp, |
|
header)->revision, |
|
local_header.oem_id)); |
|
} else { |
|
/* Standard ACPI table with full common header */ |
|
|
|
acpi_tb_cleanup_table_header(&local_header, header); |
|
|
|
ACPI_INFO(("%-4.4s 0x%8.8X%8.8X" |
|
" %06X (v%.2d %-6.6s %-8.8s %08X %-4.4s %08X)", |
|
local_header.signature, ACPI_FORMAT_UINT64(address), |
|
local_header.length, local_header.revision, |
|
local_header.oem_id, local_header.oem_table_id, |
|
local_header.oem_revision, |
|
local_header.asl_compiler_id, |
|
local_header.asl_compiler_revision)); |
|
} |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_tb_validate_checksum |
|
* |
|
* PARAMETERS: table - ACPI table to verify |
|
* length - Length of entire table |
|
* |
|
* RETURN: Status |
|
* |
|
* DESCRIPTION: Verifies that the table checksums to zero. Optionally returns |
|
* exception on bad checksum. |
|
* |
|
******************************************************************************/ |
|
|
|
acpi_status acpi_tb_verify_checksum(struct acpi_table_header *table, u32 length) |
|
{ |
|
u8 checksum; |
|
|
|
/* |
|
* FACS/S3PT: |
|
* They are the odd tables, have no standard ACPI header and no checksum |
|
*/ |
|
|
|
if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) || |
|
ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) { |
|
return (AE_OK); |
|
} |
|
|
|
/* Compute the checksum on the table */ |
|
|
|
checksum = acpi_tb_checksum(ACPI_CAST_PTR(u8, table), length); |
|
|
|
/* Checksum ok? (should be zero) */ |
|
|
|
if (checksum) { |
|
ACPI_BIOS_WARNING((AE_INFO, |
|
"Incorrect checksum in table [%4.4s] - 0x%2.2X, " |
|
"should be 0x%2.2X", |
|
table->signature, table->checksum, |
|
(u8)(table->checksum - checksum))); |
|
|
|
#if (ACPI_CHECKSUM_ABORT) |
|
return (AE_BAD_CHECKSUM); |
|
#endif |
|
} |
|
|
|
return (AE_OK); |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_tb_checksum |
|
* |
|
* PARAMETERS: buffer - Pointer to memory region to be checked |
|
* length - Length of this memory region |
|
* |
|
* RETURN: Checksum (u8) |
|
* |
|
* DESCRIPTION: Calculates circular checksum of memory region. |
|
* |
|
******************************************************************************/ |
|
|
|
u8 acpi_tb_checksum(u8 *buffer, u32 length) |
|
{ |
|
u8 sum = 0; |
|
u8 *end = buffer + length; |
|
|
|
while (buffer < end) { |
|
sum = (u8)(sum + *(buffer++)); |
|
} |
|
|
|
return (sum); |
|
}
|
|
|