0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #define EXPORT_ACPI_INTERFACES
0011
0012 #include <acpi/acpi.h>
0013 #include "accommon.h"
0014 #include "actables.h"
0015
0016 #define _COMPONENT ACPI_TABLES
0017 ACPI_MODULE_NAME("tbxface")
0018
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032 acpi_status acpi_allocate_root_table(u32 initial_table_count)
0033 {
0034
0035 acpi_gbl_root_table_list.max_table_count = initial_table_count;
0036 acpi_gbl_root_table_list.flags = ACPI_ROOT_ALLOW_RESIZE;
0037
0038 return (acpi_tb_resize_root_table_list());
0039 }
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051
0052
0053
0054
0055
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067 acpi_status ACPI_INIT_FUNCTION
0068 acpi_initialize_tables(struct acpi_table_desc *initial_table_array,
0069 u32 initial_table_count, u8 allow_resize)
0070 {
0071 acpi_physical_address rsdp_address;
0072 acpi_status status;
0073
0074 ACPI_FUNCTION_TRACE(acpi_initialize_tables);
0075
0076
0077
0078
0079
0080 if (!initial_table_array) {
0081 status = acpi_allocate_root_table(initial_table_count);
0082 if (ACPI_FAILURE(status)) {
0083 return_ACPI_STATUS(status);
0084 }
0085 } else {
0086
0087
0088 memset(initial_table_array, 0,
0089 (acpi_size)initial_table_count *
0090 sizeof(struct acpi_table_desc));
0091
0092 acpi_gbl_root_table_list.tables = initial_table_array;
0093 acpi_gbl_root_table_list.max_table_count = initial_table_count;
0094 acpi_gbl_root_table_list.flags = ACPI_ROOT_ORIGIN_UNKNOWN;
0095 if (allow_resize) {
0096 acpi_gbl_root_table_list.flags |=
0097 ACPI_ROOT_ALLOW_RESIZE;
0098 }
0099 }
0100
0101
0102
0103 rsdp_address = acpi_os_get_root_pointer();
0104 if (!rsdp_address) {
0105 return_ACPI_STATUS(AE_NOT_FOUND);
0106 }
0107
0108
0109
0110
0111
0112
0113 status = acpi_tb_parse_root_table(rsdp_address);
0114 return_ACPI_STATUS(status);
0115 }
0116
0117 ACPI_EXPORT_SYMBOL_INIT(acpi_initialize_tables)
0118
0119
0120
0121
0122
0123
0124
0125
0126
0127
0128
0129
0130
0131
0132
0133 acpi_status ACPI_INIT_FUNCTION acpi_reallocate_root_table(void)
0134 {
0135 acpi_status status;
0136 struct acpi_table_desc *table_desc;
0137 u32 i, j;
0138
0139 ACPI_FUNCTION_TRACE(acpi_reallocate_root_table);
0140
0141
0142
0143
0144
0145
0146
0147 if ((acpi_gbl_root_table_list.flags & ACPI_ROOT_ORIGIN_ALLOCATED) &&
0148 acpi_gbl_enable_table_validation) {
0149 return_ACPI_STATUS(AE_SUPPORT);
0150 }
0151
0152 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0153
0154
0155
0156
0157
0158
0159
0160 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; ++i) {
0161 table_desc = &acpi_gbl_root_table_list.tables[i];
0162 if (table_desc->pointer) {
0163 ACPI_ERROR((AE_INFO,
0164 "Table [%4.4s] is not invalidated during early boot stage",
0165 table_desc->signature.ascii));
0166 }
0167 }
0168
0169 if (!acpi_gbl_enable_table_validation) {
0170
0171
0172
0173
0174 acpi_gbl_enable_table_validation = TRUE;
0175 for (i = 0; i < acpi_gbl_root_table_list.current_table_count;
0176 ++i) {
0177 table_desc = &acpi_gbl_root_table_list.tables[i];
0178 if (!(table_desc->flags & ACPI_TABLE_IS_VERIFIED)) {
0179 status =
0180 acpi_tb_verify_temp_table(table_desc, NULL,
0181 &j);
0182 if (ACPI_FAILURE(status)) {
0183 acpi_tb_uninstall_table(table_desc);
0184 }
0185 }
0186 }
0187 }
0188
0189 acpi_gbl_root_table_list.flags |= ACPI_ROOT_ALLOW_RESIZE;
0190 status = acpi_tb_resize_root_table_list();
0191 acpi_gbl_root_table_list.flags |= ACPI_ROOT_ORIGIN_ALLOCATED;
0192
0193 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0194 return_ACPI_STATUS(status);
0195 }
0196
0197 ACPI_EXPORT_SYMBOL_INIT(acpi_reallocate_root_table)
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215 acpi_status
0216 acpi_get_table_header(char *signature,
0217 u32 instance, struct acpi_table_header *out_table_header)
0218 {
0219 u32 i;
0220 u32 j;
0221 struct acpi_table_header *header;
0222
0223
0224
0225 if (!signature || !out_table_header) {
0226 return (AE_BAD_PARAMETER);
0227 }
0228
0229
0230
0231 for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
0232 i++) {
0233 if (!ACPI_COMPARE_NAMESEG
0234 (&(acpi_gbl_root_table_list.tables[i].signature),
0235 signature)) {
0236 continue;
0237 }
0238
0239 if (++j < instance) {
0240 continue;
0241 }
0242
0243 if (!acpi_gbl_root_table_list.tables[i].pointer) {
0244 if ((acpi_gbl_root_table_list.tables[i].flags &
0245 ACPI_TABLE_ORIGIN_MASK) ==
0246 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL) {
0247 header =
0248 acpi_os_map_memory(acpi_gbl_root_table_list.
0249 tables[i].address,
0250 sizeof(struct
0251 acpi_table_header));
0252 if (!header) {
0253 return (AE_NO_MEMORY);
0254 }
0255
0256 memcpy(out_table_header, header,
0257 sizeof(struct acpi_table_header));
0258 acpi_os_unmap_memory(header,
0259 sizeof(struct
0260 acpi_table_header));
0261 } else {
0262 return (AE_NOT_FOUND);
0263 }
0264 } else {
0265 memcpy(out_table_header,
0266 acpi_gbl_root_table_list.tables[i].pointer,
0267 sizeof(struct acpi_table_header));
0268 }
0269 return (AE_OK);
0270 }
0271
0272 return (AE_NOT_FOUND);
0273 }
0274
0275 ACPI_EXPORT_SYMBOL(acpi_get_table_header)
0276
0277
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296 acpi_status
0297 acpi_get_table(char *signature,
0298 u32 instance, struct acpi_table_header ** out_table)
0299 {
0300 u32 i;
0301 u32 j;
0302 acpi_status status = AE_NOT_FOUND;
0303 struct acpi_table_desc *table_desc;
0304
0305
0306
0307 if (!signature || !out_table) {
0308 return (AE_BAD_PARAMETER);
0309 }
0310
0311
0312
0313
0314
0315
0316 *out_table = NULL;
0317
0318 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0319
0320
0321
0322 for (i = 0, j = 0; i < acpi_gbl_root_table_list.current_table_count;
0323 i++) {
0324 table_desc = &acpi_gbl_root_table_list.tables[i];
0325
0326 if (!ACPI_COMPARE_NAMESEG(&table_desc->signature, signature)) {
0327 continue;
0328 }
0329
0330 if (++j < instance) {
0331 continue;
0332 }
0333
0334 status = acpi_tb_get_table(table_desc, out_table);
0335 break;
0336 }
0337
0338 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0339 return (status);
0340 }
0341
0342 ACPI_EXPORT_SYMBOL(acpi_get_table)
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359 void acpi_put_table(struct acpi_table_header *table)
0360 {
0361 u32 i;
0362 struct acpi_table_desc *table_desc;
0363
0364 ACPI_FUNCTION_TRACE(acpi_put_table);
0365
0366 if (!table) {
0367 return_VOID;
0368 }
0369
0370 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0371
0372
0373
0374 for (i = 0; i < acpi_gbl_root_table_list.current_table_count; i++) {
0375 table_desc = &acpi_gbl_root_table_list.tables[i];
0376
0377 if (table_desc->pointer != table) {
0378 continue;
0379 }
0380
0381 acpi_tb_put_table(table_desc);
0382 break;
0383 }
0384
0385 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0386 return_VOID;
0387 }
0388
0389 ACPI_EXPORT_SYMBOL(acpi_put_table)
0390
0391
0392
0393
0394
0395
0396
0397
0398
0399
0400
0401
0402
0403
0404 acpi_status
0405 acpi_get_table_by_index(u32 table_index, struct acpi_table_header **out_table)
0406 {
0407 acpi_status status;
0408
0409 ACPI_FUNCTION_TRACE(acpi_get_table_by_index);
0410
0411
0412
0413 if (!out_table) {
0414 return_ACPI_STATUS(AE_BAD_PARAMETER);
0415 }
0416
0417
0418
0419
0420
0421
0422 *out_table = NULL;
0423
0424 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES);
0425
0426
0427
0428 if (table_index >= acpi_gbl_root_table_list.current_table_count) {
0429 status = AE_BAD_PARAMETER;
0430 goto unlock_and_exit;
0431 }
0432
0433 status =
0434 acpi_tb_get_table(&acpi_gbl_root_table_list.tables[table_index],
0435 out_table);
0436
0437 unlock_and_exit:
0438 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES);
0439 return_ACPI_STATUS(status);
0440 }
0441
0442 ACPI_EXPORT_SYMBOL(acpi_get_table_by_index)
0443
0444
0445
0446
0447
0448
0449
0450
0451
0452
0453
0454
0455
0456 acpi_status
0457 acpi_install_table_handler(acpi_table_handler handler, void *context)
0458 {
0459 acpi_status status;
0460
0461 ACPI_FUNCTION_TRACE(acpi_install_table_handler);
0462
0463 if (!handler) {
0464 return_ACPI_STATUS(AE_BAD_PARAMETER);
0465 }
0466
0467 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0468 if (ACPI_FAILURE(status)) {
0469 return_ACPI_STATUS(status);
0470 }
0471
0472
0473
0474 if (acpi_gbl_table_handler) {
0475 status = AE_ALREADY_EXISTS;
0476 goto cleanup;
0477 }
0478
0479
0480
0481 acpi_gbl_table_handler = handler;
0482 acpi_gbl_table_handler_context = context;
0483
0484 cleanup:
0485 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0486 return_ACPI_STATUS(status);
0487 }
0488
0489 ACPI_EXPORT_SYMBOL(acpi_install_table_handler)
0490
0491
0492
0493
0494
0495
0496
0497
0498
0499
0500
0501
0502
0503 acpi_status acpi_remove_table_handler(acpi_table_handler handler)
0504 {
0505 acpi_status status;
0506
0507 ACPI_FUNCTION_TRACE(acpi_remove_table_handler);
0508
0509 status = acpi_ut_acquire_mutex(ACPI_MTX_EVENTS);
0510 if (ACPI_FAILURE(status)) {
0511 return_ACPI_STATUS(status);
0512 }
0513
0514
0515
0516 if (!handler || handler != acpi_gbl_table_handler) {
0517 status = AE_BAD_PARAMETER;
0518 goto cleanup;
0519 }
0520
0521
0522
0523 acpi_gbl_table_handler = NULL;
0524
0525 cleanup:
0526 (void)acpi_ut_release_mutex(ACPI_MTX_EVENTS);
0527 return_ACPI_STATUS(status);
0528 }
0529
0530 ACPI_EXPORT_SYMBOL(acpi_remove_table_handler)