1/******************************************************************************
2 *
3 * Module Name: aetables - ACPI table setup/install for acpiexec utility
4 *
5 *****************************************************************************/
6
7/*
8 * Copyright (C) 2000 - 2011, 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 "aecommon.h"
45#include "aetables.h"
46
47#define _COMPONENT          ACPI_TOOLS
48        ACPI_MODULE_NAME    ("aetables")
49
50/* Local prototypes */
51
52void
53AeTableOverride (
54    ACPI_TABLE_HEADER       *ExistingTable,
55    ACPI_TABLE_HEADER       **NewTable);
56
57ACPI_PHYSICAL_ADDRESS
58AeLocalGetRootPointer (
59    void);
60
61/* User table (DSDT) */
62
63static ACPI_TABLE_HEADER        *DsdtToInstallOverride;
64
65/* Non-AML tables that are constructed locally and installed */
66
67static ACPI_TABLE_RSDP          LocalRSDP;
68static ACPI_TABLE_FACS          LocalFACS;
69static ACPI_TABLE_HEADER        LocalTEST;
70static ACPI_TABLE_HEADER        LocalBADTABLE;
71
72/*
73 * We need a local FADT so that the hardware subcomponent will function,
74 * even though the underlying OSD HW access functions don't do anything.
75 */
76static ACPI_TABLE_FADT          LocalFADT;
77
78/*
79 * Use XSDT so that both 32- and 64-bit versions of this utility will
80 * function automatically.
81 */
82static ACPI_TABLE_XSDT          *LocalXSDT;
83
84#define BASE_XSDT_TABLES        8
85#define BASE_XSDT_SIZE          (sizeof (ACPI_TABLE_XSDT) + \
86                                    ((BASE_XSDT_TABLES -1) * sizeof (UINT64)))
87
88#define ACPI_MAX_INIT_TABLES    (32)
89static ACPI_TABLE_DESC          Tables[ACPI_MAX_INIT_TABLES];
90
91
92/******************************************************************************
93 *
94 * FUNCTION:    AeTableOverride
95 *
96 * DESCRIPTION: Local implementation of AcpiOsTableOverride.
97 *              Exercise the override mechanism
98 *
99 *****************************************************************************/
100
101void
102AeTableOverride (
103    ACPI_TABLE_HEADER       *ExistingTable,
104    ACPI_TABLE_HEADER       **NewTable)
105{
106
107    /* This code exercises the table override mechanism in the core */
108
109    if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT))
110    {
111        *NewTable = DsdtToInstallOverride;
112    }
113
114    /* This code tests override of dynamically loaded tables */
115
116    else if (ACPI_COMPARE_NAME (ExistingTable->Signature, "TSDT"))
117    {
118        *NewTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Ssdt3Code);
119    }
120}
121
122
123/******************************************************************************
124 *
125 * FUNCTION:    AeBuildLocalTables
126 *
127 * PARAMETERS:  TableCount      - Number of tables on the command line
128 *              TableList       - List of actual tables from files
129 *
130 * RETURN:      Status
131 *
132 * DESCRIPTION: Build a complete ACPI table chain, with a local RSDP, XSDT,
133 *              FADT, and several other test tables.
134 *
135 *****************************************************************************/
136
137ACPI_STATUS
138AeBuildLocalTables (
139    UINT32                  TableCount,
140    AE_TABLE_DESC           *TableList)
141{
142    ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
143    UINT32                  XsdtSize;
144    AE_TABLE_DESC           *NextTable;
145    UINT32                  NextIndex;
146    ACPI_TABLE_FADT         *ExternalFadt = NULL;
147
148
149    /*
150     * Update the table count. For DSDT, it is not put into the XSDT. For
151     * FADT, this is already accounted for since we usually install a
152     * local FADT.
153     */
154    NextTable = TableList;
155    while (NextTable)
156    {
157        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
158            ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
159        {
160            TableCount--;
161        }
162        NextTable = NextTable->Next;
163    }
164
165    XsdtSize = BASE_XSDT_SIZE + (TableCount * sizeof (UINT64));
166
167    /* Build an XSDT */
168
169    LocalXSDT = AcpiOsAllocate (XsdtSize);
170    if (!LocalXSDT)
171    {
172        return (AE_NO_MEMORY);
173    }
174
175    ACPI_MEMSET (LocalXSDT, 0, XsdtSize);
176    ACPI_STRNCPY (LocalXSDT->Header.Signature, ACPI_SIG_XSDT, 4);
177    LocalXSDT->Header.Length = XsdtSize;
178    LocalXSDT->Header.Revision = 1;
179
180    LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalTEST);
181    LocalXSDT->TableOffsetEntry[1] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE);
182    LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);
183
184    /* Install two SSDTs to test multiple table support */
185
186    LocalXSDT->TableOffsetEntry[3] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code);
187    LocalXSDT->TableOffsetEntry[4] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code);
188
189    /* Install the OEM1 table to test LoadTable */
190
191    LocalXSDT->TableOffsetEntry[5] = ACPI_PTR_TO_PHYSADDR (&Oem1Code);
192
193    /* Install the OEMx table to test LoadTable */
194
195    LocalXSDT->TableOffsetEntry[6] = ACPI_PTR_TO_PHYSADDR (&OemxCode);
196
197     /* Install the ECDT table to test _REG */
198
199    LocalXSDT->TableOffsetEntry[7] = ACPI_PTR_TO_PHYSADDR (&EcdtCode);
200
201   /*
202     * Install the user tables. The DSDT must be installed in the FADT.
203     * All other tables are installed directly into the XSDT.
204     */
205    NextIndex = BASE_XSDT_TABLES;
206    NextTable = TableList;
207    while (NextTable)
208    {
209        /*
210         * Incoming DSDT or FADT are special cases. All other tables are
211         * just immediately installed into the XSDT.
212         */
213        if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
214        {
215            if (DsdtAddress)
216            {
217                printf ("Already found a DSDT, only one allowed\n");
218                return (AE_ALREADY_EXISTS);
219            }
220
221            /* The incoming user table is a DSDT */
222
223            DsdtAddress = ACPI_PTR_TO_PHYSADDR (&DsdtCode);
224            DsdtToInstallOverride = NextTable->Table;
225        }
226        else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
227        {
228            ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
229            LocalXSDT->TableOffsetEntry[2] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
230        }
231        else
232        {
233            /* Install the table in the XSDT */
234
235            LocalXSDT->TableOffsetEntry[NextIndex] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
236            NextIndex++;
237        }
238
239        NextTable = NextTable->Next;
240    }
241
242    /* Build an RSDP */
243
244    ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
245    ACPI_MEMCPY (LocalRSDP.Signature, ACPI_SIG_RSDP, 8);
246    ACPI_MEMCPY (LocalRSDP.OemId, "I_TEST", 6);
247    LocalRSDP.Revision = 2;
248    LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
249    LocalRSDP.Length = sizeof (ACPI_TABLE_XSDT);
250
251    /* Set checksums for both XSDT and RSDP */
252
253    LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
254        (void *) LocalXSDT, LocalXSDT->Header.Length);
255    LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
256        (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);
257
258    if (!DsdtAddress)
259    {
260        /* Use the local DSDT because incoming table(s) are all SSDT(s) */
261
262        DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode);
263        DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode);
264    }
265
266    if (ExternalFadt)
267    {
268        /*
269         * Use the external FADT, but we must update the DSDT/FACS addresses
270         * as well as the checksum
271         */
272        ExternalFadt->Dsdt = DsdtAddress;
273        ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
274
275        if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
276        {
277            ExternalFadt->XDsdt = DsdtAddress;
278            ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
279        }
280        /* Complete the FADT with the checksum */
281
282        ExternalFadt->Header.Checksum = 0;
283        ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
284            (void *) ExternalFadt, ExternalFadt->Header.Length);
285    }
286    else
287    {
288        /*
289         * Build a local FADT so we can test the hardware/event init
290         */
291        ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));
292        ACPI_STRNCPY (LocalFADT.Header.Signature, ACPI_SIG_FADT, 4);
293
294        /* Setup FADT header and DSDT/FACS addresses */
295
296        LocalFADT.Dsdt = 0;
297        LocalFADT.Facs = 0;
298
299        LocalFADT.XDsdt = DsdtAddress;
300        LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
301
302        LocalFADT.Header.Revision = 3;
303        LocalFADT.Header.Length = sizeof (ACPI_TABLE_FADT);
304
305        /* Miscellaneous FADT fields */
306
307        LocalFADT.Gpe0BlockLength = 16;
308        LocalFADT.Gpe0Block = 0x00001234;
309
310        LocalFADT.Gpe1BlockLength = 6;
311        LocalFADT.Gpe1Block = 0x00005678;
312        LocalFADT.Gpe1Base = 96;
313
314        LocalFADT.Pm1EventLength = 4;
315        LocalFADT.Pm1aEventBlock = 0x00001aaa;
316        LocalFADT.Pm1bEventBlock = 0x00001bbb;
317
318        LocalFADT.Pm1ControlLength = 2;
319        LocalFADT.Pm1aControlBlock = 0xB0;
320
321        LocalFADT.PmTimerLength = 4;
322        LocalFADT.PmTimerBlock = 0xA0;
323
324        LocalFADT.Pm2ControlBlock = 0xC0;
325        LocalFADT.Pm2ControlLength = 1;
326
327        /* Setup one example X-64 field */
328
329        LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
330        LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
331        LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);
332
333        /* Complete the FADT with the checksum */
334
335        LocalFADT.Header.Checksum = 0;
336        LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
337            (void *) &LocalFADT, LocalFADT.Header.Length);
338    }
339
340    /* Build a FACS */
341
342    ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
343    ACPI_STRNCPY (LocalFACS.Signature, ACPI_SIG_FACS, 4);
344
345    LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
346    LocalFACS.GlobalLock = 0x11AA0011;
347
348    /*
349     * Build a fake table [TEST] so that we make sure that the
350     * ACPICA core ignores it
351     */
352    ACPI_MEMSET (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER));
353    ACPI_STRNCPY (LocalTEST.Signature, "TEST", 4);
354
355    LocalTEST.Revision = 1;
356    LocalTEST.Length = sizeof (ACPI_TABLE_HEADER);
357    LocalTEST.Checksum = (UINT8) -AcpiTbChecksum (
358        (void *) &LocalTEST, LocalTEST.Length);
359
360    /*
361     * Build a fake table with a bad signature [BAD!] so that we make
362     * sure that the ACPICA core ignores it
363     */
364    ACPI_MEMSET (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER));
365    ACPI_STRNCPY (LocalBADTABLE.Signature, "BAD!", 4);
366
367    LocalBADTABLE.Revision = 1;
368    LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER);
369    LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum (
370        (void *) &LocalBADTABLE, LocalBADTABLE.Length);
371
372    return (AE_OK);
373}
374
375
376/******************************************************************************
377 *
378 * FUNCTION:    AeInstallTables
379 *
380 * PARAMETERS:  None
381 *
382 * RETURN:      Status
383 *
384 * DESCRIPTION: Install the various ACPI tables
385 *
386 *****************************************************************************/
387
388ACPI_STATUS
389AeInstallTables (
390    void)
391{
392    ACPI_STATUS             Status;
393
394
395    Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE);
396    AE_CHECK_OK (AcpiInitializeTables, Status);
397
398    Status = AcpiReallocateRootTable ();
399    AE_CHECK_OK (AcpiReallocateRootTable, Status);
400
401    Status = AcpiLoadTables ();
402    AE_CHECK_OK (AcpiLoadTables, Status);
403
404    /*
405     * Test run-time control method installation. Do it twice to test code
406     * for an existing name.
407     */
408    Status = AcpiInstallMethod (MethodCode);
409    if (ACPI_FAILURE (Status))
410    {
411        AcpiOsPrintf ("%s, Could not install method\n",
412            AcpiFormatException (Status));
413    }
414
415    Status = AcpiInstallMethod (MethodCode);
416    if (ACPI_FAILURE (Status))
417    {
418        AcpiOsPrintf ("%s, Could not install method\n",
419            AcpiFormatException (Status));
420    }
421
422    return (AE_OK);
423}
424
425
426/******************************************************************************
427 *
428 * FUNCTION:    AeLocalGetRootPointer
429 *
430 * PARAMETERS:  Flags       - not used
431 *              Address     - Where the root pointer is returned
432 *
433 * RETURN:      Status
434 *
435 * DESCRIPTION: Return a local RSDP, used to dynamically load tables via the
436 *              standard ACPI mechanism.
437 *
438 *****************************************************************************/
439
440ACPI_PHYSICAL_ADDRESS
441AeLocalGetRootPointer (
442    void)
443{
444
445    return ((ACPI_PHYSICAL_ADDRESS) &LocalRSDP);
446}
447