1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
3 *
4 * Module Name: utcksum - Support generating table checksums
5 *
6 * Copyright (C) 2000 - 2023, Intel Corp.
7 *
8 *****************************************************************************/
9
10 #include <acpi/acpi.h>
11 #include "accommon.h"
12 #include "acutils.h"
13
14 /* This module used for application-level code only */
15
16 #define _COMPONENT ACPI_CA_DISASSEMBLER
17 ACPI_MODULE_NAME("utcksum")
18
19 /*******************************************************************************
20 *
21 * FUNCTION: acpi_ut_verify_checksum
22 *
23 * PARAMETERS: table - ACPI table to verify
24 * length - Length of entire table
25 *
26 * RETURN: Status
27 *
28 * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns
29 * exception on bad checksum.
30 * Note: We don't have to check for a CDAT here, since CDAT is
31 * not in the RSDT/XSDT, and the CDAT table is never installed
32 * via ACPICA.
33 *
34 ******************************************************************************/
acpi_ut_verify_checksum(struct acpi_table_header * table,u32 length)35 acpi_status acpi_ut_verify_checksum(struct acpi_table_header *table, u32 length)
36 {
37 u8 checksum;
38
39 /*
40 * FACS/S3PT:
41 * They are the odd tables, have no standard ACPI header and no checksum
42 */
43 if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_S3PT) ||
44 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_FACS)) {
45 return (AE_OK);
46 }
47
48 /* Compute the checksum on the table */
49
50 length = table->length;
51 checksum =
52 acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, table), length,
53 table->checksum);
54
55 /* Computed checksum matches table? */
56
57 if (checksum != table->checksum) {
58 ACPI_BIOS_WARNING((AE_INFO,
59 "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
60 "should be 0x%2.2X",
61 table->signature, table->checksum,
62 table->checksum - checksum));
63
64 #if (ACPI_CHECKSUM_ABORT)
65 return (AE_BAD_CHECKSUM);
66 #endif
67 }
68
69 return (AE_OK);
70 }
71
72 /*******************************************************************************
73 *
74 * FUNCTION: acpi_ut_verify_cdat_checksum
75 *
76 * PARAMETERS: table - CDAT ACPI table to verify
77 * length - Length of entire table
78 *
79 * RETURN: Status
80 *
81 * DESCRIPTION: Verifies that the CDAT table checksums to zero. Optionally
82 * returns an exception on bad checksum.
83 *
84 ******************************************************************************/
85
86 acpi_status
acpi_ut_verify_cdat_checksum(struct acpi_table_cdat * cdat_table,u32 length)87 acpi_ut_verify_cdat_checksum(struct acpi_table_cdat *cdat_table, u32 length)
88 {
89 u8 checksum;
90
91 /* Compute the checksum on the table */
92
93 checksum = acpi_ut_generate_checksum(ACPI_CAST_PTR(u8, cdat_table),
94 cdat_table->length,
95 cdat_table->checksum);
96
97 /* Computed checksum matches table? */
98
99 if (checksum != cdat_table->checksum) {
100 ACPI_BIOS_WARNING((AE_INFO,
101 "Incorrect checksum in table [%4.4s] - 0x%2.2X, "
102 "should be 0x%2.2X",
103 acpi_gbl_CDAT, cdat_table->checksum,
104 checksum));
105
106 #if (ACPI_CHECKSUM_ABORT)
107 return (AE_BAD_CHECKSUM);
108 #endif
109 }
110
111 cdat_table->checksum = checksum;
112 return (AE_OK);
113 }
114
115 /*******************************************************************************
116 *
117 * FUNCTION: acpi_ut_generate_checksum
118 *
119 * PARAMETERS: table - Pointer to table to be checksummed
120 * length - Length of the table
121 * original_checksum - Value of the checksum field
122 *
123 * RETURN: 8 bit checksum of buffer
124 *
125 * DESCRIPTION: Computes an 8 bit checksum of the table.
126 *
127 ******************************************************************************/
128
acpi_ut_generate_checksum(void * table,u32 length,u8 original_checksum)129 u8 acpi_ut_generate_checksum(void *table, u32 length, u8 original_checksum)
130 {
131 u8 checksum;
132
133 /* Sum the entire table as-is */
134
135 checksum = acpi_ut_checksum((u8 *)table, length);
136
137 /* Subtract off the existing checksum value in the table */
138
139 checksum = (u8)(checksum - original_checksum);
140
141 /* Compute and return the final checksum */
142
143 checksum = (u8)(0 - checksum);
144 return (checksum);
145 }
146
147 /*******************************************************************************
148 *
149 * FUNCTION: acpi_ut_checksum
150 *
151 * PARAMETERS: buffer - Pointer to memory region to be checked
152 * length - Length of this memory region
153 *
154 * RETURN: Checksum (u8)
155 *
156 * DESCRIPTION: Calculates circular checksum of memory region.
157 *
158 ******************************************************************************/
159
acpi_ut_checksum(u8 * buffer,u32 length)160 u8 acpi_ut_checksum(u8 *buffer, u32 length)
161 {
162 u8 sum = 0;
163 u8 *end = buffer + length;
164
165 while (buffer < end) {
166 sum = (u8)(sum + *(buffer++));
167 }
168
169 return (sum);
170 }
171