summaryrefslogtreecommitdiffstats
path: root/drivers/acpi/acpica/utcksum.c
blob: c166e4c05ab627dfcb773d187b8a87e8b61777df (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
/******************************************************************************
 *
 * Module Name: utcksum - Support generating table checksums
 *
 * Copyright (C) 2000 - 2022, Intel Corp.
 *
 *****************************************************************************/

#include <acpi/acpi.h>
#include "accommon.h"
#include "acutils.h"

/* This module used for application-level code only */

#define _COMPONENT          ACPI_CA_DISASSEMBLER
ACPI_MODULE_NAME("utcksum")

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_verify_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.
 *              Note: We don't have to check for a CDAT here, since CDAT is
 *              not in the RSDT/XSDT, and the CDAT table is never installed
 *              via ACPICA.
 *
 ******************************************************************************/
acpi_status acpi_ut_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 */

	length = table->length;
	checksum =
	    acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, table), length,
				      table->checksum);

	/* Computed checksum matches table? */

	if (checksum != table->checksum) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
				   "should be 0x%2.2X",
				   table->signature, table->checksum,
				   table->checksum - checksum));

#if (ACPI_CHECKSUM_ABORT)
		return (AE_BAD_CHECKSUM);
#endif
	}

	return (AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_verify_cdat_checksum
 *
 * PARAMETERS:  table               - CDAT ACPI table to verify
 *              length              - Length of entire table
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Verifies that the CDAT table checksums to zero. Optionally
 *              returns an exception on bad checksum.
 *
 ******************************************************************************/

acpi_status
acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length)
{
	u8 checksum;

	/* Compute the checksum on the table */

	checksum = acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, cdat_table),
					     cdat_table->length,
					     cdat_table->checksum);

	/* Computed checksum matches table? */

	if (checksum != cdat_table->checksum) {
		ACPI_BIOS_WARNING((AE_INFO,
				   "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
				   "should be 0x%2.2X",
				   acpi_gbl_CDAT, cdat_table->checksum,
				   checksum));

#if (ACPI_CHECKSUM_ABORT)
		return (AE_BAD_CHECKSUM);
#endif
	}

	cdat_table->checksum = checksum;
	return (AE_OK);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_generate_checksum
 *
 * PARAMETERS:  table               - Pointer to table to be checksummed
 *              length              - Length of the table
 *              original_checksum   - Value of the checksum field
 *
 * RETURN:      8 bit checksum of buffer
 *
 * DESCRIPTION: Computes an 8 bit checksum of the table.
 *
 ******************************************************************************/

u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum)
{
	u8 checksum;

	/* Sum the entire table as-is */

	checksum = acpi_ut_checksum((u8 *)table, length);

	/* Subtract off the existing checksum value in the table */

	checksum = (u8)(checksum - original_checksum);

	/* Compute and return the final checksum */

	checksum = (u8)(0 - checksum);
	return (checksum);
}

/*******************************************************************************
 *
 * FUNCTION:    acpi_ut_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_ut_checksum(u8 *buffer, u32 length)
{
	u8 sum = 0;
	u8 *end = buffer + length;

	while (buffer < end) {
		sum = (u8)(sum + *(buffer++));
	}

	return (sum);
}