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