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 <contrib/dev/acpica/include/acpi.h>
45 #include <contrib/dev/acpica/include/accommon.h>
46 #include <contrib/dev/acpica/include/actables.h>
47 
48 #define _COMPONENT          ACPI_TABLES
49         ACPI_MODULE_NAME    ("tbinstal")
50 
51 /* Local prototypes */
52 
53 static BOOLEAN
54 AcpiTbCompareTables (
55     ACPI_TABLE_DESC         *TableDesc,
56     UINT32                  TableIndex);
57 
58 
59 /*******************************************************************************
60  *
61  * FUNCTION:    AcpiTbCompareTables
62  *
63  * PARAMETERS:  TableDesc           - Table 1 descriptor to be compared
64  *              TableIndex          - Index of table 2 to be compared
65  *
66  * RETURN:      TRUE if both tables are identical.
67  *
68  * DESCRIPTION: This function compares a table with another table that has
69  *              already been installed in the root table list.
70  *
71  ******************************************************************************/
72 
73 static BOOLEAN
74 AcpiTbCompareTables (
75     ACPI_TABLE_DESC         *TableDesc,
76     UINT32                  TableIndex)
77 {
78     ACPI_STATUS             Status = AE_OK;
79     BOOLEAN                 IsIdentical;
80     ACPI_TABLE_HEADER       *Table;
81     UINT32                  TableLength;
82     UINT8                   TableFlags;
83 
84 
85     Status = AcpiTbAcquireTable (&AcpiGbl_RootTableList.Tables[TableIndex],
86         &Table, &TableLength, &TableFlags);
87     if (ACPI_FAILURE (Status))
88     {
89         return (FALSE);
90     }
91 
92     /*
93      * Check for a table match on the entire table length,
94      * not just the header.
95      */
96     IsIdentical = (BOOLEAN)((TableDesc->Length != TableLength ||
97         memcmp (TableDesc->Pointer, Table, TableLength)) ?
98         FALSE : TRUE);
99 
100     /* Release the acquired table */
101 
102     AcpiTbReleaseTable (Table, TableLength, TableFlags);
103     return (IsIdentical);
104 }
105 
106 
107 /*******************************************************************************
108  *
109  * FUNCTION:    AcpiTbInstallTableWithOverride
110  *
111  * PARAMETERS:  NewTableDesc            - New table descriptor to install
112  *              Override                - Whether override should be performed
113  *              TableIndex              - Where the table index is returned
114  *
115  * RETURN:      None
116  *
117  * DESCRIPTION: Install an ACPI table into the global data structure. The
118  *              table override mechanism is called to allow the host
119  *              OS to replace any table before it is installed in the root
120  *              table array.
121  *
122  ******************************************************************************/
123 
124 void
125 AcpiTbInstallTableWithOverride (
126     ACPI_TABLE_DESC         *NewTableDesc,
127     BOOLEAN                 Override,
128     UINT32                  *TableIndex)
129 {
130     UINT32                  i;
131     ACPI_STATUS             Status;
132 
133 
134     Status = AcpiTbGetNextTableDescriptor (&i, NULL);
135     if (ACPI_FAILURE (Status))
136     {
137         return;
138     }
139 
140     /*
141      * ACPI Table Override:
142      *
143      * Before we install the table, let the host OS override it with a new
144      * one if desired. Any table within the RSDT/XSDT can be replaced,
145      * including the DSDT which is pointed to by the FADT.
146      */
147     if (Override)
148     {
149         AcpiTbOverrideTable (NewTableDesc);
150     }
151 
152     AcpiTbInitTableDescriptor (&AcpiGbl_RootTableList.Tables[i],
153         NewTableDesc->Address, NewTableDesc->Flags, NewTableDesc->Pointer);
154 
155     AcpiTbPrintTableHeader (NewTableDesc->Address, NewTableDesc->Pointer);
156 
157     /* This synchronizes AcpiGbl_DsdtIndex */
158 
159     *TableIndex = i;
160 
161     /* Set the global integer width (based upon revision of the DSDT) */
162 
163     if (i == AcpiGbl_DsdtIndex)
164     {
165         AcpiUtSetIntegerWidth (NewTableDesc->Pointer->Revision);
166     }
167 }
168 
169 
170 /*******************************************************************************
171  *
172  * FUNCTION:    AcpiTbInstallStandardTable
173  *
174  * PARAMETERS:  Address             - Address of the table (might be a virtual
175  *                                    address depending on the TableFlags)
176  *              Flags               - Flags for the table
177  *              Reload              - Whether reload should be performed
178  *              Override            - Whether override should be performed
179  *              TableIndex          - Where the table index is returned
180  *
181  * RETURN:      Status
182  *
183  * DESCRIPTION: This function is called to verify and install an ACPI table.
184  *              When this function is called by "Load" or "LoadTable" opcodes,
185  *              or by AcpiLoadTable() API, the "Reload" parameter is set.
186  *              After sucessfully returning from this function, table is
187  *              "INSTALLED" but not "VALIDATED".
188  *
189  ******************************************************************************/
190 
191 ACPI_STATUS
192 AcpiTbInstallStandardTable (
193     ACPI_PHYSICAL_ADDRESS   Address,
194     UINT8                   Flags,
195     BOOLEAN                 Reload,
196     BOOLEAN                 Override,
197     UINT32                  *TableIndex)
198 {
199     UINT32                  i;
200     ACPI_STATUS             Status = AE_OK;
201     ACPI_TABLE_DESC         NewTableDesc;
202 
203 
204     ACPI_FUNCTION_TRACE (TbInstallStandardTable);
205 
206 
207     /* Acquire a temporary table descriptor for validation */
208 
209     Status = AcpiTbAcquireTempTable (&NewTableDesc, Address, Flags);
210     if (ACPI_FAILURE (Status))
211     {
212         ACPI_ERROR ((AE_INFO,
213             "Could not acquire table length at %8.8X%8.8X",
214             ACPI_FORMAT_UINT64 (Address)));
215         return_ACPI_STATUS (Status);
216     }
217 
218     /*
219      * Optionally do not load any SSDTs from the RSDT/XSDT. This can
220      * be useful for debugging ACPI problems on some machines.
221      */
222     if (!Reload &&
223         AcpiGbl_DisableSsdtTableInstall &&
224         ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT))
225     {
226         ACPI_INFO ((
227             "Ignoring installation of %4.4s at %8.8X%8.8X",
228             NewTableDesc.Signature.Ascii, ACPI_FORMAT_UINT64 (Address)));
229         goto ReleaseAndExit;
230     }
231 
232     /* Validate and verify a table before installation */
233 
234     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL);
235     if (ACPI_FAILURE (Status))
236     {
237         goto ReleaseAndExit;
238     }
239 
240     if (Reload)
241     {
242         /*
243          * Validate the incoming table signature.
244          *
245          * 1) Originally, we checked the table signature for "SSDT" or "PSDT".
246          * 2) We added support for OEMx tables, signature "OEM".
247          * 3) Valid tables were encountered with a null signature, so we just
248          *    gave up on validating the signature, (05/2008).
249          * 4) We encountered non-AML tables such as the MADT, which caused
250          *    interpreter errors and kernel faults. So now, we once again allow
251          *    only "SSDT", "OEMx", and now, also a null signature. (05/2011).
252          */
253         if ((NewTableDesc.Signature.Ascii[0] != 0x00) &&
254            (!ACPI_COMPARE_NAME (&NewTableDesc.Signature, ACPI_SIG_SSDT)) &&
255            (strncmp (NewTableDesc.Signature.Ascii, "OEM", 3)))
256         {
257             ACPI_BIOS_ERROR ((AE_INFO,
258                 "Table has invalid signature [%4.4s] (0x%8.8X), "
259                 "must be SSDT or OEMx",
260                 AcpiUtValidNameseg (NewTableDesc.Signature.Ascii) ?
261                     NewTableDesc.Signature.Ascii : "????",
262                 NewTableDesc.Signature.Integer));
263 
264             Status = AE_BAD_SIGNATURE;
265             goto ReleaseAndExit;
266         }
267 
268         /* Check if table is already registered */
269 
270         for (i = 0; i < AcpiGbl_RootTableList.CurrentTableCount; ++i)
271         {
272             /*
273              * Check for a table match on the entire table length,
274              * not just the header.
275              */
276             if (!AcpiTbCompareTables (&NewTableDesc, i))
277             {
278                 continue;
279             }
280 
281             /*
282              * Note: the current mechanism does not unregister a table if it is
283              * dynamically unloaded. The related namespace entries are deleted,
284              * but the table remains in the root table list.
285              *
286              * The assumption here is that the number of different tables that
287              * will be loaded is actually small, and there is minimal overhead
288              * in just keeping the table in case it is needed again.
289              *
290              * If this assumption changes in the future (perhaps on large
291              * machines with many table load/unload operations), tables will
292              * need to be unregistered when they are unloaded, and slots in the
293              * root table list should be reused when empty.
294              */
295             if (AcpiGbl_RootTableList.Tables[i].Flags &
296                 ACPI_TABLE_IS_LOADED)
297             {
298                 /* Table is still loaded, this is an error */
299 
300                 Status = AE_ALREADY_EXISTS;
301                 goto ReleaseAndExit;
302             }
303             else
304             {
305                 /*
306                  * Table was unloaded, allow it to be reloaded.
307                  * As we are going to return AE_OK to the caller, we should
308                  * take the responsibility of freeing the input descriptor.
309                  * Refill the input descriptor to ensure
310                  * AcpiTbInstallTableWithOverride() can be called again to
311                  * indicate the re-installation.
312                  */
313                 AcpiTbUninstallTable (&NewTableDesc);
314                 *TableIndex = i;
315                 return_ACPI_STATUS (AE_OK);
316             }
317         }
318     }
319 
320     /* Add the table to the global root table list */
321 
322     AcpiTbInstallTableWithOverride (&NewTableDesc, Override, TableIndex);
323 
324     /* Invoke table handler if present */
325 
326     if (AcpiGbl_TableHandler)
327     {
328         (void) AcpiGbl_TableHandler (ACPI_TABLE_EVENT_INSTALL,
329             NewTableDesc.Pointer, AcpiGbl_TableHandlerContext);
330     }
331 
332 ReleaseAndExit:
333 
334     /* Release the temporary table descriptor */
335 
336     AcpiTbReleaseTempTable (&NewTableDesc);
337     return_ACPI_STATUS (Status);
338 }
339 
340 
341 /*******************************************************************************
342  *
343  * FUNCTION:    AcpiTbOverrideTable
344  *
345  * PARAMETERS:  OldTableDesc        - Validated table descriptor to be
346  *                                    overridden
347  *
348  * RETURN:      None
349  *
350  * DESCRIPTION: Attempt table override by calling the OSL override functions.
351  *              Note: If the table is overridden, then the entire new table
352  *              is acquired and returned by this function.
353  *              Before/after invocation, the table descriptor is in a state
354  *              that is "VALIDATED".
355  *
356  ******************************************************************************/
357 
358 void
359 AcpiTbOverrideTable (
360     ACPI_TABLE_DESC         *OldTableDesc)
361 {
362     ACPI_STATUS             Status;
363     char                    *OverrideType;
364     ACPI_TABLE_DESC         NewTableDesc;
365     ACPI_TABLE_HEADER       *Table;
366     ACPI_PHYSICAL_ADDRESS   Address;
367     UINT32                  Length;
368 
369 
370     /* (1) Attempt logical override (returns a logical address) */
371 
372     Status = AcpiOsTableOverride (OldTableDesc->Pointer, &Table);
373     if (ACPI_SUCCESS (Status) && Table)
374     {
375         AcpiTbAcquireTempTable (&NewTableDesc, ACPI_PTR_TO_PHYSADDR (Table),
376             ACPI_TABLE_ORIGIN_EXTERNAL_VIRTUAL);
377         OverrideType = "Logical";
378         goto FinishOverride;
379     }
380 
381     /* (2) Attempt physical override (returns a physical address) */
382 
383     Status = AcpiOsPhysicalTableOverride (OldTableDesc->Pointer,
384         &Address, &Length);
385     if (ACPI_SUCCESS (Status) && Address && Length)
386     {
387         AcpiTbAcquireTempTable (&NewTableDesc, Address,
388             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL);
389         OverrideType = "Physical";
390         goto FinishOverride;
391     }
392 
393     return; /* There was no override */
394 
395 
396 FinishOverride:
397 
398     /* Validate and verify a table before overriding */
399 
400     Status = AcpiTbVerifyTempTable (&NewTableDesc, NULL);
401     if (ACPI_FAILURE (Status))
402     {
403         return;
404     }
405 
406     ACPI_INFO (("%4.4s 0x%8.8X%8.8X"
407         " %s table override, new table: 0x%8.8X%8.8X",
408         OldTableDesc->Signature.Ascii,
409         ACPI_FORMAT_UINT64 (OldTableDesc->Address),
410         OverrideType, ACPI_FORMAT_UINT64 (NewTableDesc.Address)));
411 
412     /* We can now uninstall the original table */
413 
414     AcpiTbUninstallTable (OldTableDesc);
415 
416     /*
417      * Replace the original table descriptor and keep its state as
418      * "VALIDATED".
419      */
420     AcpiTbInitTableDescriptor (OldTableDesc, NewTableDesc.Address,
421         NewTableDesc.Flags, NewTableDesc.Pointer);
422     AcpiTbValidateTempTable (OldTableDesc);
423 
424     /* Release the temporary table descriptor */
425 
426     AcpiTbReleaseTempTable (&NewTableDesc);
427 }
428 
429 
430 /*******************************************************************************
431  *
432  * FUNCTION:    AcpiTbUninstallTable
433  *
434  * PARAMETERS:  TableDesc           - Table descriptor
435  *
436  * RETURN:      None
437  *
438  * DESCRIPTION: Delete one internal ACPI table
439  *
440  ******************************************************************************/
441 
442 void
443 AcpiTbUninstallTable (
444     ACPI_TABLE_DESC         *TableDesc)
445 {
446 
447     ACPI_FUNCTION_TRACE (TbUninstallTable);
448 
449 
450     /* Table must be installed */
451 
452     if (!TableDesc->Address)
453     {
454         return_VOID;
455     }
456 
457     AcpiTbInvalidateTable (TableDesc);
458 
459     if ((TableDesc->Flags & ACPI_TABLE_ORIGIN_MASK) ==
460         ACPI_TABLE_ORIGIN_INTERNAL_VIRTUAL)
461     {
462         ACPI_FREE (ACPI_PHYSADDR_TO_PTR (TableDesc->Address));
463     }
464 
465     TableDesc->Address = ACPI_PTR_TO_PHYSADDR (NULL);
466     return_VOID;
467 }
468