1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 /****************************************************************************** 3 * 4 * Module Name: tbinstal - ACPI table installation and removal 5 * 6 * Copyright (C) 2000 - 2021, 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("tbinstal") 16 17 /******************************************************************************* 18 * 19 * FUNCTION: acpi_tb_install_table_with_override 20 * 21 * PARAMETERS: new_table_desc - New table descriptor to install 22 * override - Whether override should be performed 23 * table_index - Where the table index is returned 24 * 25 * RETURN: None 26 * 27 * DESCRIPTION: Install an ACPI table into the global data structure. The 28 * table override mechanism is called to allow the host 29 * OS to replace any table before it is installed in the root 30 * table array. 31 * 32 ******************************************************************************/ 33 void 34 acpi_tb_install_table_with_override(struct acpi_table_desc *new_table_desc, 35 u8 override, u32 *table_index) 36 { 37 u32 i; 38 acpi_status status; 39 40 status = acpi_tb_get_next_table_descriptor(&i, NULL); 41 if (ACPI_FAILURE(status)) { 42 return; 43 } 44 45 /* 46 * ACPI Table Override: 47 * 48 * Before we install the table, let the host OS override it with a new 49 * one if desired. Any table within the RSDT/XSDT can be replaced, 50 * including the DSDT which is pointed to by the FADT. 51 */ 52 if (override) { 53 acpi_tb_override_table(new_table_desc); 54 } 55 56 acpi_tb_init_table_descriptor(&acpi_gbl_root_table_list.tables[i], 57 new_table_desc->address, 58 new_table_desc->flags, 59 new_table_desc->pointer); 60 61 acpi_tb_print_table_header(new_table_desc->address, 62 new_table_desc->pointer); 63 64 /* This synchronizes acpi_gbl_dsdt_index */ 65 66 *table_index = i; 67 68 /* Set the global integer width (based upon revision of the DSDT) */ 69 70 if (i == acpi_gbl_dsdt_index) { 71 acpi_ut_set_integer_width(new_table_desc->pointer->revision); 72 } 73 } 74 75 /******************************************************************************* 76 * 77 * FUNCTION: acpi_tb_install_standard_table 78 * 79 * PARAMETERS: address - Address of the table (might be a virtual 80 * address depending on the table_flags) 81 * flags - Flags for the table 82 * reload - Whether reload should be performed 83 * override - Whether override should be performed 84 * table_index - Where the table index is returned 85 * 86 * RETURN: Status 87 * 88 * DESCRIPTION: This function is called to verify and install an ACPI table. 89 * When this function is called by "Load" or "LoadTable" opcodes, 90 * or by acpi_load_table() API, the "Reload" parameter is set. 91 * After successfully returning from this function, table is 92 * "INSTALLED" but not "VALIDATED". 93 * 94 ******************************************************************************/ 95 96 acpi_status 97 acpi_tb_install_standard_table(acpi_physical_address address, 98 u8 flags, 99 u8 reload, u8 override, u32 *table_index) 100 { 101 u32 i; 102 acpi_status status = AE_OK; 103 struct acpi_table_desc new_table_desc; 104 105 ACPI_FUNCTION_TRACE(tb_install_standard_table); 106 107 /* Acquire a temporary table descriptor for validation */ 108 109 status = acpi_tb_acquire_temp_table(&new_table_desc, address, flags); 110 if (ACPI_FAILURE(status)) { 111 ACPI_ERROR((AE_INFO, 112 "Could not acquire table length at %8.8X%8.8X", 113 ACPI_FORMAT_UINT64(address))); 114 return_ACPI_STATUS(status); 115 } 116 117 /* 118 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 119 * be useful for debugging ACPI problems on some machines. 120 */ 121 if (!reload && 122 acpi_gbl_disable_ssdt_table_install && 123 ACPI_COMPARE_NAMESEG(&new_table_desc.signature, ACPI_SIG_SSDT)) { 124 ACPI_INFO(("Ignoring installation of %4.4s at %8.8X%8.8X", 125 new_table_desc.signature.ascii, 126 ACPI_FORMAT_UINT64(address))); 127 goto release_and_exit; 128 } 129 130 /* Acquire the table lock */ 131 132 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 133 134 /* Validate and verify a table before installation */ 135 136 status = acpi_tb_verify_temp_table(&new_table_desc, NULL, &i); 137 if (ACPI_FAILURE(status)) { 138 if (status == AE_CTRL_TERMINATE) { 139 /* 140 * Table was unloaded, allow it to be reloaded. 141 * As we are going to return AE_OK to the caller, we should 142 * take the responsibility of freeing the input descriptor. 143 * Refill the input descriptor to ensure 144 * acpi_tb_install_table_with_override() can be called again to 145 * indicate the re-installation. 146 */ 147 acpi_tb_uninstall_table(&new_table_desc); 148 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 149 *table_index = i; 150 return_ACPI_STATUS(AE_OK); 151 } 152 goto unlock_and_exit; 153 } 154 155 /* Add the table to the global root table list */ 156 157 acpi_tb_install_table_with_override(&new_table_desc, override, 158 table_index); 159 160 /* Invoke table handler */ 161 162 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 163 acpi_tb_notify_table(ACPI_TABLE_EVENT_INSTALL, new_table_desc.pointer); 164 (void)acpi_ut_acquire_mutex(ACPI_MTX_TABLES); 165 166 unlock_and_exit: 167 168 /* Release the table lock */ 169 170 (void)acpi_ut_release_mutex(ACPI_MTX_TABLES); 171 172 release_and_exit: 173 174 /* Release the temporary table descriptor */ 175 176 acpi_tb_release_temp_table(&new_table_desc); 177 return_ACPI_STATUS(status); 178 } 179 180 /******************************************************************************* 181 * 182 * FUNCTION: acpi_tb_override_table 183 * 184 * PARAMETERS: old_table_desc - Validated table descriptor to be 185 * overridden 186 * 187 * RETURN: None 188 * 189 * DESCRIPTION: Attempt table override by calling the OSL override functions. 190 * Note: If the table is overridden, then the entire new table 191 * is acquired and returned by this function. 192 * Before/after invocation, the table descriptor is in a state 193 * that is "VALIDATED". 194 * 195 ******************************************************************************/ 196 197 void acpi_tb_override_table(struct acpi_table_desc *old_table_desc) 198 { 199 acpi_status status; 200 struct acpi_table_desc new_table_desc; 201 struct acpi_table_header *table; 202 acpi_physical_address address; 203 u32 length; 204 ACPI_ERROR_ONLY(char *override_type); 205 206 /* (1) Attempt logical override (returns a logical address) */ 207 208 status = acpi_os_table_override(old_table_desc->pointer, &table); 209 if (ACPI_SUCCESS(status) && table) { 210 acpi_tb_acquire_temp_table(&new_table_desc, 211 ACPI_PTR_TO_PHYSADDR(table), 212 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 213 ACPI_ERROR_ONLY(override_type = "Logical"); 214 goto finish_override; 215 } 216 217 /* (2) Attempt physical override (returns a physical address) */ 218 219 status = acpi_os_physical_table_override(old_table_desc->pointer, 220 &address, &length); 221 if (ACPI_SUCCESS(status) && address && length) { 222 acpi_tb_acquire_temp_table(&new_table_desc, address, 223 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 224 ACPI_ERROR_ONLY(override_type = "Physical"); 225 goto finish_override; 226 } 227 228 return; /* There was no override */ 229 230 finish_override: 231 232 /* 233 * Validate and verify a table before overriding, no nested table 234 * duplication check as it's too complicated and unnecessary. 235 */ 236 status = acpi_tb_verify_temp_table(&new_table_desc, NULL, NULL); 237 if (ACPI_FAILURE(status)) { 238 return; 239 } 240 241 ACPI_INFO(("%4.4s 0x%8.8X%8.8X" 242 " %s table override, new table: 0x%8.8X%8.8X", 243 old_table_desc->signature.ascii, 244 ACPI_FORMAT_UINT64(old_table_desc->address), 245 override_type, ACPI_FORMAT_UINT64(new_table_desc.address))); 246 247 /* We can now uninstall the original table */ 248 249 acpi_tb_uninstall_table(old_table_desc); 250 251 /* 252 * Replace the original table descriptor and keep its state as 253 * "VALIDATED". 254 */ 255 acpi_tb_init_table_descriptor(old_table_desc, new_table_desc.address, 256 new_table_desc.flags, 257 new_table_desc.pointer); 258 acpi_tb_validate_temp_table(old_table_desc); 259 260 /* Release the temporary table descriptor */ 261 262 acpi_tb_release_temp_table(&new_table_desc); 263 } 264 265 /******************************************************************************* 266 * 267 * FUNCTION: acpi_tb_uninstall_table 268 * 269 * PARAMETERS: table_desc - Table descriptor 270 * 271 * RETURN: None 272 * 273 * DESCRIPTION: Delete one internal ACPI table 274 * 275 ******************************************************************************/ 276 277 void acpi_tb_uninstall_table(struct acpi_table_desc *table_desc) 278 { 279 280 ACPI_FUNCTION_TRACE(tb_uninstall_table); 281 282 /* Table must be installed */ 283 284 if (!table_desc->address) { 285 return_VOID; 286 } 287 288 acpi_tb_invalidate_table(table_desc); 289 290 if ((table_desc->flags & ACPI_TABLE_ORIGIN_MASK) == 291 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) { 292 ACPI_FREE(ACPI_PHYSADDR_TO_PTR(table_desc->address)); 293 } 294 295 table_desc->address = ACPI_PTR_TO_PHYSADDR(NULL); 296 return_VOID; 297 } 298