- Send the SCM reply packet with the final status after completing the requested...
[reactos.git] / reactos / drivers / bus / acpi / tables / tbutils.c
1 /******************************************************************************
2 *
3 * Module Name: tbutils - Table manipulation utilities
4 * $Revision: 1.1 $
5 *
6 *****************************************************************************/
7
8 /*
9 * Copyright (C) 2000, 2001 R. Byron Moore
10 *
11 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License
22 * along with this program; if not, write to the Free Software
23 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
24 */
25
26
27 #include <acpi.h>
28
29 #define _COMPONENT ACPI_TABLES
30 MODULE_NAME ("tbutils")
31
32
33 /*******************************************************************************
34 *
35 * FUNCTION: Acpi_tb_handle_to_object
36 *
37 * PARAMETERS: Table_id - Id for which the function is searching
38 * Table_desc - Pointer to return the matching table
39 * descriptor.
40 *
41 * RETURN: Search the tables to find one with a matching Table_id and
42 * return a pointer to that table descriptor.
43 *
44 ******************************************************************************/
45
46 ACPI_STATUS
47 acpi_tb_handle_to_object (
48 u16 table_id,
49 ACPI_TABLE_DESC **table_desc)
50 {
51 u32 i;
52 ACPI_TABLE_DESC *list_head;
53
54
55 for (i = 0; i < ACPI_TABLE_MAX; i++) {
56 list_head = &acpi_gbl_acpi_tables[i];
57 do {
58 if (list_head->table_id == table_id) {
59 *table_desc = list_head;
60 return (AE_OK);
61 }
62
63 list_head = list_head->next;
64
65 } while (list_head != &acpi_gbl_acpi_tables[i]);
66 }
67
68
69 return (AE_BAD_PARAMETER);
70 }
71
72
73 /*******************************************************************************
74 *
75 * FUNCTION: Acpi_tb_system_table_pointer
76 *
77 * PARAMETERS: *Where - Pointer to be examined
78 *
79 * RETURN: TRUE if Where is within the AML stream (in one of the ACPI
80 * system tables such as the DSDT or an SSDT.)
81 * FALSE otherwise
82 *
83 ******************************************************************************/
84
85 u8
86 acpi_tb_system_table_pointer (
87 void *where)
88 {
89 u32 i;
90 ACPI_TABLE_DESC *table_desc;
91 ACPI_TABLE_HEADER *table;
92
93
94 /* No function trace, called too often! */
95
96
97 /* Ignore null pointer */
98
99 if (!where) {
100 return (FALSE);
101 }
102
103
104 /* Check for a pointer within the DSDT */
105
106 if ((acpi_gbl_DSDT) &&
107 (IS_IN_ACPI_TABLE (where, acpi_gbl_DSDT))) {
108 return (TRUE);
109 }
110
111
112 /* Check each of the loaded SSDTs (if any)*/
113
114 table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_SSDT];
115
116 for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_SSDT].count; i++) {
117 table = table_desc->pointer;
118
119 if (IS_IN_ACPI_TABLE (where, table)) {
120 return (TRUE);
121 }
122
123 table_desc = table_desc->next;
124 }
125
126
127 /* Check each of the loaded PSDTs (if any)*/
128
129 table_desc = &acpi_gbl_acpi_tables[ACPI_TABLE_PSDT];
130
131 for (i = 0; i < acpi_gbl_acpi_tables[ACPI_TABLE_PSDT].count; i++) {
132 table = table_desc->pointer;
133
134 if (IS_IN_ACPI_TABLE (where, table)) {
135 return (TRUE);
136 }
137
138 table_desc = table_desc->next;
139 }
140
141
142 /* Pointer does not point into any system table */
143
144 return (FALSE);
145 }
146
147
148 /*******************************************************************************
149 *
150 * FUNCTION: Acpi_tb_validate_table_header
151 *
152 * PARAMETERS: Table_header - Logical pointer to the table
153 *
154 * RETURN: Status
155 *
156 * DESCRIPTION: Check an ACPI table header for validity
157 *
158 * NOTE: Table pointers are validated as follows:
159 * 1) Table pointer must point to valid physical memory
160 * 2) Signature must be 4 ASCII chars, even if we don't recognize the
161 * name
162 * 3) Table must be readable for length specified in the header
163 * 4) Table checksum must be valid (with the exception of the FACS
164 * which has no checksum for some odd reason)
165 *
166 ******************************************************************************/
167
168 ACPI_STATUS
169 acpi_tb_validate_table_header (
170 ACPI_TABLE_HEADER *table_header)
171 {
172 ACPI_NAME signature;
173
174
175 /* Verify that this is a valid address */
176
177 if (!acpi_os_readable (table_header, sizeof (ACPI_TABLE_HEADER))) {
178 return (AE_BAD_ADDRESS);
179 }
180
181
182 /* Ensure that the signature is 4 ASCII characters */
183
184 MOVE_UNALIGNED32_TO_32 (&signature, &table_header->signature);
185 if (!acpi_cm_valid_acpi_name (signature)) {
186 REPORT_WARNING (("Invalid table signature found\n"));
187 return (AE_BAD_SIGNATURE);
188 }
189
190
191 /* Validate the table length */
192
193 if (table_header->length < sizeof (ACPI_TABLE_HEADER)) {
194 REPORT_WARNING (("Invalid table header length found\n"));
195 return (AE_BAD_HEADER);
196 }
197
198 return (AE_OK);
199 }
200
201
202 /*******************************************************************************
203 *
204 * FUNCTION: Acpi_tb_map_acpi_table
205 *
206 * PARAMETERS: Physical_address - Physical address of table to map
207 * *Size - Size of the table. If zero, the size
208 * from the table header is used.
209 * Actual size is returned here.
210 * **Logical_address - Logical address of mapped table
211 *
212 * RETURN: Logical address of the mapped table.
213 *
214 * DESCRIPTION: Maps the physical address of table into a logical address
215 *
216 ******************************************************************************/
217
218 ACPI_STATUS
219 acpi_tb_map_acpi_table (
220 ACPI_PHYSICAL_ADDRESS physical_address,
221 u32 *size,
222 void **logical_address)
223 {
224 ACPI_TABLE_HEADER *table;
225 u32 table_size = *size;
226 ACPI_STATUS status = AE_OK;
227
228
229 /* If size is zero, look at the table header to get the actual size */
230
231 if ((*size) == 0) {
232 /* Get the table header so we can extract the table length */
233
234 status = acpi_os_map_memory (physical_address, sizeof (ACPI_TABLE_HEADER),
235 (void **) &table);
236 if (ACPI_FAILURE (status)) {
237 return (status);
238 }
239
240 /* Extract the full table length before we delete the mapping */
241
242 table_size = table->length;
243
244 /*
245 * Validate the header and delete the mapping.
246 * We will create a mapping for the full table below.
247 */
248
249 status = acpi_tb_validate_table_header (table);
250
251 /* Always unmap the memory for the header */
252
253 acpi_os_unmap_memory (table, sizeof (ACPI_TABLE_HEADER));
254
255 /* Exit if header invalid */
256
257 if (ACPI_FAILURE (status)) {
258 return (status);
259 }
260 }
261
262
263 /* Map the physical memory for the correct length */
264
265 status = acpi_os_map_memory (physical_address, table_size, (void **) &table);
266 if (ACPI_FAILURE (status)) {
267 return (status);
268 }
269
270 *size = table_size;
271 *logical_address = table;
272
273 return (status);
274 }
275
276
277 /*******************************************************************************
278 *
279 * FUNCTION: Acpi_tb_verify_table_checksum
280 *
281 * PARAMETERS: *Table_header - ACPI table to verify
282 *
283 * RETURN: 8 bit checksum of table
284 *
285 * DESCRIPTION: Does an 8 bit checksum of table and returns status. A correct
286 * table should have a checksum of 0.
287 *
288 ******************************************************************************/
289
290 ACPI_STATUS
291 acpi_tb_verify_table_checksum (
292 ACPI_TABLE_HEADER *table_header)
293 {
294 u8 checksum;
295 ACPI_STATUS status = AE_OK;
296
297
298 /* Compute the checksum on the table */
299
300 checksum = acpi_tb_checksum (table_header, table_header->length);
301
302 /* Return the appropriate exception */
303
304 if (checksum) {
305 REPORT_WARNING (("Invalid checksum (%X) in table %4.4s\n",
306 checksum, &table_header->signature));
307
308 status = AE_BAD_CHECKSUM;
309 }
310
311
312 return (status);
313 }
314
315
316 /*******************************************************************************
317 *
318 * FUNCTION: Acpi_tb_checksum
319 *
320 * PARAMETERS: Buffer - Buffer to checksum
321 * Length - Size of the buffer
322 *
323 * RETURNS 8 bit checksum of buffer
324 *
325 * DESCRIPTION: Computes an 8 bit checksum of the buffer(length) and returns it.
326 *
327 ******************************************************************************/
328
329 u8
330 acpi_tb_checksum (
331 void *buffer,
332 u32 length)
333 {
334 u8 *limit;
335 u8 *rover;
336 u8 sum = 0;
337
338
339 if (buffer && length) {
340 /* Buffer and Length are valid */
341
342 limit = (u8 *) buffer + length;
343
344 for (rover = buffer; rover < limit; rover++) {
345 sum = (u8) (sum + *rover);
346 }
347 }
348
349 return (sum);
350 }
351
352