1 /****************************************************************************** 2 * 3 * Module Name: tbinstal - ACPI table installation and removal 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2022, Intel Corp. 9 * All rights reserved. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions, and the following disclaimer, 16 * without modification. 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18 * substantially similar to the "NO WARRANTY" disclaimer below 19 * ("Disclaimer") and any redistribution must be conditioned upon 20 * including a substantially similar Disclaimer requirement for further 21 * binary redistribution. 22 * 3. Neither the names of the above-listed copyright holders nor the names 23 * of any contributors may be used to endorse or promote products derived 24 * from this software without specific prior written permission. 25 * 26 * Alternatively, this software may be distributed under the terms of the 27 * GNU General Public License ("GPL") version 2 as published by the Free 28 * Software Foundation. 29 * 30 * NO WARRANTY 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41 * POSSIBILITY OF SUCH DAMAGES. 42 */ 43 44 #include "acpi.h" 45 #include "accommon.h" 46 #include "actables.h" 47 48 #define _COMPONENT ACPI_TABLES 49 ACPI_MODULE_NAME ("tbinstal") 50 51 52 /******************************************************************************* 53 * 54 * FUNCTION: AcpiTbInstallTableWithOverride 55 * 56 * PARAMETERS: NewTableDesc - New table descriptor to install 57 * Override - Whether override should be performed 58 * TableIndex - Where the table index is returned 59 * 60 * RETURN: None 61 * 62 * DESCRIPTION: Install an ACPI table into the global data structure. The 63 * table override mechanism is called to allow the host 64 * OS to replace any table before it is installed in the root 65 * table array. 66 * 67 ******************************************************************************/ 68 69 void 70 AcpiTbInstallTableWithOverride ( 71 ACPI_TABLE_DESC *NewTableDesc, 72 BOOLEAN Override, 73 UINT32 *TableIndex) 74 { 75 UINT32 i; 76 ACPI_STATUS Status; 77 78 79 Status = AcpiTbGetNextTableDescriptor (&i, NULL); 80 if (ACPI_FAILURE (Status)) 81 { 82 return; 83 } 84 85 /* 86 * ACPI Table Override: 87 * 88 * Before we install the table, let the host OS override it with a new 89 * one if desired. Any table within the RSDT/XSDT can be replaced, 90 * including the DSDT which is pointed to by the FADT. 91 */ 92 if (Override) 93 { 94 AcpiTbOverrideTable (NewTableDesc); 95 } 96 97 AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[i], 98 NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer); 99 100 AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer); 101 102 /* This synchronizes AcpiGbl_DsdtIndex */ 103 104 *TableIndex = i; 105 106 /* Set the global integer width (based upon revision of the DSDT) */ 107 108 if (i == AcpiGbl_DsdtIndex) 109 { 110 AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision); 111 } 112 } 113 114 115 /******************************************************************************* 116 * 117 * FUNCTION: AcpiTbInstallStandardTable 118 * 119 * PARAMETERS: Address - Address of the table (might be a virtual 120 * address depending on the TableFlags) 121 * Flags - Flags for the table 122 * Table - Pointer to the table (required for virtual 123 * origins, optional for physical) 124 * Reload - Whether reload should be performed 125 * Override - Whether override should be performed 126 * TableIndex - Where the table index is returned 127 * 128 * RETURN: Status 129 * 130 * DESCRIPTION: This function is called to verify and install an ACPI table. 131 * When this function is called by "Load" or "LoadTable" opcodes, 132 * or by AcpiLoadTable() API, the "Reload" parameter is set. 133 * After successfully returning from this function, table is 134 * "INSTALLED" but not "VALIDATED". 135 * 136 ******************************************************************************/ 137 138 ACPI_STATUS 139 AcpiTbInstallStandardTable ( 140 ACPI_PHYSICAL_ADDRESS Address, 141 UINT8 Flags, 142 ACPI_TABLE_HEADER *Table, 143 BOOLEAN Reload, 144 BOOLEAN Override, 145 UINT32 *TableIndex) 146 { 147 UINT32 i; 148 ACPI_STATUS Status = AE_OK; 149 ACPI_TABLE_DESC NewTableDesc; 150 151 152 ACPI_FUNCTION_TRACE (TbInstallStandardTable); 153 154 155 /* Acquire a temporary table descriptor for validation */ 156 157 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags, Table); 158 if (ACPI_FAILURE (Status)) 159 { 160 ACPI_ERROR ((AE_INFO, 161 "Could not acquire table length at %8.8X%8.8X", 162 ACPI_FORMAT_UINT64 (Address))); 163 return_ACPI_STATUS (Status); 164 } 165 166 /* 167 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 168 * be useful for debugging ACPI problems on some machines. 169 */ 170 if (!Reload && 171 AcpiGbl_DisableSsdtTableInstall && 172 ACPI_COMPARE_NAMESEG (&NewTableDesc.Signature, ACPI_SIG_SSDT)) 173 { 174 ACPI_INFO (( 175 "Ignoring installation of %4.4s at %8.8X%8.8X", 176 NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); 177 goto ReleaseAndExit; 178 } 179 180 /* Acquire the table lock */ 181 182 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 183 184 /* Validate and verify a table before installation */ 185 186 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i); 187 if (ACPI_FAILURE (Status)) 188 { 189 if (Status == AE_CTRL_TERMINATE) 190 { 191 /* 192 * Table was unloaded, allow it to be reloaded. 193 * As we are going to return AE_OK to the caller, we should 194 * take the responsibility of freeing the input descriptor. 195 * Refill the input descriptor to ensure 196 * AcpiTbInstallTableWithOverride() can be called again to 197 * indicate the re-installation. 198 */ 199 AcpiTbUninstallTable (&NewTableDesc); 200 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 201 *TableIndex = i; 202 return_ACPI_STATUS (AE_OK); 203 } 204 goto UnlockAndExit; 205 } 206 207 /* Add the table to the global root table list */ 208 209 AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); 210 211 /* Invoke table handler */ 212 213 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 214 AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer); 215 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 216 217 UnlockAndExit: 218 219 /* Release the table lock */ 220 221 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 222 223 ReleaseAndExit: 224 225 /* Release the temporary table descriptor */ 226 227 AcpiTbReleaseTempTable (&NewTableDesc); 228 return_ACPI_STATUS (Status); 229 } 230 231 232 /******************************************************************************* 233 * 234 * FUNCTION: AcpiTbOverrideTable 235 * 236 * PARAMETERS: OldTableDesc - Validated table descriptor to be 237 * overridden 238 * 239 * RETURN: None 240 * 241 * DESCRIPTION: Attempt table override by calling the OSL override functions. 242 * Note: If the table is overridden, then the entire new table 243 * is acquired and returned by this function. 244 * Before/after invocation, the table descriptor is in a state 245 * that is "VALIDATED". 246 * 247 ******************************************************************************/ 248 249 void 250 AcpiTbOverrideTable ( 251 ACPI_TABLE_DESC *OldTableDesc) 252 { 253 ACPI_STATUS Status; 254 ACPI_TABLE_DESC NewTableDesc; 255 ACPI_TABLE_HEADER *Table; 256 ACPI_PHYSICAL_ADDRESS Address; 257 UINT32 Length; 258 ACPI_ERROR_ONLY (char *OverrideType); 259 260 261 /* (1) Attempt logical override (returns a logical address) */ 262 263 Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); 264 if (ACPI_SUCCESS (Status) && Table) 265 { 266 AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), 267 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL, Table); 268 ACPI_ERROR_ONLY (OverrideType = "Logical"); 269 goto FinishOverride; 270 } 271 272 /* (2) Attempt physical override (returns a physical address) */ 273 274 Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, 275 &Address, &Length); 276 if (ACPI_SUCCESS (Status) && Address && Length) 277 { 278 AcpiTbAcquireTempTable (&NewTableDesc, Address, 279 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL); 280 ACPI_ERROR_ONLY (OverrideType = "Physical"); 281 goto FinishOverride; 282 } 283 284 return; /* There was no override */ 285 286 287 FinishOverride: 288 289 /* 290 * Validate and verify a table before overriding, no nested table 291 * duplication check as it's too complicated and unnecessary. 292 */ 293 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, NULL); 294 if (ACPI_FAILURE (Status)) 295 { 296 return; 297 } 298 299 ACPI_INFO (("%4.4s 0x%8.8X%8.8X" 300 " %s table override, new table: 0x%8.8X%8.8X", 301 OldTableDesc->Signature.Ascii, 302 ACPI_FORMAT_UINT64 (OldTableDesc->Address), 303 OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); 304 305 /* We can now uninstall the original table */ 306 307 AcpiTbUninstallTable (OldTableDesc); 308 309 /* 310 * Replace the original table descriptor and keep its state as 311 * "VALIDATED". 312 */ 313 AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, 314 NewTableDesc.Flags, NewTableDesc.Pointer); 315 AcpiTbValidateTempTable (OldTableDesc); 316 317 /* Release the temporary table descriptor */ 318 319 AcpiTbReleaseTempTable (&NewTableDesc); 320 } 321 322 323 /******************************************************************************* 324 * 325 * FUNCTION: AcpiTbUninstallTable 326 * 327 * PARAMETERS: TableDesc - Table descriptor 328 * 329 * RETURN: None 330 * 331 * DESCRIPTION: Delete one internal ACPI table 332 * 333 ******************************************************************************/ 334 335 void 336 AcpiTbUninstallTable ( 337 ACPI_TABLE_DESC *TableDesc) 338 { 339 340 ACPI_FUNCTION_TRACE (TbUninstallTable); 341 342 343 /* Table must be installed */ 344 345 if (!TableDesc->Address) 346 { 347 return_VOID; 348 } 349 350 AcpiTbInvalidateTable (TableDesc); 351 352 if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == 353 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) 354 { 355 ACPI_FREE (TableDesc->Pointer); 356 TableDesc->Pointer = NULL; 357 } 358 359 TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL); 360 return_VOID; 361 } 362