xref: /openbmc/linux/drivers/acpi/acpica/utcksum.c (revision 2a598d0b)
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  ******************************************************************************/
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
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 
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 
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