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