tbinstal.c revision 1.11
1/******************************************************************************
2 *
3 * Module Name: tbinstal - ACPI table installation and removal
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2017, 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
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 *              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 sucessfully returning from this function, table is
132 *              "INSTALLED" but not "VALIDATED".
133 *
134 ******************************************************************************/
135
136ACPI_STATUS
137AcpiTbInstallStandardTable (
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_NAME (&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
214UnlockAndExit:
215
216    /* Release the table lock */
217
218    (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
219
220ReleaseAndExit:
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
246void
247AcpiTbOverrideTable (
248    ACPI_TABLE_DESC         *OldTableDesc)
249{
250    ACPI_STATUS             Status;
251    const char              *OverrideType;
252    ACPI_TABLE_DESC         NewTableDesc;
253    ACPI_TABLE_HEADER       *Table;
254    ACPI_PHYSICAL_ADDRESS   Address;
255    UINT32                  Length;
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        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        OverrideType = "Physical";
278        goto FinishOverride;
279    }
280
281    return; /* There was no override */
282
283
284FinishOverride:
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
332void
333AcpiTbUninstallTable (
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	void *ptr = ACPI_PHYSADDR_TO_PTR (TableDesc->Address);
353	if (ptr)
354	{
355		ACPI_FREE (ptr);
356	}
357    }
358
359    TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
360    return_VOID;
361}
362