1 /******************************************************************************
   2  *
   3  * Module Name: tbxface - ACPI table-oriented external interfaces
   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 #define __TBXFACE_C__
  45 #define EXPORT_ACPI_INTERFACES
  46 
  47 #include "acpi.h"
  48 #include "accommon.h"
  49 #include "actables.h"
  50 
  51 #define _COMPONENT          ACPI_TABLES
  52         ACPI_MODULE_NAME    ("tbxface")
  53 
  54 
  55 /*******************************************************************************
  56  *
  57  * FUNCTION:    AcpiAllocateRootTable
  58  *
  59  * PARAMETERS:  InitialTableCount   - Size of InitialTableArray, in number of
  60  *                                    ACPI_TABLE_DESC structures
  61  *
  62  * RETURN:      Status
  63  *
  64  * DESCRIPTION: Allocate a root table array. Used by iASL compiler and
  65  *              AcpiInitializeTables.
  66  *
  67  ******************************************************************************/
  68 
  69 ACPI_STATUS
  70 AcpiAllocateRootTable (
  71     UINT32                  InitialTableCount)
  72 {
  73 
  74     AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
  75     AcpiGbl_RootTableList.Flags = ACPI_ROOT_ALLOW_RESIZE;
  76 
  77     return (AcpiTbResizeRootTableList ());
  78 }
  79 
  80 
  81 /*******************************************************************************
  82  *
  83  * FUNCTION:    AcpiInitializeTables
  84  *
  85  * PARAMETERS:  InitialTableArray   - Pointer to an array of pre-allocated
  86  *                                    ACPI_TABLE_DESC structures. If NULL, the
  87  *                                    array is dynamically allocated.
  88  *              InitialTableCount   - Size of InitialTableArray, in number of
  89  *                                    ACPI_TABLE_DESC structures
  90  *              AllowResize         - Flag to tell Table Manager if resize of
  91  *                                    pre-allocated array is allowed. Ignored
  92  *                                    if InitialTableArray is NULL.
  93  *
  94  * RETURN:      Status
  95  *
  96  * DESCRIPTION: Initialize the table manager, get the RSDP and RSDT/XSDT.
  97  *
  98  * NOTE:        Allows static allocation of the initial table array in order
  99  *              to avoid the use of dynamic memory in confined environments
 100  *              such as the kernel boot sequence where it may not be available.
 101  *
 102  *              If the host OS memory managers are initialized, use NULL for
 103  *              InitialTableArray, and the table will be dynamically allocated.
 104  *
 105  ******************************************************************************/
 106 
 107 ACPI_STATUS
 108 AcpiInitializeTables (
 109     ACPI_TABLE_DESC         *InitialTableArray,
 110     UINT32                  InitialTableCount,
 111     BOOLEAN                 AllowResize)
 112 {
 113     ACPI_PHYSICAL_ADDRESS   RsdpAddress;
 114     ACPI_STATUS             Status;
 115 
 116 
 117     ACPI_FUNCTION_TRACE (AcpiInitializeTables);
 118 
 119 
 120     /*
 121      * Setup the Root Table Array and allocate the table array
 122      * if requested
 123      */
 124     if (!InitialTableArray)
 125     {
 126         Status = AcpiAllocateRootTable (InitialTableCount);
 127         if (ACPI_FAILURE (Status))
 128         {
 129             return_ACPI_STATUS (Status);
 130         }
 131     }
 132     else
 133     {
 134         /* Root Table Array has been statically allocated by the host */
 135 
 136         ACPI_MEMSET (InitialTableArray, 0,
 137             (ACPI_SIZE) InitialTableCount * sizeof (ACPI_TABLE_DESC));
 138 
 139         AcpiGbl_RootTableList.Tables = InitialTableArray;
 140         AcpiGbl_RootTableList.MaxTableCount = InitialTableCount;
 141         AcpiGbl_RootTableList.Flags = ACPI_ROOT_ORIGIN_UNKNOWN;
 142         if (AllowResize)
 143         {
 144             AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;
 145         }
 146     }
 147 
 148     /* Get the address of the RSDP */
 149 
 150     RsdpAddress = AcpiOsGetRootPointer ();
 151     if (!RsdpAddress)
 152     {
 153         return_ACPI_STATUS (AE_NOT_FOUND);
 154     }
 155 
 156     /*
 157      * Get the root table (RSDT or XSDT) and extract all entries to the local
 158      * Root Table Array. This array contains the information of the RSDT/XSDT
 159      * in a common, more useable format.
 160      */
 161     Status = AcpiTbParseRootTable (RsdpAddress);
 162     return_ACPI_STATUS (Status);
 163 }
 164 
 165 ACPI_EXPORT_SYMBOL_INIT (AcpiInitializeTables)
 166 
 167 
 168 /*******************************************************************************
 169  *
 170  * FUNCTION:    AcpiReallocateRootTable
 171  *
 172  * PARAMETERS:  None
 173  *
 174  * RETURN:      Status
 175  *
 176  * DESCRIPTION: Reallocate Root Table List into dynamic memory. Copies the
 177  *              root list from the previously provided scratch area. Should
 178  *              be called once dynamic memory allocation is available in the
 179  *              kernel.
 180  *
 181  ******************************************************************************/
 182 
 183 ACPI_STATUS
 184 AcpiReallocateRootTable (
 185     void)
 186 {
 187     ACPI_STATUS             Status;
 188 
 189 
 190     ACPI_FUNCTION_TRACE (AcpiReallocateRootTable);
 191 
 192 
 193     /*
 194      * Only reallocate the root table if the host provided a static buffer
 195      * for the table array in the call to AcpiInitializeTables.
 196      */
 197     if (AcpiGbl_RootTableList.Flags & ACPI_ROOT_ORIGIN_ALLOCATED)
 198     {
 199         return_ACPI_STATUS (AE_SUPPORT);
 200     }
 201 
 202     AcpiGbl_RootTableList.Flags |= ACPI_ROOT_ALLOW_RESIZE;
 203 
 204     Status = AcpiTbResizeRootTableList ();
 205     return_ACPI_STATUS (Status);
 206 }
 207 
 208 ACPI_EXPORT_SYMBOL_INIT (AcpiReallocateRootTable)
 209 
 210 
 211 /*******************************************************************************
 212  *
 213  * FUNCTION:    AcpiGetTableHeader
 214  *
 215  * PARAMETERS:  Signature           - ACPI signature of needed table
 216  *              Instance            - Which instance (for SSDTs)
 217  *              OutTableHeader      - The pointer to the table header to fill
 218  *
 219  * RETURN:      Status and pointer to mapped table header
 220  *
 221  * DESCRIPTION: Finds an ACPI table header.
 222  *
 223  * NOTE:        Caller is responsible in unmapping the header with
 224  *              AcpiOsUnmapMemory
 225  *
 226  ******************************************************************************/
 227 
 228 ACPI_STATUS
 229 AcpiGetTableHeader (
 230     char                    *Signature,
 231     UINT32                  Instance,
 232     ACPI_TABLE_HEADER       *OutTableHeader)
 233 {
 234     UINT32                  i;
 235     UINT32                  j;
 236     ACPI_TABLE_HEADER       *Header;
 237 
 238 
 239     /* Parameter validation */
 240 
 241     if (!Signature || !OutTableHeader)
 242     {
 243         return (AE_BAD_PARAMETER);
 244     }
 245 
 246     /* Walk the root table list */
 247 
 248     for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
 249     {
 250         if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
 251                     Signature))
 252         {
 253             continue;
 254         }
 255 
 256         if (++j < Instance)
 257         {
 258             continue;
 259         }
 260 
 261         if (!AcpiGbl_RootTableList.Tables[i].Pointer)
 262         {
 263             if ((AcpiGbl_RootTableList.Tables[i].Flags &
 264                     ACPI_TABLE_ORIGIN_MASK) ==
 265                 ACPI_TABLE_ORIGIN_MAPPED)
 266             {
 267                 Header = AcpiOsMapMemory (
 268                             AcpiGbl_RootTableList.Tables[i].Address,
 269                             sizeof (ACPI_TABLE_HEADER));
 270                 if (!Header)
 271                 {
 272                     return (AE_NO_MEMORY);
 273                 }
 274 
 275                 ACPI_MEMCPY (OutTableHeader, Header,
 276                     sizeof (ACPI_TABLE_HEADER));
 277                 AcpiOsUnmapMemory (Header, sizeof (ACPI_TABLE_HEADER));
 278             }
 279             else
 280             {
 281                 return (AE_NOT_FOUND);
 282             }
 283         }
 284         else
 285         {
 286             ACPI_MEMCPY (OutTableHeader,
 287                 AcpiGbl_RootTableList.Tables[i].Pointer,
 288                 sizeof (ACPI_TABLE_HEADER));
 289         }
 290 
 291         return (AE_OK);
 292     }
 293 
 294     return (AE_NOT_FOUND);
 295 }
 296 
 297 ACPI_EXPORT_SYMBOL (AcpiGetTableHeader)
 298 
 299 
 300 /*******************************************************************************
 301  *
 302  * FUNCTION:    AcpiGetTable
 303  *
 304  * PARAMETERS:  Signature           - ACPI signature of needed table
 305  *              Instance            - Which instance (for SSDTs)
 306  *              OutTable            - Where the pointer to the table is returned
 307  *
 308  * RETURN:      Status and pointer to the requested table
 309  *
 310  * DESCRIPTION: Finds and verifies an ACPI table. Table must be in the
 311  *              RSDT/XSDT.
 312  *
 313  ******************************************************************************/
 314 
 315 ACPI_STATUS
 316 AcpiGetTable (
 317     char                    *Signature,
 318     UINT32                  Instance,
 319     ACPI_TABLE_HEADER       **OutTable)
 320 {
 321     UINT32                  i;
 322     UINT32                  j;
 323     ACPI_STATUS             Status;
 324 
 325 
 326     /* Parameter validation */
 327 
 328     if (!Signature || !OutTable)
 329     {
 330         return (AE_BAD_PARAMETER);
 331     }
 332 
 333     /* Walk the root table list */
 334 
 335     for (i = 0, j = 0; i < AcpiGbl_RootTableList.CurrentTableCount; i++)
 336     {
 337         if (!ACPI_COMPARE_NAME (&(AcpiGbl_RootTableList.Tables[i].Signature),
 338                 Signature))
 339         {
 340             continue;
 341         }
 342 
 343         if (++j < Instance)
 344         {
 345             continue;
 346         }
 347 
 348         Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[i]);
 349         if (ACPI_SUCCESS (Status))
 350         {
 351             *OutTable = AcpiGbl_RootTableList.Tables[i].Pointer;
 352         }
 353 
 354         return (Status);
 355     }
 356 
 357     return (AE_NOT_FOUND);
 358 }
 359 
 360 ACPI_EXPORT_SYMBOL (AcpiGetTable)
 361 
 362 
 363 /*******************************************************************************
 364  *
 365  * FUNCTION:    AcpiGetTableByIndex
 366  *
 367  * PARAMETERS:  TableIndex          - Table index
 368  *              Table               - Where the pointer to the table is returned
 369  *
 370  * RETURN:      Status and pointer to the requested table
 371  *
 372  * DESCRIPTION: Obtain a table by an index into the global table list. Used
 373  *              internally also.
 374  *
 375  ******************************************************************************/
 376 
 377 ACPI_STATUS
 378 AcpiGetTableByIndex (
 379     UINT32                  TableIndex,
 380     ACPI_TABLE_HEADER       **Table)
 381 {
 382     ACPI_STATUS             Status;
 383 
 384 
 385     ACPI_FUNCTION_TRACE (AcpiGetTableByIndex);
 386 
 387 
 388     /* Parameter validation */
 389 
 390     if (!Table)
 391     {
 392         return_ACPI_STATUS (AE_BAD_PARAMETER);
 393     }
 394 
 395     (void) AcpiUtAcquireMutex (ACPI_MTX_TABLES);
 396 
 397     /* Validate index */
 398 
 399     if (TableIndex >= AcpiGbl_RootTableList.CurrentTableCount)
 400     {
 401         (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 402         return_ACPI_STATUS (AE_BAD_PARAMETER);
 403     }
 404 
 405     if (!AcpiGbl_RootTableList.Tables[TableIndex].Pointer)
 406     {
 407         /* Table is not mapped, map it */
 408 
 409         Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[TableIndex]);
 410         if (ACPI_FAILURE (Status))
 411         {
 412             (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 413             return_ACPI_STATUS (Status);
 414         }
 415     }
 416 
 417     *Table = AcpiGbl_RootTableList.Tables[TableIndex].Pointer;
 418     (void) AcpiUtReleaseMutex (ACPI_MTX_TABLES);
 419     return_ACPI_STATUS (AE_OK);
 420 }
 421 
 422 ACPI_EXPORT_SYMBOL (AcpiGetTableByIndex)
 423 
 424 
 425 /*******************************************************************************
 426  *
 427  * FUNCTION:    AcpiInstallTableHandler
 428  *
 429  * PARAMETERS:  Handler         - Table event handler
 430  *              Context         - Value passed to the handler on each event
 431  *
 432  * RETURN:      Status
 433  *
 434  * DESCRIPTION: Install a global table event handler.
 435  *
 436  ******************************************************************************/
 437 
 438 ACPI_STATUS
 439 AcpiInstallTableHandler (
 440     ACPI_TABLE_HANDLER      Handler,
 441     void                    *Context)
 442 {
 443     ACPI_STATUS             Status;
 444 
 445 
 446     ACPI_FUNCTION_TRACE (AcpiInstallTableHandler);
 447 
 448 
 449     if (!Handler)
 450     {
 451         return_ACPI_STATUS (AE_BAD_PARAMETER);
 452     }
 453 
 454     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 455     if (ACPI_FAILURE (Status))
 456     {
 457         return_ACPI_STATUS (Status);
 458     }
 459 
 460     /* Don't allow more than one handler */
 461 
 462     if (AcpiGbl_TableHandler)
 463     {
 464         Status = AE_ALREADY_EXISTS;
 465         goto Cleanup;
 466     }
 467 
 468     /* Install the handler */
 469 
 470     AcpiGbl_TableHandler = Handler;
 471     AcpiGbl_TableHandlerContext = Context;
 472 
 473 Cleanup:
 474     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 475     return_ACPI_STATUS (Status);
 476 }
 477 
 478 ACPI_EXPORT_SYMBOL (AcpiInstallTableHandler)
 479 
 480 
 481 /*******************************************************************************
 482  *
 483  * FUNCTION:    AcpiRemoveTableHandler
 484  *
 485  * PARAMETERS:  Handler         - Table event handler that was installed
 486  *                                previously.
 487  *
 488  * RETURN:      Status
 489  *
 490  * DESCRIPTION: Remove a table event handler
 491  *
 492  ******************************************************************************/
 493 
 494 ACPI_STATUS
 495 AcpiRemoveTableHandler (
 496     ACPI_TABLE_HANDLER      Handler)
 497 {
 498     ACPI_STATUS             Status;
 499 
 500 
 501     ACPI_FUNCTION_TRACE (AcpiRemoveTableHandler);
 502 
 503 
 504     Status = AcpiUtAcquireMutex (ACPI_MTX_EVENTS);
 505     if (ACPI_FAILURE (Status))
 506     {
 507         return_ACPI_STATUS (Status);
 508     }
 509 
 510     /* Make sure that the installed handler is the same */
 511 
 512     if (!Handler ||
 513         Handler != AcpiGbl_TableHandler)
 514     {
 515         Status = AE_BAD_PARAMETER;
 516         goto Cleanup;
 517     }
 518 
 519     /* Remove the handler */
 520 
 521     AcpiGbl_TableHandler = NULL;
 522 
 523 Cleanup:
 524     (void) AcpiUtReleaseMutex (ACPI_MTX_EVENTS);
 525     return_ACPI_STATUS (Status);
 526 }
 527 
 528 ACPI_EXPORT_SYMBOL (AcpiRemoveTableHandler)