1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45#include <linux/export.h>
46#include <acpi/acpi.h>
47#include "accommon.h"
48#include "acnamesp.h"
49#include "actables.h"
50
51#define _COMPONENT ACPI_TABLES
52ACPI_MODULE_NAME("tbxface")
53
54
55static acpi_status acpi_tb_load_namespace(void);
56
57static int no_auto_ssdt;
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73acpi_status acpi_allocate_root_table(u32 initial_table_count)
74{
75
76 acpi_gbl_root_table_list.max_table_count = initial_table_count;
77 acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
78
79 return (acpi_tb_resize_root_table_list());
80}
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108acpi_status __init
109acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
110 u32 initial_table_count, u8 allow_resize)
111{
112 acpi_physical_address rsdp_address;
113 acpi_status status;
114
115 ACPI_FUNCTION_TRACE(acpi_initialize_tables);
116
117
118
119
120
121 if (!initial_table_array) {
122 status = acpi_allocate_root_table(initial_table_count);
123 if (ACPI_FAILURE(status)) {
124 return_ACPI_STATUS(status);
125 }
126 } else {
127
128
129 ACPI_MEMSET(initial_table_array, 0,
130 (acpi_size) initial_table_count *
131 sizeof(struct acpi_table_desc));
132
133 acpi_gbl_root_table_list.tables = initial_table_array;
134 acpi_gbl_root_table_list.max_table_count = initial_table_count;
135 acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
136 if (allow_resize) {
137 acpi_gbl_root_table_list.flags |=
138 ACPI_ROOT_ALLOW_RESIZE;
139 }
140 }
141
142
143
144 rsdp_address = acpi_os_get_root_pointer();
145 if (!rsdp_address) {
146 return_ACPI_STATUS(AE_NOT_FOUND);
147 }
148
149
150
151
152
153
154 status = acpi_tb_parse_root_table(rsdp_address);
155 return_ACPI_STATUS(status);
156}
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172acpi_status acpi_reallocate_root_table(void)
173{
174 struct acpi_table_desc *tables;
175 acpi_size new_size;
176 acpi_size current_size;
177
178 ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
179
180
181
182
183
184 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
185 return_ACPI_STATUS(AE_SUPPORT);
186 }
187
188
189
190
191
192 current_size = (acpi_size)
193 acpi_gbl_root_table_list.current_table_count *
194 sizeof(struct acpi_table_desc);
195
196 new_size = current_size +
197 (ACPI_ROOT_TABLE_SIZE_INCREMENT * sizeof(struct acpi_table_desc));
198
199
200
201 tables = ACPI_ALLOCATE_ZEROED(new_size);
202 if (!tables) {
203 return_ACPI_STATUS(AE_NO_MEMORY);
204 }
205
206 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, current_size);
207
208
209
210
211
212
213 acpi_gbl_root_table_list.tables = tables;
214 acpi_gbl_root_table_list.max_table_count =
215 acpi_gbl_root_table_list.current_table_count +
216 ACPI_ROOT_TABLE_SIZE_INCREMENT;
217 acpi_gbl_root_table_list.flags =
218 ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
219
220 return_ACPI_STATUS(AE_OK);
221}
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
239{
240 acpi_status status;
241 u32 table_index;
242 struct acpi_table_desc table_desc;
243
244 if (!table_ptr)
245 return AE_BAD_PARAMETER;
246
247 ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
248 table_desc.pointer = table_ptr;
249 table_desc.length = table_ptr->length;
250 table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
251
252
253
254
255 status = acpi_tb_add_table(&table_desc, &table_index);
256 if (ACPI_FAILURE(status)) {
257 return status;
258 }
259 status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
260 return status;
261}
262
263ACPI_EXPORT_SYMBOL(acpi_load_table)
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281acpi_status
282acpi_get_table_header(char *signature,
283 u32 instance, struct acpi_table_header *out_table_header)
284{
285 u32 i;
286 u32 j;
287 struct acpi_table_header *header;
288
289
290
291 if (!signature || !out_table_header) {
292 return (AE_BAD_PARAMETER);
293 }
294
295
296
297 for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
298 i++) {
299 if (!ACPI_COMPARE_NAME
300 (&(acpi_gbl_root_table_list.tables[i].signature),
301 signature)) {
302 continue;
303 }
304
305 if (++j < instance) {
306 continue;
307 }
308
309 if (!acpi_gbl_root_table_list.tables[i].pointer) {
310 if ((acpi_gbl_root_table_list.tables[i].flags &
311 ACPI_TABLE_ORIGIN_MASK) ==
312 ACPI_TABLE_ORIGIN_MAPPED) {
313 header =
314 acpi_os_map_memory(acpi_gbl_root_table_list.
315 tables[i].address,
316 sizeof(struct
317 acpi_table_header));
318 if (!header) {
319 return AE_NO_MEMORY;
320 }
321 ACPI_MEMCPY(out_table_header, header,
322 sizeof(struct acpi_table_header));
323 acpi_os_unmap_memory(header,
324 sizeof(struct
325 acpi_table_header));
326 } else {
327 return AE_NOT_FOUND;
328 }
329 } else {
330 ACPI_MEMCPY(out_table_header,
331 acpi_gbl_root_table_list.tables[i].pointer,
332 sizeof(struct acpi_table_header));
333 }
334 return (AE_OK);
335 }
336
337 return (AE_NOT_FOUND);
338}
339
340ACPI_EXPORT_SYMBOL(acpi_get_table_header)
341
342
343
344
345
346
347
348
349
350
351
352
353acpi_status acpi_unload_table_id(acpi_owner_id id)
354{
355 int i;
356 acpi_status status = AE_NOT_EXIST;
357
358 ACPI_FUNCTION_TRACE(acpi_unload_table_id);
359
360
361 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
362 if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
363 continue;
364 }
365
366
367
368
369
370
371 acpi_tb_delete_namespace_by_owner(i);
372 status = acpi_tb_release_owner_id(i);
373 acpi_tb_set_table_loaded_flag(i, FALSE);
374 break;
375 }
376 return_ACPI_STATUS(status);
377}
378
379ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394acpi_status
395acpi_get_table_with_size(char *signature,
396 u32 instance, struct acpi_table_header **out_table,
397 acpi_size *tbl_size)
398{
399 u32 i;
400 u32 j;
401 acpi_status status;
402
403
404
405 if (!signature || !out_table) {
406 return (AE_BAD_PARAMETER);
407 }
408
409
410
411 for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
412 i++) {
413 if (!ACPI_COMPARE_NAME
414 (&(acpi_gbl_root_table_list.tables[i].signature),
415 signature)) {
416 continue;
417 }
418
419 if (++j < instance) {
420 continue;
421 }
422
423 status =
424 acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
425 if (ACPI_SUCCESS(status)) {
426 *out_table = acpi_gbl_root_table_list.tables[i].pointer;
427 *tbl_size = acpi_gbl_root_table_list.tables[i].length;
428 }
429
430 if (!acpi_gbl_permanent_mmap) {
431 acpi_gbl_root_table_list.tables[i].pointer = NULL;
432 }
433
434 return (status);
435 }
436
437 return (AE_NOT_FOUND);
438}
439
440acpi_status
441acpi_get_table(char *signature,
442 u32 instance, struct acpi_table_header **out_table)
443{
444 acpi_size tbl_size;
445
446 return acpi_get_table_with_size(signature,
447 instance, out_table, &tbl_size);
448}
449ACPI_EXPORT_SYMBOL(acpi_get_table)
450
451
452
453
454
455
456
457
458
459
460
461
462
463acpi_status
464acpi_get_table_by_index(u32 table_index, struct acpi_table_header **table)
465{
466 acpi_status status;
467
468 ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
469
470
471
472 if (!table) {
473 return_ACPI_STATUS(AE_BAD_PARAMETER);
474 }
475
476 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
477
478
479
480 if (table_index >= acpi_gbl_root_table_list.current_table_count) {
481 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
482 return_ACPI_STATUS(AE_BAD_PARAMETER);
483 }
484
485 if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
486
487
488
489 status =
490 acpi_tb_verify_table(&acpi_gbl_root_table_list.
491 tables[table_index]);
492 if (ACPI_FAILURE(status)) {
493 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
494 return_ACPI_STATUS(status);
495 }
496 }
497
498 *table = acpi_gbl_root_table_list.tables[table_index].pointer;
499 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
500 return_ACPI_STATUS(AE_OK);
501}
502
503ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
504
505
506
507
508
509
510
511
512
513
514
515
516
517static acpi_status acpi_tb_load_namespace(void)
518{
519 acpi_status status;
520 u32 i;
521 struct acpi_table_header *new_dsdt;
522
523 ACPI_FUNCTION_TRACE(tb_load_namespace);
524
525 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
526
527
528
529
530
531 if (!acpi_gbl_root_table_list.current_table_count ||
532 !ACPI_COMPARE_NAME(&
533 (acpi_gbl_root_table_list.
534 tables[ACPI_TABLE_INDEX_DSDT].signature),
535 ACPI_SIG_DSDT)
536 ||
537 ACPI_FAILURE(acpi_tb_verify_table
538 (&acpi_gbl_root_table_list.
539 tables[ACPI_TABLE_INDEX_DSDT]))) {
540 status = AE_NO_ACPI_TABLES;
541 goto unlock_and_exit;
542 }
543
544
545
546
547
548
549
550 acpi_gbl_DSDT =
551 acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer;
552
553
554
555
556
557
558
559 if (acpi_gbl_copy_dsdt_locally) {
560 new_dsdt = acpi_tb_copy_dsdt(ACPI_TABLE_INDEX_DSDT);
561 if (new_dsdt) {
562 acpi_gbl_DSDT = new_dsdt;
563 }
564 }
565
566
567
568
569
570 ACPI_MEMCPY(&acpi_gbl_original_dsdt_header, acpi_gbl_DSDT,
571 sizeof(struct acpi_table_header));
572
573 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
574
575
576
577 status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
578 if (ACPI_FAILURE(status)) {
579 return_ACPI_STATUS(status);
580 }
581
582
583
584 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
585 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
586 if ((!ACPI_COMPARE_NAME
587 (&(acpi_gbl_root_table_list.tables[i].signature),
588 ACPI_SIG_SSDT)
589 &&
590 !ACPI_COMPARE_NAME(&
591 (acpi_gbl_root_table_list.tables[i].
592 signature), ACPI_SIG_PSDT))
593 ||
594 ACPI_FAILURE(acpi_tb_verify_table
595 (&acpi_gbl_root_table_list.tables[i]))) {
596 continue;
597 }
598
599 if (no_auto_ssdt) {
600 printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n");
601 continue;
602 }
603
604
605
606 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
607 (void)acpi_ns_load_table(i, acpi_gbl_root_node);
608 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
609 }
610
611 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
612
613 unlock_and_exit:
614 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
615 return_ACPI_STATUS(status);
616}
617
618
619
620
621
622
623
624
625
626
627
628
629
630acpi_status acpi_load_tables(void)
631{
632 acpi_status status;
633
634 ACPI_FUNCTION_TRACE(acpi_load_tables);
635
636
637
638 status = acpi_tb_load_namespace();
639 if (ACPI_FAILURE(status)) {
640 ACPI_EXCEPTION((AE_INFO, status,
641 "While loading namespace from ACPI tables"));
642 }
643
644 return_ACPI_STATUS(status);
645}
646
647ACPI_EXPORT_SYMBOL(acpi_load_tables)
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662acpi_status
663acpi_install_table_handler(acpi_tbl_handler handler, void *context)
664{
665 acpi_status status;
666
667 ACPI_FUNCTION_TRACE(acpi_install_table_handler);
668
669 if (!handler) {
670 return_ACPI_STATUS(AE_BAD_PARAMETER);
671 }
672
673 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
674 if (ACPI_FAILURE(status)) {
675 return_ACPI_STATUS(status);
676 }
677
678
679
680 if (acpi_gbl_table_handler) {
681 status = AE_ALREADY_EXISTS;
682 goto cleanup;
683 }
684
685
686
687 acpi_gbl_table_handler = handler;
688 acpi_gbl_table_handler_context = context;
689
690 cleanup:
691 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
692 return_ACPI_STATUS(status);
693}
694
695ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
696
697
698
699
700
701
702
703
704
705
706
707
708
709acpi_status acpi_remove_table_handler(acpi_tbl_handler handler)
710{
711 acpi_status status;
712
713 ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
714
715 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
716 if (ACPI_FAILURE(status)) {
717 return_ACPI_STATUS(status);
718 }
719
720
721
722 if (!handler || handler != acpi_gbl_table_handler) {
723 status = AE_BAD_PARAMETER;
724 goto cleanup;
725 }
726
727
728
729 acpi_gbl_table_handler = NULL;
730
731 cleanup:
732 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
733 return_ACPI_STATUS(status);
734}
735
736ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)
737
738
739static int __init acpi_no_auto_ssdt_setup(char *s) {
740
741 printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n");
742
743 no_auto_ssdt = 1;
744
745 return 1;
746}
747
748__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
749