0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "actables.h"
0013
0014 #define _COMPONENT ACPI_TABLES
0015 ACPI_MODULE_NAME("tbutils")
0016
0017
0018 static acpi_physical_address
0019 acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size);
0020
0021 #if (!ACPI_REDUCED_HARDWARE)
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035 acpi_status acpi_tb_initialize_facs(void)
0036 {
0037 struct acpi_table_facs *facs;
0038
0039
0040
0041 if (acpi_gbl_reduced_hardware) {
0042 acpi_gbl_FACS = NULL;
0043 return (AE_OK);
0044 } else if (acpi_gbl_FADT.Xfacs &&
0045 (!acpi_gbl_FADT.facs
0046 || !acpi_gbl_use32_bit_facs_addresses)) {
0047 (void)acpi_get_table_by_index(acpi_gbl_xfacs_index,
0048 ACPI_CAST_INDIRECT_PTR(struct
0049 acpi_table_header,
0050 &facs));
0051 acpi_gbl_FACS = facs;
0052 } else if (acpi_gbl_FADT.facs) {
0053 (void)acpi_get_table_by_index(acpi_gbl_facs_index,
0054 ACPI_CAST_INDIRECT_PTR(struct
0055 acpi_table_header,
0056 &facs));
0057 acpi_gbl_FACS = facs;
0058 }
0059
0060
0061
0062 return (AE_OK);
0063 }
0064 #endif
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077
0078
0079
0080 void acpi_tb_check_dsdt_header(void)
0081 {
0082
0083
0084
0085 if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length ||
0086 acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) {
0087 ACPI_BIOS_ERROR((AE_INFO,
0088 "The DSDT has been corrupted or replaced - "
0089 "old, new headers below"));
0090
0091 acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header);
0092 acpi_tb_print_table_header(0, acpi_gbl_DSDT);
0093
0094 ACPI_ERROR((AE_INFO,
0095 "Please send DMI info to linux-acpi@vger.kernel.org\n"
0096 "If system does not work as expected, please boot with acpi=copy_dsdt"));
0097
0098
0099
0100 acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length;
0101 acpi_gbl_original_dsdt_header.checksum =
0102 acpi_gbl_DSDT->checksum;
0103 }
0104 }
0105
0106
0107
0108
0109
0110
0111
0112
0113
0114
0115
0116
0117
0118
0119
0120 struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index)
0121 {
0122 struct acpi_table_header *new_table;
0123 struct acpi_table_desc *table_desc;
0124
0125 table_desc = &acpi_gbl_root_table_list.tables[table_index];
0126
0127 new_table = ACPI_ALLOCATE(table_desc->length);
0128 if (!new_table) {
0129 ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X",
0130 table_desc->length));
0131 return (NULL);
0132 }
0133
0134 memcpy(new_table, table_desc->pointer, table_desc->length);
0135 acpi_tb_uninstall_table(table_desc);
0136
0137 acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.
0138 tables[acpi_gbl_dsdt_index],
0139 ACPI_PTR_TO_PHYSADDR(new_table),
0140 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL,
0141 new_table);
0142
0143 ACPI_INFO(("Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length));
0144
0145 return (new_table);
0146 }
0147
0148
0149
0150
0151
0152
0153
0154
0155
0156
0157
0158
0159
0160
0161
0162
0163
0164
0165 static acpi_physical_address
0166 acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size)
0167 {
0168 u64 address64;
0169
0170
0171
0172
0173
0174 if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) {
0175
0176
0177
0178
0179 return ((acpi_physical_address)
0180 (*ACPI_CAST_PTR(u32, table_entry)));
0181 } else {
0182
0183
0184
0185
0186
0187 ACPI_MOVE_64_TO_64(&address64, table_entry);
0188
0189 #if ACPI_MACHINE_WIDTH == 32
0190 if (address64 > ACPI_UINT32_MAX) {
0191
0192
0193
0194 ACPI_BIOS_WARNING((AE_INFO,
0195 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X),"
0196 " truncating",
0197 ACPI_FORMAT_UINT64(address64)));
0198 }
0199 #endif
0200 return ((acpi_physical_address)(address64));
0201 }
0202 }
0203
0204
0205
0206
0207
0208
0209
0210
0211
0212
0213
0214
0215
0216
0217
0218
0219
0220
0221 acpi_status ACPI_INIT_FUNCTION
0222 acpi_tb_parse_root_table(acpi_physical_address rsdp_address)
0223 {
0224 struct acpi_table_rsdp *rsdp;
0225 u32 table_entry_size;
0226 u32 i;
0227 u32 table_count;
0228 struct acpi_table_header *table;
0229 acpi_physical_address address;
0230 u32 length;
0231 u8 *table_entry;
0232 acpi_status status;
0233 u32 table_index;
0234
0235 ACPI_FUNCTION_TRACE(tb_parse_root_table);
0236
0237
0238
0239 rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp));
0240 if (!rsdp) {
0241 return_ACPI_STATUS(AE_NO_MEMORY);
0242 }
0243
0244 acpi_tb_print_table_header(rsdp_address,
0245 ACPI_CAST_PTR(struct acpi_table_header,
0246 rsdp));
0247
0248
0249
0250 if ((rsdp->revision > 1) &&
0251 rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) {
0252
0253
0254
0255
0256
0257 address = (acpi_physical_address)rsdp->xsdt_physical_address;
0258 table_entry_size = ACPI_XSDT_ENTRY_SIZE;
0259 } else {
0260
0261
0262 address = (acpi_physical_address)rsdp->rsdt_physical_address;
0263 table_entry_size = ACPI_RSDT_ENTRY_SIZE;
0264 }
0265
0266
0267
0268
0269
0270 acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp));
0271
0272
0273
0274 table = acpi_os_map_memory(address, sizeof(struct acpi_table_header));
0275 if (!table) {
0276 return_ACPI_STATUS(AE_NO_MEMORY);
0277 }
0278
0279 acpi_tb_print_table_header(address, table);
0280
0281
0282
0283
0284
0285 length = table->length;
0286 acpi_os_unmap_memory(table, sizeof(struct acpi_table_header));
0287
0288 if (length < (sizeof(struct acpi_table_header) + table_entry_size)) {
0289 ACPI_BIOS_ERROR((AE_INFO,
0290 "Invalid table length 0x%X in RSDT/XSDT",
0291 length));
0292 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH);
0293 }
0294
0295 table = acpi_os_map_memory(address, length);
0296 if (!table) {
0297 return_ACPI_STATUS(AE_NO_MEMORY);
0298 }
0299
0300
0301
0302 status = acpi_tb_verify_checksum(table, length);
0303 if (ACPI_FAILURE(status)) {
0304 acpi_os_unmap_memory(table, length);
0305 return_ACPI_STATUS(status);
0306 }
0307
0308
0309
0310 table_count = (u32)((table->length - sizeof(struct acpi_table_header)) /
0311 table_entry_size);
0312 table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header));
0313
0314
0315
0316 for (i = 0; i < table_count; i++) {
0317
0318
0319
0320 address =
0321 acpi_tb_get_root_table_entry(table_entry, table_entry_size);
0322
0323
0324
0325 if (!address) {
0326 goto next_table;
0327 }
0328
0329 status = acpi_tb_install_standard_table(address,
0330 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL,
0331 NULL, FALSE, TRUE,
0332 &table_index);
0333
0334 if (ACPI_SUCCESS(status) &&
0335 ACPI_COMPARE_NAMESEG(&acpi_gbl_root_table_list.
0336 tables[table_index].signature,
0337 ACPI_SIG_FADT)) {
0338 acpi_gbl_fadt_index = table_index;
0339 acpi_tb_parse_fadt();
0340 }
0341
0342 next_table:
0343
0344 table_entry += table_entry_size;
0345 }
0346
0347 acpi_os_unmap_memory(table, length);
0348 return_ACPI_STATUS(AE_OK);
0349 }
0350
0351
0352
0353
0354
0355
0356
0357
0358
0359
0360
0361
0362
0363
0364
0365
0366
0367 acpi_status
0368 acpi_tb_get_table(struct acpi_table_desc *table_desc,
0369 struct acpi_table_header **out_table)
0370 {
0371 acpi_status status;
0372
0373 ACPI_FUNCTION_TRACE(acpi_tb_get_table);
0374
0375 if (table_desc->validation_count == 0) {
0376
0377
0378
0379 status = acpi_tb_validate_table(table_desc);
0380 if (ACPI_FAILURE(status)) {
0381 return_ACPI_STATUS(status);
0382 }
0383 }
0384
0385 if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
0386 table_desc->validation_count++;
0387
0388
0389
0390
0391
0392 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
0393 ACPI_WARNING((AE_INFO,
0394 "Table %p, Validation count overflows\n",
0395 table_desc));
0396 }
0397 }
0398
0399 *out_table = table_desc->pointer;
0400 return_ACPI_STATUS(AE_OK);
0401 }
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417
0418 void acpi_tb_put_table(struct acpi_table_desc *table_desc)
0419 {
0420
0421 ACPI_FUNCTION_TRACE(acpi_tb_put_table);
0422
0423 if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) {
0424 table_desc->validation_count--;
0425
0426
0427
0428
0429
0430 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) {
0431 ACPI_WARNING((AE_INFO,
0432 "Table %p, Validation count underflows\n",
0433 table_desc));
0434 return_VOID;
0435 }
0436 }
0437
0438 if (table_desc->validation_count == 0) {
0439
0440
0441
0442 acpi_tb_invalidate_table(table_desc);
0443 }
0444
0445 return_VOID;
0446 }