scroll mode for very long start menus
[reactos.git] / reactos / drivers / bus / acpi / tables / tbinstal.c
1 /******************************************************************************
2 *
3 * Module Name: tbinstal - ACPI table installation and removal
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 #include "achware.h"
29 #include "actables.h"
30
31
32 #define _COMPONENT ACPI_TABLES
33 MODULE_NAME ("tbinstal")
34
35
36 /*******************************************************************************
37 *
38 * FUNCTION: Acpi_tb_install_table
39 *
40 * PARAMETERS: Table_ptr - Input buffer pointer, optional
41 * Table_info - Return value from Acpi_tb_get_table
42 *
43 * RETURN: Status
44 *
45 * DESCRIPTION: Load and validate all tables other than the RSDT. The RSDT must
46 * already be loaded and validated.
47 * Install the table into the global data structs.
48 *
49 ******************************************************************************/
50
51 ACPI_STATUS
52 acpi_tb_install_table (
53 ACPI_TABLE_HEADER *table_ptr,
54 ACPI_TABLE_DESC *table_info)
55 {
56 ACPI_STATUS status;
57
58
59 /*
60 * Check the table signature and make sure it is recognized
61 * Also checks the header checksum
62 */
63
64 status = acpi_tb_recognize_table (table_ptr, table_info);
65 if (ACPI_FAILURE (status)) {
66 return (status);
67 }
68
69 /* Lock tables while installing */
70
71 acpi_cm_acquire_mutex (ACPI_MTX_TABLES);
72
73 /* Install the table into the global data structure */
74
75 status = acpi_tb_init_table_descriptor (table_info->type, table_info);
76
77 acpi_cm_release_mutex (ACPI_MTX_TABLES);
78 return (status);
79 }
80
81
82 /*******************************************************************************
83 *
84 * FUNCTION: Acpi_tb_recognize_table
85 *
86 * PARAMETERS: Table_ptr - Input buffer pointer, optional
87 * Table_info - Return value from Acpi_tb_get_table
88 *
89 * RETURN: Status
90 *
91 * DESCRIPTION: Check a table signature for a match against known table types
92 *
93 * NOTE: All table pointers are validated as follows:
94 * 1) Table pointer must point to valid physical memory
95 * 2) Signature must be 4 ASCII chars, even if we don't recognize the
96 * name
97 * 3) Table must be readable for length specified in the header
98 * 4) Table checksum must be valid (with the exception of the FACS
99 * which has no checksum for some odd reason)
100 *
101 ******************************************************************************/
102
103 ACPI_STATUS
104 acpi_tb_recognize_table (
105 ACPI_TABLE_HEADER *table_ptr,
106 ACPI_TABLE_DESC *table_info)
107 {
108 ACPI_TABLE_HEADER *table_header;
109 ACPI_STATUS status;
110 ACPI_TABLE_TYPE table_type = 0;
111 u32 i;
112
113
114 /* Ensure that we have a valid table pointer */
115
116 table_header = (ACPI_TABLE_HEADER *) table_info->pointer;
117 if (!table_header) {
118 return (AE_BAD_PARAMETER);
119 }
120
121 /*
122 * Search for a signature match among the known table types
123 * Start at index one -> Skip the RSDP
124 */
125
126 status = AE_SUPPORT;
127 for (i = 1; i < NUM_ACPI_TABLES; i++) {
128 if (!STRNCMP (table_header->signature,
129 acpi_gbl_acpi_table_data[i].signature,
130 acpi_gbl_acpi_table_data[i].sig_length)) {
131 /*
132 * Found a signature match, get the pertinent info from the
133 * Table_data structure
134 */
135
136 table_type = i;
137 status = acpi_gbl_acpi_table_data[i].status;
138
139 break;
140 }
141 }
142
143 /* Return the table type and length via the info struct */
144
145 table_info->type = (u8) table_type;
146 table_info->length = table_header->length;
147
148
149 /*
150 * Validate checksum for _most_ tables,
151 * even the ones whose signature we don't recognize
152 */
153
154 if (table_type != ACPI_TABLE_FACS) {
155 /* But don't abort if the checksum is wrong */
156 /* TBD: [Future] make this a configuration option? */
157
158 acpi_tb_verify_table_checksum (table_header);
159 }
160
161 /*
162 * An AE_SUPPORT means that the table was not recognized.
163 * We basically ignore this; just print a debug message
164 */
165
166
167 return (status);
168 }
169
170
171 /*******************************************************************************
172 *
173 * FUNCTION: Acpi_tb_init_table_descriptor
174 *
175 * PARAMETERS: Table_type - The type of the table
176 * Table_info - A table info struct
177 *
178 * RETURN: None.
179 *
180 * DESCRIPTION: Install a table into the global data structs.
181 *
182 ******************************************************************************/
183
184 ACPI_STATUS
185 acpi_tb_init_table_descriptor (
186 ACPI_TABLE_TYPE table_type,
187 ACPI_TABLE_DESC *table_info)
188 {
189 ACPI_TABLE_DESC *list_head;
190 ACPI_TABLE_DESC *table_desc;
191
192
193 /*
194 * Install the table into the global data structure
195 */
196
197 list_head = &acpi_gbl_acpi_tables[table_type];
198 table_desc = list_head;
199
200
201 /*
202 * Two major types of tables: 1) Only one instance is allowed. This
203 * includes most ACPI tables such as the DSDT. 2) Multiple instances of
204 * the table are allowed. This includes SSDT and PSDTs.
205 */
206
207 if (IS_SINGLE_TABLE (acpi_gbl_acpi_table_data[table_type].flags)) {
208 /*
209 * Only one table allowed, and a table has alread been installed
210 * at this location, so return an error.
211 */
212
213 if (list_head->pointer) {
214 return (AE_EXIST);
215 }
216
217 table_desc->count = 1;
218 }
219
220
221 else {
222 /*
223 * Multiple tables allowed for this table type, we must link
224 * the new table in to the list of tables of this type.
225 */
226
227 if (list_head->pointer) {
228 table_desc = acpi_cm_callocate (sizeof (ACPI_TABLE_DESC));
229 if (!table_desc) {
230 return (AE_NO_MEMORY);
231 }
232
233 list_head->count++;
234
235 /* Update the original previous */
236
237 list_head->prev->next = table_desc;
238
239 /* Update new entry */
240
241 table_desc->prev = list_head->prev;
242 table_desc->next = list_head;
243
244 /* Update list head */
245
246 list_head->prev = table_desc;
247 }
248
249 else {
250 table_desc->count = 1;
251 }
252 }
253
254
255 /* Common initialization of the table descriptor */
256
257 table_desc->pointer = table_info->pointer;
258 table_desc->base_pointer = table_info->base_pointer;
259 table_desc->length = table_info->length;
260 table_desc->allocation = table_info->allocation;
261 table_desc->aml_pointer = (u8 *) (table_desc->pointer + 1),
262 table_desc->aml_length = (u32) (table_desc->length -
263 (u32) sizeof (ACPI_TABLE_HEADER));
264 table_desc->table_id = acpi_cm_allocate_owner_id (OWNER_TYPE_TABLE);
265 table_desc->loaded_into_namespace = FALSE;
266
267 /*
268 * Set the appropriate global pointer (if there is one) to point to the
269 * newly installed table
270 */
271
272 if (acpi_gbl_acpi_table_data[table_type].global_ptr) {
273 *(acpi_gbl_acpi_table_data[table_type].global_ptr) = table_info->pointer;
274 }
275
276
277 /* Return Data */
278
279 table_info->table_id = table_desc->table_id;
280 table_info->installed_desc = table_desc;
281
282 return (AE_OK);
283 }
284
285
286 /*******************************************************************************
287 *
288 * FUNCTION: Acpi_tb_delete_acpi_tables
289 *
290 * PARAMETERS: None.
291 *
292 * RETURN: None.
293 *
294 * DESCRIPTION: Delete all internal ACPI tables
295 *
296 ******************************************************************************/
297
298 void
299 acpi_tb_delete_acpi_tables (void)
300 {
301 ACPI_TABLE_TYPE type;
302
303
304 /*
305 * Free memory allocated for ACPI tables
306 * Memory can either be mapped or allocated
307 */
308
309 for (type = 0; type < NUM_ACPI_TABLES; type++) {
310 acpi_tb_delete_acpi_table (type);
311 }
312
313 }
314
315
316 /*******************************************************************************
317 *
318 * FUNCTION: Acpi_tb_delete_acpi_table
319 *
320 * PARAMETERS: Type - The table type to be deleted
321 *
322 * RETURN: None.
323 *
324 * DESCRIPTION: Delete an internal ACPI table
325 * Locks the ACPI table mutex
326 *
327 ******************************************************************************/
328
329 void
330 acpi_tb_delete_acpi_table (
331 ACPI_TABLE_TYPE type)
332 {
333
334 if (type > ACPI_TABLE_MAX) {
335 return;
336 }
337
338
339 acpi_cm_acquire_mutex (ACPI_MTX_TABLES);
340
341 /* Free the table */
342
343 acpi_tb_free_acpi_tables_of_type (&acpi_gbl_acpi_tables[type]);
344
345
346 /* Clear the appropriate "typed" global table pointer */
347
348 switch (type) {
349 case ACPI_TABLE_RSDP:
350 acpi_gbl_RSDP = NULL;
351 break;
352
353 case ACPI_TABLE_DSDT:
354 acpi_gbl_DSDT = NULL;
355 break;
356
357 case ACPI_TABLE_FADT:
358 acpi_gbl_FADT = NULL;
359 break;
360
361 case ACPI_TABLE_FACS:
362 acpi_gbl_FACS = NULL;
363 break;
364
365 case ACPI_TABLE_XSDT:
366 acpi_gbl_XSDT = NULL;
367 break;
368
369 case ACPI_TABLE_SSDT:
370 case ACPI_TABLE_PSDT:
371 default:
372 break;
373 }
374
375 acpi_cm_release_mutex (ACPI_MTX_TABLES);
376
377 return;
378 }
379
380
381 /*******************************************************************************
382 *
383 * FUNCTION: Acpi_tb_free_acpi_tables_of_type
384 *
385 * PARAMETERS: Table_info - A table info struct
386 *
387 * RETURN: None.
388 *
389 * DESCRIPTION: Free the memory associated with an internal ACPI table
390 * Table mutex should be locked.
391 *
392 ******************************************************************************/
393
394 void
395 acpi_tb_free_acpi_tables_of_type (
396 ACPI_TABLE_DESC *list_head)
397 {
398 ACPI_TABLE_DESC *table_desc;
399 u32 count;
400 u32 i;
401
402
403 /* Get the head of the list */
404
405 table_desc = list_head;
406 count = list_head->count;
407
408 /*
409 * Walk the entire list, deleting both the allocated tables
410 * and the table descriptors
411 */
412
413 for (i = 0; i < count; i++) {
414 table_desc = acpi_tb_uninstall_table (table_desc);
415 }
416
417 return;
418 }
419
420
421 /*******************************************************************************
422 *
423 * FUNCTION: Acpi_tb_delete_single_table
424 *
425 * PARAMETERS: Table_info - A table info struct
426 *
427 * RETURN: None.
428 *
429 * DESCRIPTION: Low-level free for a single ACPI table. Handles cases where
430 * the table was allocated a buffer or was mapped.
431 *
432 ******************************************************************************/
433
434 void
435 acpi_tb_delete_single_table (
436 ACPI_TABLE_DESC *table_desc)
437 {
438
439 if (!table_desc) {
440 return;
441 }
442
443 if (table_desc->pointer) {
444 /* Valid table, determine type of memory allocation */
445
446 switch (table_desc->allocation) {
447
448 case ACPI_MEM_NOT_ALLOCATED:
449 break;
450
451
452 case ACPI_MEM_ALLOCATED:
453
454 acpi_cm_free (table_desc->base_pointer);
455 break;
456
457
458 case ACPI_MEM_MAPPED:
459
460 acpi_os_unmap_memory (table_desc->base_pointer, table_desc->length);
461 break;
462 }
463 }
464 }
465
466
467 /*******************************************************************************
468 *
469 * FUNCTION: Acpi_tb_uninstall_table
470 *
471 * PARAMETERS: Table_info - A table info struct
472 *
473 * RETURN: None.
474 *
475 * DESCRIPTION: Free the memory associated with an internal ACPI table that
476 * is either installed or has never been installed.
477 * Table mutex should be locked.
478 *
479 ******************************************************************************/
480
481 ACPI_TABLE_DESC *
482 acpi_tb_uninstall_table (
483 ACPI_TABLE_DESC *table_desc)
484 {
485 ACPI_TABLE_DESC *next_desc;
486
487
488 if (!table_desc) {
489 return (NULL);
490 }
491
492
493 /* Unlink the descriptor */
494
495 if (table_desc->prev) {
496 table_desc->prev->next = table_desc->next;
497 }
498
499 if (table_desc->next) {
500 table_desc->next->prev = table_desc->prev;
501 }
502
503
504 /* Free the memory allocated for the table itself */
505
506 acpi_tb_delete_single_table (table_desc);
507
508
509 /* Free the table descriptor (Don't delete the list head, tho) */
510
511 if ((table_desc->prev) == (table_desc->next)) {
512
513 next_desc = NULL;
514
515 /* Clear the list head */
516
517 table_desc->pointer = NULL;
518 table_desc->length = 0;
519 table_desc->count = 0;
520
521 }
522
523 else {
524 /* Free the table descriptor */
525
526 next_desc = table_desc->next;
527 acpi_cm_free (table_desc);
528 }
529
530
531 return (next_desc);
532 }
533
534