1/******************************************************************************
2 *
3 * Module Name: tbinstal - ACPI table installation and removal
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2023, 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
69void
70AcpiTbInstallTableWithOverride (
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
138ACPI_STATUS
139AcpiTbInstallStandardTable (
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
217UnlockAndExit:
218
219    /* Release the table lock */
220
221    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
222
223ReleaseAndExit:
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
249void
250AcpiTbOverrideTable (
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 (const 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
287FinishOverride:
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
335void
336AcpiTbUninstallTable (
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