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