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 <acpi/acpi.h>
46#include <acpi/acnamesp.h>
47#include <acpi/actables.h>
48
49#define _COMPONENT ACPI_TABLES
50ACPI_MODULE_NAME("tbxface")
51
52
53static acpi_status acpi_tb_load_namespace(void);
54
55static int no_auto_ssdt;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71acpi_status acpi_allocate_root_table(u32 initial_table_count)
72{
73
74 acpi_gbl_root_table_list.size = initial_table_count;
75 acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
76
77 return (acpi_tb_resize_root_table_list());
78}
79
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
106acpi_status __init
107acpi_initialize_tables(struct acpi_table_desc * initial_table_array,
108 u32 initial_table_count, u8 allow_resize)
109{
110 acpi_physical_address rsdp_address;
111 acpi_status status;
112
113 ACPI_FUNCTION_TRACE(acpi_initialize_tables);
114
115
116
117
118
119 if (!initial_table_array) {
120 status = acpi_allocate_root_table(initial_table_count);
121 if (ACPI_FAILURE(status)) {
122 return_ACPI_STATUS(status);
123 }
124 } else {
125
126
127 ACPI_MEMSET(initial_table_array, 0,
128 initial_table_count *
129 sizeof(struct acpi_table_desc));
130
131 acpi_gbl_root_table_list.tables = initial_table_array;
132 acpi_gbl_root_table_list.size = initial_table_count;
133 acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
134 if (allow_resize) {
135 acpi_gbl_root_table_list.flags |=
136 ACPI_ROOT_ALLOW_RESIZE;
137 }
138 }
139
140
141
142 rsdp_address = acpi_os_get_root_pointer();
143 if (!rsdp_address) {
144 return_ACPI_STATUS(AE_NOT_FOUND);
145 }
146
147
148
149
150
151
152 status =
153 acpi_tb_parse_root_table(rsdp_address, ACPI_TABLE_ORIGIN_MAPPED);
154 return_ACPI_STATUS(status);
155}
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171acpi_status acpi_reallocate_root_table(void)
172{
173 struct acpi_table_desc *tables;
174 acpi_size new_size;
175
176 ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
177
178
179
180
181
182 if (acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) {
183 return_ACPI_STATUS(AE_SUPPORT);
184 }
185
186 new_size =
187 (acpi_gbl_root_table_list.count +
188 ACPI_ROOT_TABLE_SIZE_INCREMENT) * sizeof(struct acpi_table_desc);
189
190
191
192 tables = ACPI_ALLOCATE_ZEROED(new_size);
193 if (!tables) {
194 return_ACPI_STATUS(AE_NO_MEMORY);
195 }
196
197 ACPI_MEMCPY(tables, acpi_gbl_root_table_list.tables, new_size);
198
199 acpi_gbl_root_table_list.size = acpi_gbl_root_table_list.count;
200 acpi_gbl_root_table_list.tables = tables;
201 acpi_gbl_root_table_list.flags =
202 ACPI_ROOT_ORIGIN_ALLOCATED | ACPI_ROOT_ALLOW_RESIZE;
203
204 return_ACPI_STATUS(AE_OK);
205}
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222acpi_status acpi_load_table(struct acpi_table_header *table_ptr)
223{
224 acpi_status status;
225 acpi_native_uint table_index;
226 struct acpi_table_desc table_desc;
227
228 if (!table_ptr)
229 return AE_BAD_PARAMETER;
230
231 ACPI_MEMSET(&table_desc, 0, sizeof(struct acpi_table_desc));
232 table_desc.pointer = table_ptr;
233 table_desc.length = table_ptr->length;
234 table_desc.flags = ACPI_TABLE_ORIGIN_UNKNOWN;
235
236
237
238
239 status = acpi_tb_add_table(&table_desc, &table_index);
240 if (ACPI_FAILURE(status)) {
241 return status;
242 }
243 status = acpi_ns_load_table(table_index, acpi_gbl_root_node);
244 return status;
245}
246
247ACPI_EXPORT_SYMBOL(acpi_load_table)
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265acpi_status
266acpi_get_table_header(char *signature,
267 acpi_native_uint instance,
268 struct acpi_table_header * out_table_header)
269{
270 acpi_native_uint i;
271 acpi_native_uint j;
272 struct acpi_table_header *header;
273
274
275
276 if (!signature || !out_table_header) {
277 return (AE_BAD_PARAMETER);
278 }
279
280
281
282
283 for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
284 if (!ACPI_COMPARE_NAME
285 (&(acpi_gbl_root_table_list.tables[i].signature),
286 signature)) {
287 continue;
288 }
289
290 if (++j < instance) {
291 continue;
292 }
293
294 if (!acpi_gbl_root_table_list.tables[i].pointer) {
295 if ((acpi_gbl_root_table_list.tables[i].
296 flags & ACPI_TABLE_ORIGIN_MASK) ==
297 ACPI_TABLE_ORIGIN_MAPPED) {
298 header =
299 acpi_os_map_memory(acpi_gbl_root_table_list.
300 tables[i].address,
301 sizeof(struct
302 acpi_table_header));
303 if (!header) {
304 return AE_NO_MEMORY;
305 }
306 ACPI_MEMCPY(out_table_header, header,
307 sizeof(struct acpi_table_header));
308 acpi_os_unmap_memory(header,
309 sizeof(struct
310 acpi_table_header));
311 } else {
312 return AE_NOT_FOUND;
313 }
314 } else {
315 ACPI_MEMCPY(out_table_header,
316 acpi_gbl_root_table_list.tables[i].pointer,
317 sizeof(struct acpi_table_header));
318 }
319 return (AE_OK);
320 }
321
322 return (AE_NOT_FOUND);
323}
324
325ACPI_EXPORT_SYMBOL(acpi_get_table_header)
326
327
328
329
330
331
332
333
334
335
336
337
338acpi_status acpi_unload_table_id(acpi_owner_id id)
339{
340 int i;
341 acpi_status status = AE_NOT_EXIST;
342
343 ACPI_FUNCTION_TRACE(acpi_unload_table_id);
344
345
346 for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
347 if (id != acpi_gbl_root_table_list.tables[i].owner_id) {
348 continue;
349 }
350
351
352
353
354
355
356 acpi_tb_delete_namespace_by_owner(i);
357 status = acpi_tb_release_owner_id(i);
358 acpi_tb_set_table_loaded_flag(i, FALSE);
359 break;
360 }
361 return_ACPI_STATUS(status);
362}
363
364ACPI_EXPORT_SYMBOL(acpi_unload_table_id)
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379acpi_status
380acpi_get_table(char *signature,
381 acpi_native_uint instance, struct acpi_table_header **out_table)
382{
383 acpi_native_uint i;
384 acpi_native_uint j;
385 acpi_status status;
386
387
388
389 if (!signature || !out_table) {
390 return (AE_BAD_PARAMETER);
391 }
392
393
394
395
396 for (i = 0, j = 0; i < acpi_gbl_root_table_list.count; i++) {
397 if (!ACPI_COMPARE_NAME
398 (&(acpi_gbl_root_table_list.tables[i].signature),
399 signature)) {
400 continue;
401 }
402
403 if (++j < instance) {
404 continue;
405 }
406
407 status =
408 acpi_tb_verify_table(&acpi_gbl_root_table_list.tables[i]);
409 if (ACPI_SUCCESS(status)) {
410 *out_table = acpi_gbl_root_table_list.tables[i].pointer;
411 }
412
413 if (!acpi_gbl_permanent_mmap) {
414 acpi_gbl_root_table_list.tables[i].pointer = NULL;
415 }
416
417 return (status);
418 }
419
420 return (AE_NOT_FOUND);
421}
422
423ACPI_EXPORT_SYMBOL(acpi_get_table)
424
425
426
427
428
429
430
431
432
433
434
435
436
437acpi_status
438acpi_get_table_by_index(acpi_native_uint table_index,
439 struct acpi_table_header ** table)
440{
441 acpi_status status;
442
443 ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
444
445
446
447 if (!table) {
448 return_ACPI_STATUS(AE_BAD_PARAMETER);
449 }
450
451 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
452
453
454
455 if (table_index >= acpi_gbl_root_table_list.count) {
456 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
457 return_ACPI_STATUS(AE_BAD_PARAMETER);
458 }
459
460 if (!acpi_gbl_root_table_list.tables[table_index].pointer) {
461
462
463
464 status =
465 acpi_tb_verify_table(&acpi_gbl_root_table_list.
466 tables[table_index]);
467 if (ACPI_FAILURE(status)) {
468 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
469 return_ACPI_STATUS(status);
470 }
471 }
472
473 *table = acpi_gbl_root_table_list.tables[table_index].pointer;
474 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
475 return_ACPI_STATUS(AE_OK);
476}
477
478ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
479
480
481
482
483
484
485
486
487
488
489
490
491
492static acpi_status acpi_tb_load_namespace(void)
493{
494 acpi_status status;
495 struct acpi_table_header *table;
496 acpi_native_uint i;
497
498 ACPI_FUNCTION_TRACE(tb_load_namespace);
499
500 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
501
502
503
504
505
506 if (!acpi_gbl_root_table_list.count ||
507 !ACPI_COMPARE_NAME(&
508 (acpi_gbl_root_table_list.
509 tables[ACPI_TABLE_INDEX_DSDT].signature),
510 ACPI_SIG_DSDT)
511 ||
512 ACPI_FAILURE(acpi_tb_verify_table
513 (&acpi_gbl_root_table_list.
514 tables[ACPI_TABLE_INDEX_DSDT]))) {
515 status = AE_NO_ACPI_TABLES;
516 goto unlock_and_exit;
517 }
518
519
520
521
522 status =
523 acpi_os_table_override(acpi_gbl_root_table_list.
524 tables[ACPI_TABLE_INDEX_DSDT].pointer,
525 &table);
526 if (ACPI_SUCCESS(status) && table) {
527
528
529
530 acpi_tb_delete_table(&acpi_gbl_root_table_list.
531 tables[ACPI_TABLE_INDEX_DSDT]);
532 acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].pointer =
533 table;
534 acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].length =
535 table->length;
536 acpi_gbl_root_table_list.tables[ACPI_TABLE_INDEX_DSDT].flags =
537 ACPI_TABLE_ORIGIN_UNKNOWN;
538
539 ACPI_INFO((AE_INFO, "Table DSDT replaced by host OS"));
540 acpi_tb_print_table_header(0, table);
541
542 if (no_auto_ssdt == 0) {
543 printk(KERN_WARNING "ACPI: DSDT override uses original SSDTs unless \"acpi_no_auto_ssdt\"");
544 }
545 }
546
547 status =
548 acpi_tb_verify_table(&acpi_gbl_root_table_list.
549 tables[ACPI_TABLE_INDEX_DSDT]);
550 if (ACPI_FAILURE(status)) {
551
552
553
554 status = AE_NO_ACPI_TABLES;
555 goto unlock_and_exit;
556 }
557
558 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
559
560
561
562
563 status = acpi_ns_load_table(ACPI_TABLE_INDEX_DSDT, acpi_gbl_root_node);
564 if (ACPI_FAILURE(status)) {
565 return_ACPI_STATUS(status);
566 }
567
568
569
570
571 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
572 for (i = 0; i < acpi_gbl_root_table_list.count; ++i) {
573 if ((!ACPI_COMPARE_NAME
574 (&(acpi_gbl_root_table_list.tables[i].signature),
575 ACPI_SIG_SSDT)
576 &&
577 !ACPI_COMPARE_NAME(&
578 (acpi_gbl_root_table_list.tables[i].
579 signature), ACPI_SIG_PSDT))
580 ||
581 ACPI_FAILURE(acpi_tb_verify_table
582 (&acpi_gbl_root_table_list.tables[i]))) {
583 continue;
584 }
585
586 if (no_auto_ssdt) {
587 printk(KERN_WARNING "ACPI: SSDT ignored due to \"acpi_no_auto_ssdt\"\n");
588 continue;
589 }
590
591
592
593 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
594 (void)acpi_ns_load_table(i, acpi_gbl_root_node);
595 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
596 }
597
598 ACPI_DEBUG_PRINT((ACPI_DB_INIT, "ACPI Tables successfully acquired\n"));
599
600 unlock_and_exit:
601 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
602 return_ACPI_STATUS(status);
603}
604
605
606
607
608
609
610
611
612
613
614
615
616
617acpi_status acpi_load_tables(void)
618{
619 acpi_status status;
620
621 ACPI_FUNCTION_TRACE(acpi_load_tables);
622
623
624
625
626 status = acpi_tb_load_namespace();
627 if (ACPI_FAILURE(status)) {
628 ACPI_EXCEPTION((AE_INFO, status,
629 "While loading namespace from ACPI tables"));
630 }
631
632 return_ACPI_STATUS(status);
633}
634
635ACPI_EXPORT_SYMBOL(acpi_load_tables)
636
637
638static int __init acpi_no_auto_ssdt_setup(char *s) {
639
640 printk(KERN_NOTICE "ACPI: SSDT auto-load disabled\n");
641
642 no_auto_ssdt = 1;
643
644 return 1;
645}
646
647__setup("acpi_no_auto_ssdt", acpi_no_auto_ssdt_setup);
648