1 /******************************************************************************
   2  *
   3  * Module Name: aetables - ACPI table setup/install for acpiexec utility
   4  *
   5  *****************************************************************************/
   6 
   7 /*
   8  * Copyright (C) 2000 - 2014, 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 
  52 static void
  53 AeInitializeTableHeader (
  54     ACPI_TABLE_HEADER       *Header,
  55     char                    *Signature,
  56     UINT32                  Length);
  57 
  58 void
  59 AeTableOverride (
  60     ACPI_TABLE_HEADER       *ExistingTable,
  61     ACPI_TABLE_HEADER       **NewTable);
  62 
  63 ACPI_PHYSICAL_ADDRESS
  64 AeLocalGetRootPointer (
  65     void);
  66 
  67 /* User table (DSDT) */
  68 
  69 static ACPI_TABLE_HEADER        *DsdtToInstallOverride;
  70 
  71 /* Non-AML tables that are constructed locally and installed */
  72 
  73 static ACPI_TABLE_RSDP          LocalRSDP;
  74 static ACPI_TABLE_FACS          LocalFACS;
  75 static ACPI_TABLE_HEADER        LocalTEST;
  76 static ACPI_TABLE_HEADER        LocalBADTABLE;
  77 
  78 /*
  79  * We need a local FADT so that the hardware subcomponent will function,
  80  * even though the underlying OSD HW access functions don't do anything.
  81  */
  82 static ACPI_TABLE_FADT          LocalFADT;
  83 
  84 /*
  85  * Use XSDT so that both 32- and 64-bit versions of this utility will
  86  * function automatically.
  87  */
  88 static ACPI_TABLE_XSDT          *LocalXSDT;
  89 
  90 #define BASE_XSDT_TABLES        9
  91 #define BASE_XSDT_SIZE          ((BASE_XSDT_TABLES) * sizeof (UINT64))
  92 
  93 #define ACPI_MAX_INIT_TABLES    (32)
  94 static ACPI_TABLE_DESC          Tables[ACPI_MAX_INIT_TABLES];
  95 
  96 
  97 /******************************************************************************
  98  *
  99  * FUNCTION:    AeTableOverride
 100  *
 101  * DESCRIPTION: Local implementation of AcpiOsTableOverride.
 102  *              Exercise the override mechanism
 103  *
 104  *****************************************************************************/
 105 
 106 void
 107 AeTableOverride (
 108     ACPI_TABLE_HEADER       *ExistingTable,
 109     ACPI_TABLE_HEADER       **NewTable)
 110 {
 111 
 112     if (!AcpiGbl_LoadTestTables)
 113     {
 114         *NewTable = NULL;
 115         return;
 116     }
 117 
 118     /* This code exercises the table override mechanism in the core */
 119 
 120     if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT))
 121     {
 122         *NewTable = DsdtToInstallOverride;
 123     }
 124 
 125     /* This code tests override of dynamically loaded tables */
 126 
 127     else if (ACPI_COMPARE_NAME (ExistingTable->Signature, "OEM9"))
 128     {
 129         *NewTable = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Ssdt3Code);
 130     }
 131 }
 132 
 133 
 134 /******************************************************************************
 135  *
 136  * FUNCTION:    AeInitializeTableHeader
 137  *
 138  * PARAMETERS:  Header          - A valid standard ACPI table header
 139  *              Signature       - Signature to insert
 140  *              Length          - Length of the table
 141  *
 142  * RETURN:      None. Header is modified.
 143  *
 144  * DESCRIPTION: Initialize the table header for a local ACPI table.
 145  *
 146  *****************************************************************************/
 147 
 148 static void
 149 AeInitializeTableHeader (
 150     ACPI_TABLE_HEADER       *Header,
 151     char                    *Signature,
 152     UINT32                  Length)
 153 {
 154 
 155     ACPI_MOVE_NAME (Header->Signature, Signature);
 156     Header->Length = Length;
 157 
 158     Header->OemRevision = 0x1001;
 159     ACPI_STRNCPY (Header->OemId, "Intel", ACPI_OEM_ID_SIZE);
 160     ACPI_STRNCPY (Header->OemTableId, "AcpiExec", ACPI_OEM_TABLE_ID_SIZE);
 161     ACPI_STRNCPY (Header->AslCompilerId, "INTL", ACPI_NAME_SIZE);
 162     Header->AslCompilerRevision = 0x20131218;
 163 }
 164 
 165 
 166 /******************************************************************************
 167  *
 168  * FUNCTION:    AeBuildLocalTables
 169  *
 170  * PARAMETERS:  TableCount      - Number of tables on the command line
 171  *              TableList       - List of actual tables from files
 172  *
 173  * RETURN:      Status
 174  *
 175  * DESCRIPTION: Build a complete ACPI table chain, with a local RSDP, XSDT,
 176  *              FADT, and several other test tables.
 177  *
 178  *****************************************************************************/
 179 
 180 ACPI_STATUS
 181 AeBuildLocalTables (
 182     UINT32                  TableCount,
 183     AE_TABLE_DESC           *TableList)
 184 {
 185     ACPI_PHYSICAL_ADDRESS   DsdtAddress = 0;
 186     UINT32                  XsdtSize;
 187     AE_TABLE_DESC           *NextTable;
 188     UINT32                  NextIndex;
 189     ACPI_TABLE_FADT         *ExternalFadt = NULL;
 190 
 191 
 192     /*
 193      * Update the table count. For the DSDT, it is not put into the XSDT.
 194      * For the FADT, this table is already accounted for since we usually
 195      * install a local FADT.
 196      */
 197     NextTable = TableList;
 198     while (NextTable)
 199     {
 200         if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT) ||
 201             ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
 202         {
 203             TableCount--;
 204         }
 205         NextTable = NextTable->Next;
 206     }
 207 
 208     XsdtSize = (((TableCount + 1) * sizeof (UINT64)) + sizeof (ACPI_TABLE_HEADER));
 209     if (AcpiGbl_LoadTestTables)
 210     {
 211         XsdtSize += BASE_XSDT_SIZE;
 212     }
 213 
 214     /* Build an XSDT */
 215 
 216     LocalXSDT = AcpiOsAllocate (XsdtSize);
 217     if (!LocalXSDT)
 218     {
 219         return (AE_NO_MEMORY);
 220     }
 221 
 222     ACPI_MEMSET (LocalXSDT, 0, XsdtSize);
 223     AeInitializeTableHeader ((void *) LocalXSDT, ACPI_SIG_XSDT, XsdtSize);
 224 
 225     LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (&LocalFADT);
 226     NextIndex = 1;
 227 
 228     /*
 229      * Install the user tables. The DSDT must be installed in the FADT.
 230      * All other tables are installed directly into the XSDT.
 231      *
 232      * Note: The tables are loaded in reverse order from the incoming
 233      * input, which makes it match the command line order.
 234      */
 235     NextTable = TableList;
 236     while (NextTable)
 237     {
 238         /*
 239          * Incoming DSDT or FADT are special cases. All other tables are
 240          * just immediately installed into the XSDT.
 241          */
 242         if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_DSDT))
 243         {
 244             if (DsdtAddress)
 245             {
 246                 printf ("Already found a DSDT, only one allowed\n");
 247                 return (AE_ALREADY_EXISTS);
 248             }
 249 
 250             /* The incoming user table is a DSDT */
 251 
 252             DsdtAddress = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
 253             DsdtToInstallOverride = NextTable->Table;
 254         }
 255         else if (ACPI_COMPARE_NAME (NextTable->Table->Signature, ACPI_SIG_FADT))
 256         {
 257             ExternalFadt = ACPI_CAST_PTR (ACPI_TABLE_FADT, NextTable->Table);
 258             LocalXSDT->TableOffsetEntry[0] = ACPI_PTR_TO_PHYSADDR (NextTable->Table);
 259         }
 260         else
 261         {
 262             /* Install the table in the XSDT */
 263 
 264             LocalXSDT->TableOffsetEntry[TableCount - NextIndex + 1] =
 265                 ACPI_PTR_TO_PHYSADDR (NextTable->Table);
 266             NextIndex++;
 267         }
 268 
 269         NextTable = NextTable->Next;
 270     }
 271 
 272     /* Install the optional extra local tables */
 273 
 274     if (AcpiGbl_LoadTestTables)
 275     {
 276         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalTEST);
 277         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&LocalBADTABLE);
 278 
 279         /* Install two SSDTs to test multiple table support */
 280 
 281         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt1Code);
 282         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Ssdt2Code);
 283 
 284         /* Install the OEM1 table to test LoadTable */
 285 
 286         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Oem1Code);
 287 
 288         /* Install the OEMx table to test LoadTable */
 289 
 290         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&OemxCode);
 291 
 292          /* Install the ECDT table to test _REG */
 293 
 294         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&EcdtCode);
 295 
 296         /* Install two UEFIs to test multiple table support */
 297 
 298         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi1Code);
 299         LocalXSDT->TableOffsetEntry[NextIndex++] = ACPI_PTR_TO_PHYSADDR (&Uefi2Code);
 300     }
 301 
 302     /* Build an RSDP. Contains a valid XSDT only, no RSDT */
 303 
 304     ACPI_MEMSET (&LocalRSDP, 0, sizeof (ACPI_TABLE_RSDP));
 305     ACPI_MAKE_RSDP_SIG (LocalRSDP.Signature);
 306     ACPI_MEMCPY (LocalRSDP.OemId, "Intel", 6);
 307 
 308     LocalRSDP.Revision = 2;
 309     LocalRSDP.XsdtPhysicalAddress = ACPI_PTR_TO_PHYSADDR (LocalXSDT);
 310     LocalRSDP.Length = sizeof (ACPI_TABLE_RSDP);
 311 
 312     /* Set checksums for both XSDT and RSDP */
 313 
 314     LocalXSDT->Header.Checksum = 0;
 315     LocalXSDT->Header.Checksum = (UINT8) -AcpiTbChecksum (
 316         (void *) LocalXSDT, LocalXSDT->Header.Length);
 317 
 318     LocalRSDP.Checksum = 0;
 319     LocalRSDP.Checksum = (UINT8) -AcpiTbChecksum (
 320         (void *) &LocalRSDP, ACPI_RSDP_CHECKSUM_LENGTH);
 321 
 322     if (!DsdtAddress)
 323     {
 324         /* Use the local DSDT because incoming table(s) are all SSDT(s) */
 325 
 326         DsdtAddress = ACPI_PTR_TO_PHYSADDR (LocalDsdtCode);
 327         DsdtToInstallOverride = ACPI_CAST_PTR (ACPI_TABLE_HEADER, LocalDsdtCode);
 328     }
 329 
 330     /*
 331      * Build an FADT. There are three options for the FADT:
 332      * 1) Incoming external FADT specified on the command line
 333      * 2) A "hardware reduced" local FADT
 334      * 3) A fully featured local FADT
 335      */
 336     if (ExternalFadt)
 337     {
 338         /*
 339          * Use the external FADT, but we must update the DSDT/FACS addresses
 340          * as well as the checksum
 341          */
 342         ExternalFadt->Dsdt = DsdtAddress;
 343         if (!AcpiGbl_ReducedHardware)
 344         {
 345             ExternalFadt->Facs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
 346         }
 347 
 348         /* Is there room in the FADT for the XDsdst and XFacs 64-bit pointers? */
 349 
 350         if (ExternalFadt->Header.Length > ACPI_PTR_DIFF (&ExternalFadt->XDsdt, ExternalFadt))
 351         {
 352             ExternalFadt->XDsdt = DsdtAddress;
 353 
 354             if (!AcpiGbl_ReducedHardware)
 355             {
 356                 ExternalFadt->XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
 357             }
 358         }
 359 
 360         /* Complete the FADT with the checksum */
 361 
 362         ExternalFadt->Header.Checksum = 0;
 363         ExternalFadt->Header.Checksum = (UINT8) -AcpiTbChecksum (
 364             (void *) ExternalFadt, ExternalFadt->Header.Length);
 365     }
 366     else if (AcpiGbl_UseHwReducedFadt)
 367     {
 368         ACPI_MEMCPY (&LocalFADT, HwReducedFadtCode, sizeof (ACPI_TABLE_FADT));
 369         LocalFADT.Dsdt = DsdtAddress;
 370         LocalFADT.XDsdt = DsdtAddress;
 371 
 372         LocalFADT.Header.Checksum = 0;
 373         LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
 374             (void *) &LocalFADT, LocalFADT.Header.Length);
 375     }
 376     else
 377     {
 378         /*
 379          * Build a local FADT so we can test the hardware/event init
 380          */
 381         ACPI_MEMSET (&LocalFADT, 0, sizeof (ACPI_TABLE_FADT));
 382         LocalFADT.Header.Revision = 5;
 383         AeInitializeTableHeader ((void *) &LocalFADT, ACPI_SIG_FADT, sizeof (ACPI_TABLE_FADT));
 384 
 385         /* Setup FADT header and DSDT/FACS addresses */
 386 
 387         LocalFADT.Dsdt = 0;
 388         LocalFADT.Facs = 0;
 389 
 390         LocalFADT.XDsdt = DsdtAddress;
 391         LocalFADT.XFacs = ACPI_PTR_TO_PHYSADDR (&LocalFACS);
 392 
 393         /* Miscellaneous FADT fields */
 394 
 395         LocalFADT.Gpe0BlockLength = 16;
 396         LocalFADT.Gpe0Block = 0x00001234;
 397 
 398         LocalFADT.Gpe1BlockLength = 6;
 399         LocalFADT.Gpe1Block = 0x00005678;
 400         LocalFADT.Gpe1Base = 96;
 401 
 402         LocalFADT.Pm1EventLength = 4;
 403         LocalFADT.Pm1aEventBlock = 0x00001aaa;
 404         LocalFADT.Pm1bEventBlock = 0x00001bbb;
 405 
 406         LocalFADT.Pm1ControlLength = 2;
 407         LocalFADT.Pm1aControlBlock = 0xB0;
 408 
 409         LocalFADT.PmTimerLength = 4;
 410         LocalFADT.PmTimerBlock = 0xA0;
 411 
 412         LocalFADT.Pm2ControlBlock = 0xC0;
 413         LocalFADT.Pm2ControlLength = 1;
 414 
 415         /* Setup one example X-64 GAS field */
 416 
 417         LocalFADT.XPm1bEventBlock.SpaceId = ACPI_ADR_SPACE_SYSTEM_IO;
 418         LocalFADT.XPm1bEventBlock.Address = LocalFADT.Pm1bEventBlock;
 419         LocalFADT.XPm1bEventBlock.BitWidth = (UINT8) ACPI_MUL_8 (LocalFADT.Pm1EventLength);
 420 
 421         /* Complete the FADT with the checksum */
 422 
 423         LocalFADT.Header.Checksum = 0;
 424         LocalFADT.Header.Checksum = (UINT8) -AcpiTbChecksum (
 425             (void *) &LocalFADT, LocalFADT.Header.Length);
 426     }
 427 
 428     /* Build a FACS */
 429 
 430     ACPI_MEMSET (&LocalFACS, 0, sizeof (ACPI_TABLE_FACS));
 431     ACPI_MOVE_NAME (LocalFACS.Signature, ACPI_SIG_FACS);
 432 
 433     LocalFACS.Length = sizeof (ACPI_TABLE_FACS);
 434     LocalFACS.GlobalLock = 0x11AA0011;
 435 
 436     /* Build the optional local tables */
 437 
 438     if (AcpiGbl_LoadTestTables)
 439     {
 440         /*
 441          * Build a fake table [TEST] so that we make sure that the
 442          * ACPICA core ignores it
 443          */
 444         ACPI_MEMSET (&LocalTEST, 0, sizeof (ACPI_TABLE_HEADER));
 445         ACPI_MOVE_NAME (LocalTEST.Signature, "TEST");
 446 
 447         LocalTEST.Revision = 1;
 448         LocalTEST.Length = sizeof (ACPI_TABLE_HEADER);
 449         LocalTEST.Checksum = (UINT8) -AcpiTbChecksum (
 450             (void *) &LocalTEST, LocalTEST.Length);
 451 
 452         /*
 453          * Build a fake table with a bad signature [BAD!] so that we make
 454          * sure that the ACPICA core ignores it
 455          */
 456         ACPI_MEMSET (&LocalBADTABLE, 0, sizeof (ACPI_TABLE_HEADER));
 457         ACPI_MOVE_NAME (LocalBADTABLE.Signature, "BAD!");
 458 
 459         LocalBADTABLE.Revision = 1;
 460         LocalBADTABLE.Length = sizeof (ACPI_TABLE_HEADER);
 461         LocalBADTABLE.Checksum = (UINT8) -AcpiTbChecksum (
 462             (void *) &LocalBADTABLE, LocalBADTABLE.Length);
 463     }
 464 
 465     return (AE_OK);
 466 }
 467 
 468 
 469 /******************************************************************************
 470  *
 471  * FUNCTION:    AeInstallTables
 472  *
 473  * PARAMETERS:  None
 474  *
 475  * RETURN:      Status
 476  *
 477  * DESCRIPTION: Install the various ACPI tables
 478  *
 479  *****************************************************************************/
 480 
 481 ACPI_STATUS
 482 AeInstallTables (
 483     void)
 484 {
 485     ACPI_STATUS             Status;
 486     ACPI_TABLE_HEADER       Header;
 487     ACPI_TABLE_HEADER       *Table;
 488 
 489 
 490     Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE);
 491     AE_CHECK_OK (AcpiInitializeTables, Status);
 492 
 493     Status = AcpiReallocateRootTable ();
 494     AE_CHECK_OK (AcpiReallocateRootTable, Status);
 495 
 496     Status = AcpiLoadTables ();
 497     AE_CHECK_OK (AcpiLoadTables, Status);
 498 
 499     /*
 500      * Test run-time control method installation. Do it twice to test code
 501      * for an existing name.
 502      */
 503     Status = AcpiInstallMethod (MethodCode);
 504     if (ACPI_FAILURE (Status))
 505     {
 506         AcpiOsPrintf ("%s, Could not install method\n",
 507             AcpiFormatException (Status));
 508     }
 509 
 510     Status = AcpiInstallMethod (MethodCode);
 511     if (ACPI_FAILURE (Status))
 512     {
 513         AcpiOsPrintf ("%s, Could not install method\n",
 514             AcpiFormatException (Status));
 515     }
 516 
 517     if (AcpiGbl_LoadTestTables)
 518     {
 519         /* Test multiple table/UEFI support. First, get the headers */
 520 
 521         Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 1, &Header);
 522         AE_CHECK_OK (AcpiGetTableHeader, Status);
 523 
 524         Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 2, &Header);
 525         AE_CHECK_OK (AcpiGetTableHeader, Status);
 526 
 527         Status = AcpiGetTableHeader (ACPI_SIG_UEFI, 3, &Header);
 528         AE_CHECK_STATUS (AcpiGetTableHeader, Status, AE_NOT_FOUND);
 529 
 530         /* Now get the actual tables */
 531 
 532         Status = AcpiGetTable (ACPI_SIG_UEFI, 1, &Table);
 533         AE_CHECK_OK (AcpiGetTable, Status);
 534 
 535         Status = AcpiGetTable (ACPI_SIG_UEFI, 2, &Table);
 536         AE_CHECK_OK (AcpiGetTable, Status);
 537 
 538         Status = AcpiGetTable (ACPI_SIG_UEFI, 3, &Table);
 539         AE_CHECK_STATUS (AcpiGetTable, Status, AE_NOT_FOUND);
 540     }
 541 
 542     return (AE_OK);
 543 }
 544 
 545 
 546 /******************************************************************************
 547  *
 548  * FUNCTION:    AeLocalGetRootPointer
 549  *
 550  * PARAMETERS:  Flags       - not used
 551  *              Address     - Where the root pointer is returned
 552  *
 553  * RETURN:      Status
 554  *
 555  * DESCRIPTION: Return a local RSDP, used to dynamically load tables via the
 556  *              standard ACPI mechanism.
 557  *
 558  *****************************************************************************/
 559 
 560 ACPI_PHYSICAL_ADDRESS
 561 AeLocalGetRootPointer (
 562     void)
 563 {
 564 
 565     return ((ACPI_PHYSICAL_ADDRESS) &LocalRSDP);
 566 }