1 /****************************************************************************** 2 * 3 * Module Name: tbinstal - ACPI table installation and removal 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2020, 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 MERCHANTIBILITY 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 * Reload - Whether reload should be performed 123 * Override - Whether override should be performed 124 * TableIndex - Where the table index is returned 125 * 126 * RETURN: Status 127 * 128 * DESCRIPTION: This function is called to verify and install an ACPI table. 129 * When this function is called by "Load" or "LoadTable" opcodes, 130 * or by AcpiLoadTable() API, the "Reload" parameter is set. 131 * After successfully returning from this function, table is 132 * "INSTALLED" but not "VALIDATED". 133 * 134 ******************************************************************************/ 135 136 ACPI_STATUS 137 AcpiTbInstallStandardTable ( 138 ACPI_PHYSICAL_ADDRESS Address, 139 UINT8 Flags, 140 BOOLEAN Reload, 141 BOOLEAN Override, 142 UINT32 *TableIndex) 143 { 144 UINT32 i; 145 ACPI_STATUS Status = AE_OK; 146 ACPI_TABLE_DESC NewTableDesc; 147 148 149 ACPI_FUNCTION_TRACE (TbInstallStandardTable); 150 151 152 /* Acquire a temporary table descriptor for validation */ 153 154 Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags); 155 if (ACPI_FAILURE (Status)) 156 { 157 ACPI_ERROR ((AE_INFO, 158 "Could not acquire table length at %8.8X%8.8X", 159 ACPI_FORMAT_UINT64 (Address))); 160 return_ACPI_STATUS (Status); 161 } 162 163 /* 164 * Optionally do not load any SSDTs from the RSDT/XSDT. This can 165 * be useful for debugging ACPI problems on some machines. 166 */ 167 if (!Reload && 168 AcpiGbl_DisableSsdtTableInstall && 169 ACPI_COMPARE_NAMESEG (&NewTableDesc.Signature, ACPI_SIG_SSDT)) 170 { 171 ACPI_INFO (( 172 "Ignoring installation of %4.4s at %8.8X%8.8X", 173 NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address))); 174 goto ReleaseAndExit; 175 } 176 177 /* Acquire the table lock */ 178 179 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 180 181 /* Validate and verify a table before installation */ 182 183 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, &i); 184 if (ACPI_FAILURE (Status)) 185 { 186 if (Status == AE_CTRL_TERMINATE) 187 { 188 /* 189 * Table was unloaded, allow it to be reloaded. 190 * As we are going to return AE_OK to the caller, we should 191 * take the responsibility of freeing the input descriptor. 192 * Refill the input descriptor to ensure 193 * AcpiTbInstallTableWithOverride() can be called again to 194 * indicate the re-installation. 195 */ 196 AcpiTbUninstallTable (&NewTableDesc); 197 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 198 *TableIndex = i; 199 return_ACPI_STATUS (AE_OK); 200 } 201 goto UnlockAndExit; 202 } 203 204 /* Add the table to the global root table list */ 205 206 AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex); 207 208 /* Invoke table handler */ 209 210 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 211 AcpiTbNotifyTable (ACPI_TABLE_EVENT_INSTALL, NewTableDesc.Pointer); 212 (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES); 213 214 UnlockAndExit: 215 216 /* Release the table lock */ 217 218 (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES); 219 220 ReleaseAndExit: 221 222 /* Release the temporary table descriptor */ 223 224 AcpiTbReleaseTempTable (&NewTableDesc); 225 return_ACPI_STATUS (Status); 226 } 227 228 229 /******************************************************************************* 230 * 231 * FUNCTION: AcpiTbOverrideTable 232 * 233 * PARAMETERS: OldTableDesc - Validated table descriptor to be 234 * overridden 235 * 236 * RETURN: None 237 * 238 * DESCRIPTION: Attempt table override by calling the OSL override functions. 239 * Note: If the table is overridden, then the entire new table 240 * is acquired and returned by this function. 241 * Before/after invocation, the table descriptor is in a state 242 * that is "VALIDATED". 243 * 244 ******************************************************************************/ 245 246 void 247 AcpiTbOverrideTable ( 248 ACPI_TABLE_DESC *OldTableDesc) 249 { 250 ACPI_STATUS Status; 251 ACPI_TABLE_DESC NewTableDesc; 252 ACPI_TABLE_HEADER *Table; 253 ACPI_PHYSICAL_ADDRESS Address; 254 UINT32 Length; 255 ACPI_ERROR_ONLY (char *OverrideType); 256 257 258 /* (1) Attempt logical override (returns a logical address) */ 259 260 Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table); 261 if (ACPI_SUCCESS (Status) && Table) 262 { 263 AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table), 264 ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL); 265 ACPI_ERROR_ONLY (OverrideType = "Logical"); 266 goto FinishOverride; 267 } 268 269 /* (2) Attempt physical override (returns a physical address) */ 270 271 Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer, 272 &Address, &Length); 273 if (ACPI_SUCCESS (Status) && Address && Length) 274 { 275 AcpiTbAcquireTempTable (&NewTableDesc, Address, 276 ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL); 277 ACPI_ERROR_ONLY (OverrideType = "Physical"); 278 goto FinishOverride; 279 } 280 281 return; /* There was no override */ 282 283 284 FinishOverride: 285 286 /* 287 * Validate and verify a table before overriding, no nested table 288 * duplication check as it's too complicated and unnecessary. 289 */ 290 Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL, NULL); 291 if (ACPI_FAILURE (Status)) 292 { 293 return; 294 } 295 296 ACPI_INFO (("%4.4s 0x%8.8X%8.8X" 297 " %s table override, new table: 0x%8.8X%8.8X", 298 OldTableDesc->Signature.Ascii, 299 ACPI_FORMAT_UINT64 (OldTableDesc->Address), 300 OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address))); 301 302 /* We can now uninstall the original table */ 303 304 AcpiTbUninstallTable (OldTableDesc); 305 306 /* 307 * Replace the original table descriptor and keep its state as 308 * "VALIDATED". 309 */ 310 AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address, 311 NewTableDesc.Flags, NewTableDesc.Pointer); 312 AcpiTbValidateTempTable (OldTableDesc); 313 314 /* Release the temporary table descriptor */ 315 316 AcpiTbReleaseTempTable (&NewTableDesc); 317 } 318 319 320 /******************************************************************************* 321 * 322 * FUNCTION: AcpiTbUninstallTable 323 * 324 * PARAMETERS: TableDesc - Table descriptor 325 * 326 * RETURN: None 327 * 328 * DESCRIPTION: Delete one internal ACPI table 329 * 330 ******************************************************************************/ 331 332 void 333 AcpiTbUninstallTable ( 334 ACPI_TABLE_DESC *TableDesc) 335 { 336 337 ACPI_FUNCTION_TRACE (TbUninstallTable); 338 339 340 /* Table must be installed */ 341 342 if (!TableDesc->Address) 343 { 344 return_VOID; 345 } 346 347 AcpiTbInvalidateTable (TableDesc); 348 349 if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) == 350 ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL) 351 { 352 ACPI_FREE (ACPI_PHYSADDR_TO_PTR (TableDesc->Address)); 353 } 354 355 TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL); 356 return_VOID; 357 } 358