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