1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: tbutils - ACPI Table utilities 5 * 6 * Copyright (C) 2000 - 2023, Intel Corp. 7 * 8 *****************************************************************************/ 9 10 #include <acpi/acpi.h> 11 #include "accommon.h" 12 #include "actables.h" 13 14 #define _COMPONENT ACPI_TABLES 15 ACPI_MODULE_NAME("tbutils") 16 17 /* Local prototypes */ 18 static acpi_physical_address 19 acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size); 20 21 #if (!ACPI_REDUCED_HARDWARE) 22 /******************************************************************************* 23 * 24 * FUNCTION: acpi_tb_initialize_facs 25 * 26 * PARAMETERS: None 27 * 28 * RETURN: Status 29 * 30 * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global 31 * for accessing the Global Lock and Firmware Waking Vector 32 * 33 ******************************************************************************/ 34 35 acpi_status acpi_tb_initialize_facs(void) 36 { 37 struct acpi_table_facs *facs; 38 39 if (acpi_gbl_FADT.Xfacs && 40 (!acpi_gbl_FADT.facs 41 || !acpi_gbl_use32_bit_facs_addresses)) { 42 (void)acpi_get_table_by_index(acpi_gbl_xfacs_index, 43 ACPI_CAST_INDIRECT_PTR(struct 44 acpi_table_header, 45 &facs)); 46 acpi_gbl_FACS = facs; 47 } else if (acpi_gbl_FADT.facs) { 48 (void)acpi_get_table_by_index(acpi_gbl_facs_index, 49 ACPI_CAST_INDIRECT_PTR(struct 50 acpi_table_header, 51 &facs)); 52 acpi_gbl_FACS = facs; 53 } 54 55 /* If there is no FACS, just continue. There was already an error msg */ 56 57 return (AE_OK); 58 } 59 #endif /* !ACPI_REDUCED_HARDWARE */ 60 61 /******************************************************************************* 62 * 63 * FUNCTION: acpi_tb_check_dsdt_header 64 * 65 * PARAMETERS: None 66 * 67 * RETURN: None 68 * 69 * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect 70 * if the DSDT has been replaced from outside the OS and/or if 71 * the DSDT header has been corrupted. 72 * 73 ******************************************************************************/ 74 75 void acpi_tb_check_dsdt_header(void) 76 { 77 78 /* Compare original length and checksum to current values */ 79 80 if (acpi_gbl_original_dsdt_header.length != acpi_gbl_DSDT->length || 81 acpi_gbl_original_dsdt_header.checksum != acpi_gbl_DSDT->checksum) { 82 ACPI_BIOS_ERROR((AE_INFO, 83 "The DSDT has been corrupted or replaced - " 84 "old, new headers below")); 85 86 acpi_tb_print_table_header(0, &acpi_gbl_original_dsdt_header); 87 acpi_tb_print_table_header(0, acpi_gbl_DSDT); 88 89 ACPI_ERROR((AE_INFO, 90 "Please send DMI info to linux-acpi@vger.kernel.org\n" 91 "If system does not work as expected, please boot with acpi=copy_dsdt")); 92 93 /* Disable further error messages */ 94 95 acpi_gbl_original_dsdt_header.length = acpi_gbl_DSDT->length; 96 acpi_gbl_original_dsdt_header.checksum = 97 acpi_gbl_DSDT->checksum; 98 } 99 } 100 101 /******************************************************************************* 102 * 103 * FUNCTION: acpi_tb_copy_dsdt 104 * 105 * PARAMETERS: table_index - Index of installed table to copy 106 * 107 * RETURN: The copied DSDT 108 * 109 * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. 110 * Some very bad BIOSs are known to either corrupt the DSDT or 111 * install a new, bad DSDT. This copy works around the problem. 112 * 113 ******************************************************************************/ 114 115 struct acpi_table_header *acpi_tb_copy_dsdt(u32 table_index) 116 { 117 struct acpi_table_header *new_table; 118 struct acpi_table_desc *table_desc; 119 120 table_desc = &acpi_gbl_root_table_list.tables[table_index]; 121 122 new_table = ACPI_ALLOCATE(table_desc->length); 123 if (!new_table) { 124 ACPI_ERROR((AE_INFO, "Could not copy DSDT of length 0x%X", 125 table_desc->length)); 126 return (NULL); 127 } 128 129 memcpy(new_table, table_desc->pointer, table_desc->length); 130 acpi_tb_uninstall_table(table_desc); 131 132 acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list. 133 tables[acpi_gbl_dsdt_index], 134 ACPI_PTR_TO_PHYSADDR(new_table), 135 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL, 136 new_table); 137 138 ACPI_INFO(("Forced DSDT copy: length 0x%05X copied locally, original unmapped", new_table->length)); 139 140 return (new_table); 141 } 142 143 /******************************************************************************* 144 * 145 * FUNCTION: acpi_tb_get_root_table_entry 146 * 147 * PARAMETERS: table_entry - Pointer to the RSDT/XSDT table entry 148 * table_entry_size - sizeof 32 or 64 (RSDT or XSDT) 149 * 150 * RETURN: Physical address extracted from the root table 151 * 152 * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on 153 * both 32-bit and 64-bit platforms 154 * 155 * NOTE: acpi_physical_address is 32-bit on 32-bit platforms, 64-bit on 156 * 64-bit platforms. 157 * 158 ******************************************************************************/ 159 160 static acpi_physical_address 161 acpi_tb_get_root_table_entry(u8 *table_entry, u32 table_entry_size) 162 { 163 u32 address32; 164 u64 address64; 165 166 /* 167 * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): 168 * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT 169 */ 170 if (table_entry_size == ACPI_RSDT_ENTRY_SIZE) { 171 /* 172 * 32-bit platform, RSDT: Return 32-bit table entry 173 * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return 174 */ 175 ACPI_MOVE_32_TO_32(&address32, table_entry); 176 return address32; 177 } else { 178 /* 179 * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return 180 * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, 181 * return 64-bit 182 */ 183 ACPI_MOVE_64_TO_64(&address64, table_entry); 184 185 #if ACPI_MACHINE_WIDTH == 32 186 if (address64 > ACPI_UINT32_MAX) { 187 188 /* Will truncate 64-bit address to 32 bits, issue warning */ 189 190 ACPI_BIOS_WARNING((AE_INFO, 191 "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," 192 " truncating", 193 ACPI_FORMAT_UINT64(address64))); 194 } 195 #endif 196 return ((acpi_physical_address)(address64)); 197 } 198 } 199 200 /******************************************************************************* 201 * 202 * FUNCTION: acpi_tb_parse_root_table 203 * 204 * PARAMETERS: rsdp_address - Pointer to the RSDP 205 * 206 * RETURN: Status 207 * 208 * DESCRIPTION: This function is called to parse the Root System Description 209 * Table (RSDT or XSDT) 210 * 211 * NOTE: Tables are mapped (not copied) for efficiency. The FACS must 212 * be mapped and cannot be copied because it contains the actual 213 * memory location of the ACPI Global Lock. 214 * 215 ******************************************************************************/ 216 217 acpi_status ACPI_INIT_FUNCTION 218 acpi_tb_parse_root_table(acpi_physical_address rsdp_address) 219 { 220 struct acpi_table_rsdp *rsdp; 221 u32 table_entry_size; 222 u32 i; 223 u32 table_count; 224 struct acpi_table_header *table; 225 acpi_physical_address address; 226 u32 length; 227 u8 *table_entry; 228 acpi_status status; 229 u32 table_index; 230 231 ACPI_FUNCTION_TRACE(tb_parse_root_table); 232 233 /* Map the entire RSDP and extract the address of the RSDT or XSDT */ 234 235 rsdp = acpi_os_map_memory(rsdp_address, sizeof(struct acpi_table_rsdp)); 236 if (!rsdp) { 237 return_ACPI_STATUS(AE_NO_MEMORY); 238 } 239 240 acpi_tb_print_table_header(rsdp_address, 241 ACPI_CAST_PTR(struct acpi_table_header, 242 rsdp)); 243 244 /* Use XSDT if present and not overridden. Otherwise, use RSDT */ 245 246 if ((rsdp->revision > 1) && 247 rsdp->xsdt_physical_address && !acpi_gbl_do_not_use_xsdt) { 248 /* 249 * RSDP contains an XSDT (64-bit physical addresses). We must use 250 * the XSDT if the revision is > 1 and the XSDT pointer is present, 251 * as per the ACPI specification. 252 */ 253 address = (acpi_physical_address)rsdp->xsdt_physical_address; 254 table_entry_size = ACPI_XSDT_ENTRY_SIZE; 255 } else { 256 /* Root table is an RSDT (32-bit physical addresses) */ 257 258 address = (acpi_physical_address)rsdp->rsdt_physical_address; 259 table_entry_size = ACPI_RSDT_ENTRY_SIZE; 260 } 261 262 /* 263 * It is not possible to map more than one entry in some environments, 264 * so unmap the RSDP here before mapping other tables 265 */ 266 acpi_os_unmap_memory(rsdp, sizeof(struct acpi_table_rsdp)); 267 268 /* Map the RSDT/XSDT table header to get the full table length */ 269 270 table = acpi_os_map_memory(address, sizeof(struct acpi_table_header)); 271 if (!table) { 272 return_ACPI_STATUS(AE_NO_MEMORY); 273 } 274 275 acpi_tb_print_table_header(address, table); 276 277 /* 278 * Validate length of the table, and map entire table. 279 * Minimum length table must contain at least one entry. 280 */ 281 length = table->length; 282 acpi_os_unmap_memory(table, sizeof(struct acpi_table_header)); 283 284 if (length < (sizeof(struct acpi_table_header) + table_entry_size)) { 285 ACPI_BIOS_ERROR((AE_INFO, 286 "Invalid table length 0x%X in RSDT/XSDT", 287 length)); 288 return_ACPI_STATUS(AE_INVALID_TABLE_LENGTH); 289 } 290 291 table = acpi_os_map_memory(address, length); 292 if (!table) { 293 return_ACPI_STATUS(AE_NO_MEMORY); 294 } 295 296 /* Validate the root table checksum */ 297 298 status = acpi_ut_verify_checksum(table, length); 299 if (ACPI_FAILURE(status)) { 300 acpi_os_unmap_memory(table, length); 301 return_ACPI_STATUS(status); 302 } 303 304 /* Get the number of entries and pointer to first entry */ 305 306 table_count = (u32)((table->length - sizeof(struct acpi_table_header)) / 307 table_entry_size); 308 table_entry = ACPI_ADD_PTR(u8, table, sizeof(struct acpi_table_header)); 309 310 /* Initialize the root table array from the RSDT/XSDT */ 311 312 for (i = 0; i < table_count; i++) { 313 314 /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ 315 316 address = 317 acpi_tb_get_root_table_entry(table_entry, table_entry_size); 318 319 /* Skip NULL entries in RSDT/XSDT */ 320 321 if (!address) { 322 goto next_table; 323 } 324 325 status = acpi_tb_install_standard_table(address, 326 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, 327 NULL, FALSE, TRUE, 328 &table_index); 329 330 if (ACPI_SUCCESS(status) && 331 ACPI_COMPARE_NAMESEG(&acpi_gbl_root_table_list. 332 tables[table_index].signature, 333 ACPI_SIG_FADT)) { 334 acpi_gbl_fadt_index = table_index; 335 acpi_tb_parse_fadt(); 336 } 337 338 next_table: 339 340 table_entry += table_entry_size; 341 } 342 343 acpi_os_unmap_memory(table, length); 344 return_ACPI_STATUS(AE_OK); 345 } 346 347 /******************************************************************************* 348 * 349 * FUNCTION: acpi_tb_get_table 350 * 351 * PARAMETERS: table_desc - Table descriptor 352 * out_table - Where the pointer to the table is returned 353 * 354 * RETURN: Status and pointer to the requested table 355 * 356 * DESCRIPTION: Increase a reference to a table descriptor and return the 357 * validated table pointer. 358 * If the table descriptor is an entry of the root table list, 359 * this API must be invoked with ACPI_MTX_TABLES acquired. 360 * 361 ******************************************************************************/ 362 363 acpi_status 364 acpi_tb_get_table(struct acpi_table_desc *table_desc, 365 struct acpi_table_header **out_table) 366 { 367 acpi_status status; 368 369 ACPI_FUNCTION_TRACE(acpi_tb_get_table); 370 371 if (table_desc->validation_count == 0) { 372 373 /* Table need to be "VALIDATED" */ 374 375 status = acpi_tb_validate_table(table_desc); 376 if (ACPI_FAILURE(status)) { 377 return_ACPI_STATUS(status); 378 } 379 } 380 381 if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) { 382 table_desc->validation_count++; 383 384 /* 385 * Detect validation_count overflows to ensure that the warning 386 * message will only be printed once. 387 */ 388 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) { 389 ACPI_WARNING((AE_INFO, 390 "Table %p, Validation count overflows\n", 391 table_desc)); 392 } 393 } 394 395 *out_table = table_desc->pointer; 396 return_ACPI_STATUS(AE_OK); 397 } 398 399 /******************************************************************************* 400 * 401 * FUNCTION: acpi_tb_put_table 402 * 403 * PARAMETERS: table_desc - Table descriptor 404 * 405 * RETURN: None 406 * 407 * DESCRIPTION: Decrease a reference to a table descriptor and release the 408 * validated table pointer if no references. 409 * If the table descriptor is an entry of the root table list, 410 * this API must be invoked with ACPI_MTX_TABLES acquired. 411 * 412 ******************************************************************************/ 413 414 void acpi_tb_put_table(struct acpi_table_desc *table_desc) 415 { 416 417 ACPI_FUNCTION_TRACE(acpi_tb_put_table); 418 419 if (table_desc->validation_count < ACPI_MAX_TABLE_VALIDATIONS) { 420 table_desc->validation_count--; 421 422 /* 423 * Detect validation_count underflows to ensure that the warning 424 * message will only be printed once. 425 */ 426 if (table_desc->validation_count >= ACPI_MAX_TABLE_VALIDATIONS) { 427 ACPI_WARNING((AE_INFO, 428 "Table %p, Validation count underflows\n", 429 table_desc)); 430 return_VOID; 431 } 432 } 433 434 if (table_desc->validation_count == 0) { 435 436 /* Table need to be "INVALIDATED" */ 437 438 acpi_tb_invalidate_table(table_desc); 439 } 440 441 return_VOID; 442 } 443