1 /******************************************************************************
   2  *
   3  * Module Name: osfreebsdtbl - FreeBSD OSL for obtaining ACPI tables
   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 "acpidump.h"
  45 
  46 #include <kenv.h>
  47 #include <unistd.h>
  48 #include <sys/param.h>
  49 #include <sys/sysctl.h>
  50 
  51 
  52 #define _COMPONENT          ACPI_OS_SERVICES
  53         ACPI_MODULE_NAME    ("osfreebsdtbl")
  54 
  55 
  56 /* Local prototypes */
  57 
  58 static ACPI_STATUS
  59 OslTableInitialize (
  60     void);
  61 
  62 static ACPI_STATUS
  63 OslMapTable (
  64     ACPI_SIZE               Address,
  65     char                    *Signature,
  66     ACPI_TABLE_HEADER       **Table);
  67 
  68 static ACPI_STATUS
  69 OslAddTablesToList (
  70     void);
  71 
  72 static ACPI_STATUS
  73 OslGetTableViaRoot (
  74     char                    *Signature,
  75     UINT32                  Instance,
  76     ACPI_TABLE_HEADER       **Table,
  77     ACPI_PHYSICAL_ADDRESS   *Address);
  78 
  79 
  80 /* Hints for RSDP */
  81 
  82 #define SYSTEM_KENV         "hint.acpi.0.rsdp"
  83 #define SYSTEM_SYSCTL       "machdep.acpi_root"
  84 
  85 /* Initialization flags */
  86 
  87 UINT8                   Gbl_TableListInitialized = FALSE;
  88 UINT8                   Gbl_MainTableObtained = FALSE;
  89 
  90 /* Local copies of main ACPI tables */
  91 
  92 ACPI_TABLE_RSDP         Gbl_Rsdp;
  93 ACPI_TABLE_FADT         *Gbl_Fadt;
  94 ACPI_TABLE_RSDT         *Gbl_Rsdt;
  95 ACPI_TABLE_XSDT         *Gbl_Xsdt;
  96 
  97 /* Fadt address */
  98 
  99 ACPI_PHYSICAL_ADDRESS   Gbl_FadtAddress;
 100 
 101 /* Revision of RSD PTR */
 102 
 103 UINT8                   Gbl_Revision;
 104 
 105 /* List of information about obtained ACPI tables */
 106 
 107 typedef struct          table_info
 108 {
 109     struct table_info       *Next;
 110     char                    Signature[4];
 111     UINT32                  Instance;
 112     ACPI_PHYSICAL_ADDRESS   Address;
 113 
 114 } OSL_TABLE_INFO;
 115 
 116 OSL_TABLE_INFO          *Gbl_TableListHead = NULL;
 117 
 118 
 119 /******************************************************************************
 120  *
 121  * FUNCTION:    AcpiOsGetTableByAddress
 122  *
 123  * PARAMETERS:  Address         - Physical address of the ACPI table
 124  *              Table           - Where a pointer to the table is returned
 125  *
 126  * RETURN:      Status; Table buffer is returned if AE_OK.
 127  *              AE_NOT_FOUND: A valid table was not found at the address
 128  *
 129  * DESCRIPTION: Get an ACPI table via a physical memory address.
 130  *
 131  *****************************************************************************/
 132 
 133 ACPI_STATUS
 134 AcpiOsGetTableByAddress (
 135     ACPI_PHYSICAL_ADDRESS   Address,
 136     ACPI_TABLE_HEADER       **Table)
 137 {
 138     ACPI_TABLE_HEADER       *MappedTable;
 139     ACPI_TABLE_HEADER       *LocalTable;
 140     ACPI_STATUS             Status;
 141 
 142 
 143     /* Validate the input physical address to avoid program crash */
 144 
 145     if (Address < ACPI_HI_RSDP_WINDOW_BASE)
 146     {
 147         fprintf (stderr, "Invalid table address: 0x%8.8X%8.8X\n",
 148             ACPI_FORMAT_UINT64 (Address));
 149         return (AE_BAD_ADDRESS);
 150     }
 151 
 152     /* Map the table and validate it */
 153 
 154     Status = OslMapTable (Address, NULL, &MappedTable);
 155     if (ACPI_FAILURE (Status))
 156     {
 157         return (Status);
 158     }
 159 
 160     /* Copy table to local buffer and return it */
 161 
 162     LocalTable = calloc (1, MappedTable->Length);
 163     if (!LocalTable)
 164     {
 165         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 166         return (AE_NO_MEMORY);
 167     }
 168 
 169     ACPI_MEMCPY (LocalTable, MappedTable, MappedTable->Length);
 170     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 171 
 172     *Table = LocalTable;
 173     return (AE_OK);
 174 }
 175 
 176 
 177 /******************************************************************************
 178  *
 179  * FUNCTION:    AcpiOsGetTableByName
 180  *
 181  * PARAMETERS:  Signature       - ACPI Signature for desired table. Must be
 182  *                                a null terminated 4-character string.
 183  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
 184  *                                Must be 0 for other tables.
 185  *              Table           - Where a pointer to the table is returned
 186  *              Address         - Where the table physical address is returned
 187  *
 188  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
 189  *              AE_LIMIT: Instance is beyond valid limit
 190  *              AE_NOT_FOUND: A table with the signature was not found
 191  *
 192  * NOTE:        Assumes the input signature is uppercase.
 193  *
 194  *****************************************************************************/
 195 
 196 ACPI_STATUS
 197 AcpiOsGetTableByName (
 198     char                    *Signature,
 199     UINT32                  Instance,
 200     ACPI_TABLE_HEADER       **Table,
 201     ACPI_PHYSICAL_ADDRESS   *Address)
 202 {
 203     ACPI_STATUS             Status;
 204 
 205 
 206     /* Instance is only valid for SSDT/UEFI tables */
 207 
 208     if (Instance &&
 209         !ACPI_COMPARE_NAME (Signature, ACPI_SIG_SSDT) &&
 210         !ACPI_COMPARE_NAME (Signature, ACPI_SIG_UEFI))
 211     {
 212         return (AE_LIMIT);
 213     }
 214 
 215     /* Initialize main tables */
 216 
 217     Status = OslTableInitialize ();
 218     if (ACPI_FAILURE (Status))
 219     {
 220         return (Status);
 221     }
 222 
 223     /*
 224      * If one of the main ACPI tables was requested (RSDT/XSDT/FADT),
 225      * simply return it immediately.
 226      */
 227     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_XSDT))
 228     {
 229         if (!Gbl_Revision)
 230         {
 231             return (AE_NOT_FOUND);
 232         }
 233 
 234         *Address = Gbl_Rsdp.XsdtPhysicalAddress;
 235         *Table = (ACPI_TABLE_HEADER *) Gbl_Xsdt;
 236         return (AE_OK);
 237     }
 238 
 239     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_RSDT))
 240     {
 241         if (!Gbl_Rsdp.RsdtPhysicalAddress)
 242         {
 243             return (AE_NOT_FOUND);
 244         }
 245 
 246         *Address = Gbl_Rsdp.RsdtPhysicalAddress;
 247         *Table = (ACPI_TABLE_HEADER *) Gbl_Rsdt;
 248         return (AE_OK);
 249     }
 250 
 251     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_FADT))
 252     {
 253         *Address = Gbl_FadtAddress;
 254         *Table = (ACPI_TABLE_HEADER *) Gbl_Fadt;
 255         return (AE_OK);
 256     }
 257 
 258     /* Not a main ACPI table, attempt to extract it from the RSDT/XSDT */
 259 
 260     Status = OslGetTableViaRoot (Signature, Instance, Table, Address);
 261     if (ACPI_FAILURE (Status))
 262     {
 263         return (Status);
 264     }
 265 
 266     return (AE_OK);
 267 }
 268 
 269 
 270 /******************************************************************************
 271  *
 272  * FUNCTION:    AcpiOsGetTableByIndex
 273  *
 274  * PARAMETERS:  Index           - Which table to get
 275  *              Table           - Where a pointer to the table is returned
 276  *              Instance        - Where a pointer to the table instance no. is
 277  *                                returned
 278  *              Address         - Where the table physical address is returned
 279  *
 280  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
 281  *              AE_LIMIT: Index is beyond valid limit
 282  *
 283  * DESCRIPTION: Get an ACPI table via an index value (0 through n). Returns
 284  *              AE_LIMIT when an invalid index is reached. Index is not
 285  *              necessarily an index into the RSDT/XSDT.
 286  *
 287  *****************************************************************************/
 288 
 289 ACPI_STATUS
 290 AcpiOsGetTableByIndex (
 291     UINT32                  Index,
 292     ACPI_TABLE_HEADER       **Table,
 293     UINT32                  *Instance,
 294     ACPI_PHYSICAL_ADDRESS   *Address)
 295 {
 296     OSL_TABLE_INFO          *Info;
 297     ACPI_STATUS             Status;
 298     UINT32                  i;
 299 
 300 
 301     /* Initialize main tables */
 302 
 303     Status = OslTableInitialize ();
 304     if (ACPI_FAILURE (Status))
 305     {
 306         return (Status);
 307     }
 308 
 309     /* Add all tables to list */
 310 
 311     Status = OslAddTablesToList ();
 312     if (ACPI_FAILURE (Status))
 313     {
 314         return (Status);
 315     }
 316 
 317     /* Validate Index */
 318 
 319     if (Index >= Gbl_TableListHead->Instance)
 320     {
 321         return (AE_LIMIT);
 322     }
 323 
 324     /* Point to the table list entry specified by the Index argument */
 325 
 326     Info = Gbl_TableListHead;
 327     for (i = 0; i <= Index; i++)
 328     {
 329         Info = Info->Next;
 330     }
 331 
 332     /* Now we can just get the table via the address or name */
 333 
 334     if (Info->Address)
 335     {
 336         Status = AcpiOsGetTableByAddress (Info->Address, Table);
 337         if (ACPI_SUCCESS (Status))
 338         {
 339             *Address = Info->Address;
 340         }
 341     }
 342     else
 343     {
 344         Status = AcpiOsGetTableByName (Info->Signature, Info->Instance,
 345             Table, Address);
 346     }
 347 
 348     if (ACPI_SUCCESS (Status))
 349     {
 350         *Instance = Info->Instance;
 351     }
 352     return (Status);
 353 }
 354 
 355 
 356 /******************************************************************************
 357  *
 358  * FUNCTION:    OslTableInitialize
 359  *
 360  * PARAMETERS:  None
 361  *
 362  * RETURN:      Status
 363  *
 364  * DESCRIPTION: Initialize ACPI table data. Get and store main ACPI tables to
 365  *              local variables. Main ACPI tables include RSDP, FADT, RSDT,
 366  *              and/or XSDT.
 367  *
 368  *****************************************************************************/
 369 
 370 static ACPI_STATUS
 371 OslTableInitialize (
 372     void)
 373 {
 374     char                    Buffer[32];
 375     ACPI_TABLE_HEADER       *MappedTable;
 376     UINT8                   *TableAddress;
 377     UINT8                   *RsdpAddress;
 378     ACPI_PHYSICAL_ADDRESS   RsdpBase;
 379     ACPI_SIZE               RsdpSize;
 380     ACPI_STATUS             Status;
 381     u_long                  Address = 0;
 382     size_t                  Length = sizeof (Address);
 383 
 384 
 385     /* Get main ACPI tables from memory on first invocation of this function */
 386 
 387     if (Gbl_MainTableObtained)
 388     {
 389         return (AE_OK);
 390     }
 391 
 392     /* Attempt to use kenv or sysctl to find RSD PTR record. */
 393 
 394     if (Gbl_RsdpBase)
 395     {
 396         Address = Gbl_RsdpBase;
 397     }
 398     else if (kenv (KENV_GET, SYSTEM_KENV, Buffer, sizeof (Buffer)) > 0)
 399     {
 400         Address = ACPI_STRTOUL (Buffer, NULL, 0);
 401     }
 402     if (!Address)
 403     {
 404         if (sysctlbyname (SYSTEM_SYSCTL, &Address, &Length, NULL, 0) != 0)
 405         {
 406             Address = 0;
 407         }
 408     }
 409     if (Address)
 410     {
 411         RsdpBase = Address;
 412         RsdpSize = sizeof (Gbl_Rsdp);
 413     }
 414     else
 415     {
 416         RsdpBase = ACPI_HI_RSDP_WINDOW_BASE;
 417         RsdpSize = ACPI_HI_RSDP_WINDOW_SIZE;
 418     }
 419 
 420     /* Get RSDP from memory */
 421 
 422     RsdpAddress = AcpiOsMapMemory (RsdpBase, RsdpSize);
 423     if (!RsdpAddress)
 424     {
 425         return (AE_BAD_ADDRESS);
 426     }
 427 
 428     /* Search low memory for the RSDP */
 429 
 430     TableAddress = AcpiTbScanMemoryForRsdp (RsdpAddress, RsdpSize);
 431     if (!TableAddress)
 432     {
 433         AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
 434         return (AE_ERROR);
 435     }
 436 
 437     ACPI_MEMCPY (&Gbl_Rsdp, TableAddress, sizeof (Gbl_Rsdp));
 438     AcpiOsUnmapMemory (RsdpAddress, RsdpSize);
 439 
 440     /* Get XSDT from memory */
 441 
 442     if (Gbl_Rsdp.Revision)
 443     {
 444         Status = OslMapTable (Gbl_Rsdp.XsdtPhysicalAddress,
 445             ACPI_SIG_XSDT, &MappedTable);
 446         if (ACPI_FAILURE (Status))
 447         {
 448             return (Status);
 449         }
 450 
 451         Gbl_Revision = 2;
 452         Gbl_Xsdt = calloc (1, MappedTable->Length);
 453         if (!Gbl_Xsdt)
 454         {
 455             fprintf (stderr,
 456                 "XSDT: Could not allocate buffer for table of length %X\n",
 457                 MappedTable->Length);
 458             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 459             return (AE_NO_MEMORY);
 460         }
 461 
 462         ACPI_MEMCPY (Gbl_Xsdt, MappedTable, MappedTable->Length);
 463         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 464     }
 465 
 466     /* Get RSDT from memory */
 467 
 468     if (Gbl_Rsdp.RsdtPhysicalAddress)
 469     {
 470         Status = OslMapTable (Gbl_Rsdp.RsdtPhysicalAddress,
 471             ACPI_SIG_RSDT, &MappedTable);
 472         if (ACPI_FAILURE (Status))
 473         {
 474             return (Status);
 475         }
 476 
 477         Gbl_Rsdt = calloc (1, MappedTable->Length);
 478         if (!Gbl_Rsdt)
 479         {
 480             fprintf (stderr,
 481                 "RSDT: Could not allocate buffer for table of length %X\n",
 482                 MappedTable->Length);
 483             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 484             return (AE_NO_MEMORY);
 485         }
 486 
 487         ACPI_MEMCPY (Gbl_Rsdt, MappedTable, MappedTable->Length);
 488         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 489     }
 490 
 491     /* Get FADT from memory */
 492 
 493     if (Gbl_Revision)
 494     {
 495         Gbl_FadtAddress = Gbl_Xsdt->TableOffsetEntry[0];
 496     }
 497     else
 498     {
 499         Gbl_FadtAddress = Gbl_Rsdt->TableOffsetEntry[0];
 500     }
 501 
 502     if (!Gbl_FadtAddress)
 503     {
 504         fprintf(stderr, "FADT: Table could not be found\n");
 505         return (AE_ERROR);
 506     }
 507 
 508     Status = OslMapTable (Gbl_FadtAddress, ACPI_SIG_FADT, &MappedTable);
 509     if (ACPI_FAILURE (Status))
 510     {
 511         return (Status);
 512     }
 513 
 514     Gbl_Fadt = calloc (1, MappedTable->Length);
 515     if (!Gbl_Fadt)
 516     {
 517         fprintf (stderr,
 518             "FADT: Could not allocate buffer for table of length %X\n",
 519             MappedTable->Length);
 520         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 521         return (AE_NO_MEMORY);
 522     }
 523 
 524     ACPI_MEMCPY (Gbl_Fadt, MappedTable, MappedTable->Length);
 525     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 526     Gbl_MainTableObtained = TRUE;
 527     return (AE_OK);
 528 }
 529 
 530 
 531 /******************************************************************************
 532  *
 533  * FUNCTION:    OslGetTableViaRoot
 534  *
 535  * PARAMETERS:  Signature       - ACPI Signature for common table. Must be
 536  *                                a null terminated 4-character string.
 537  *              Instance        - Multiple table support for SSDT/UEFI (0...n)
 538  *                                Must be 0 for other tables.
 539  *              Table           - Where a pointer to the table is returned
 540  *              Address         - Where the table physical address is returned
 541  *
 542  * RETURN:      Status; Table buffer and physical address returned if AE_OK.
 543  *              AE_LIMIT: Instance is beyond valid limit
 544  *              AE_NOT_FOUND: A table with the signature was not found
 545  *
 546  * DESCRIPTION: Get an ACPI table via the root table (RSDT/XSDT)
 547  *
 548  * NOTE:        Assumes the input signature is uppercase.
 549  *
 550  *****************************************************************************/
 551 
 552 static ACPI_STATUS
 553 OslGetTableViaRoot (
 554     char                    *Signature,
 555     UINT32                  Instance,
 556     ACPI_TABLE_HEADER       **Table,
 557     ACPI_PHYSICAL_ADDRESS   *Address)
 558 {
 559     ACPI_TABLE_HEADER       *LocalTable = NULL;
 560     ACPI_TABLE_HEADER       *MappedTable = NULL;
 561     UINT8                   NumberOfTables;
 562     UINT32                  CurrentInstance = 0;
 563     ACPI_PHYSICAL_ADDRESS   TableAddress = 0;
 564     ACPI_STATUS             Status;
 565     UINT32                  i;
 566 
 567 
 568     /* DSDT and FACS address must be extracted from the FADT */
 569 
 570     if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT) ||
 571         ACPI_COMPARE_NAME (Signature, ACPI_SIG_FACS))
 572     {
 573         /*
 574          * Get the appropriate address, either 32-bit or 64-bit. Be very
 575          * careful about the FADT length and validate table addresses.
 576          * Note: The 64-bit addresses have priority.
 577          */
 578         if (ACPI_COMPARE_NAME (Signature, ACPI_SIG_DSDT))
 579         {
 580             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XDSDT) &&
 581                 Gbl_Fadt->XDsdt)
 582             {
 583                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XDsdt;
 584             }
 585             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_DSDT) &&
 586                 Gbl_Fadt->Dsdt)
 587             {
 588                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Dsdt;
 589             }
 590         }
 591         else /* FACS */
 592         {
 593             if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_XFACS) &&
 594                 Gbl_Fadt->XFacs)
 595             {
 596                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->XFacs;
 597             }
 598             else if ((Gbl_Fadt->Header.Length >= MIN_FADT_FOR_FACS) &&
 599                 Gbl_Fadt->Facs)
 600             {
 601                 TableAddress = (ACPI_PHYSICAL_ADDRESS) Gbl_Fadt->Facs;
 602             }
 603         }
 604     }
 605     else /* Case for a normal ACPI table */
 606     {
 607         if (Gbl_Revision)
 608         {
 609             NumberOfTables =
 610                 (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
 611                 / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
 612         }
 613         else /* Use RSDT if XSDT is not available */
 614         {
 615             NumberOfTables =
 616                 (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
 617                 / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
 618         }
 619 
 620         /* Search RSDT/XSDT for the requested table */
 621 
 622         for (i = 0; i < NumberOfTables; i++)
 623         {
 624             if (Gbl_Revision)
 625             {
 626                 TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
 627             }
 628             else
 629             {
 630                 TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
 631             }
 632 
 633             MappedTable = AcpiOsMapMemory (TableAddress, sizeof (*MappedTable));
 634             if (!MappedTable)
 635             {
 636                 return (AE_BAD_ADDRESS);
 637             }
 638 
 639             /* Does this table match the requested signature? */
 640 
 641             if (ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
 642             {
 643 
 644                 /* Match table instance (for SSDT/UEFI tables) */
 645 
 646                 if (CurrentInstance == Instance)
 647                 {
 648                     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
 649                     break;
 650                 }
 651 
 652                 CurrentInstance++;
 653             }
 654 
 655             AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 656             TableAddress = 0;
 657         }
 658     }
 659 
 660     if (!TableAddress)
 661     {
 662         if (CurrentInstance)
 663         {
 664             return (AE_LIMIT);
 665         }
 666         return (AE_NOT_FOUND);
 667     }
 668 
 669     /* Now we can get the requested table */
 670 
 671     Status = OslMapTable (TableAddress, Signature, &MappedTable);
 672     if (ACPI_FAILURE (Status))
 673     {
 674         return (Status);
 675     }
 676 
 677     /* Copy table to local buffer and return it */
 678 
 679     LocalTable = calloc (1, MappedTable->Length);
 680     if (!LocalTable)
 681     {
 682         AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 683         return (AE_NO_MEMORY);
 684     }
 685 
 686     ACPI_MEMCPY (LocalTable, MappedTable, MappedTable->Length);
 687     AcpiOsUnmapMemory (MappedTable, MappedTable->Length);
 688     *Table = LocalTable;
 689     *Address = TableAddress;
 690     return (AE_OK);
 691 }
 692 
 693 
 694 /******************************************************************************
 695  *
 696  * FUNCTION:    OslAddTablesToList
 697  *
 698  * PARAMETERS:  None
 699  *
 700  * RETURN:      Status; Table list is initialized if AE_OK.
 701  *
 702  * DESCRIPTION: Add ACPI tables to the table list.
 703  *
 704  *****************************************************************************/
 705 
 706 static ACPI_STATUS
 707 OslAddTablesToList(
 708     void)
 709 {
 710     ACPI_PHYSICAL_ADDRESS   TableAddress;
 711     OSL_TABLE_INFO          *Info = NULL;
 712     OSL_TABLE_INFO          *NewInfo;
 713     ACPI_TABLE_HEADER       *Table;
 714     UINT8                   Instance;
 715     UINT8                   NumberOfTables;
 716     int                     i;
 717 
 718 
 719     /* Initialize the table list on first invocation */
 720 
 721     if (Gbl_TableListInitialized)
 722     {
 723         return (AE_OK);
 724     }
 725 
 726     /* Add mandatory tables to global table list first */
 727 
 728     for (i = 0; i < 4; i++)
 729     {
 730         NewInfo = calloc (1, sizeof (*NewInfo));
 731         if (!NewInfo)
 732         {
 733             return (AE_NO_MEMORY);
 734         }
 735 
 736         switch (i) {
 737         case 0:
 738 
 739             Gbl_TableListHead = Info = NewInfo;
 740             continue;
 741 
 742         case 1:
 743 
 744             ACPI_MOVE_NAME (NewInfo->Signature,
 745                 Gbl_Revision ? ACPI_SIG_XSDT : ACPI_SIG_RSDT);
 746             break;
 747 
 748         case 2:
 749 
 750             ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_FACS);
 751             break;
 752 
 753         default:
 754 
 755             ACPI_MOVE_NAME (NewInfo->Signature, ACPI_SIG_DSDT);
 756 
 757         }
 758 
 759         Info->Next = NewInfo;
 760         Info = NewInfo;
 761         Gbl_TableListHead->Instance++;
 762     }
 763 
 764     /* Add normal tables from RSDT/XSDT to global list */
 765 
 766     if (Gbl_Revision)
 767     {
 768         NumberOfTables =
 769             (Gbl_Xsdt->Header.Length - sizeof (Gbl_Xsdt->Header))
 770             / sizeof (Gbl_Xsdt->TableOffsetEntry[0]);
 771     }
 772     else
 773     {
 774         NumberOfTables =
 775             (Gbl_Rsdt->Header.Length - sizeof (Gbl_Rsdt->Header))
 776             / sizeof (Gbl_Rsdt->TableOffsetEntry[0]);
 777     }
 778 
 779     for (i = 0; i < NumberOfTables; i++)
 780     {
 781         if (Gbl_Revision)
 782         {
 783             TableAddress = Gbl_Xsdt->TableOffsetEntry[i];
 784         }
 785         else
 786         {
 787             TableAddress = Gbl_Rsdt->TableOffsetEntry[i];
 788         }
 789 
 790         Table = AcpiOsMapMemory (TableAddress, sizeof (*Table));
 791         if (!Table)
 792         {
 793             return (AE_BAD_ADDRESS);
 794         }
 795 
 796         Instance = 0;
 797         NewInfo = Gbl_TableListHead;
 798         while (NewInfo->Next != NULL)
 799         {
 800             NewInfo = NewInfo->Next;
 801             if (ACPI_COMPARE_NAME (Table->Signature, NewInfo->Signature))
 802             {
 803                 Instance++;
 804             }
 805         }
 806 
 807         NewInfo = calloc (1, sizeof (*NewInfo));
 808         if (!NewInfo)
 809         {
 810             AcpiOsUnmapMemory (Table, sizeof (*Table));
 811             return (AE_NO_MEMORY);
 812         }
 813 
 814         ACPI_MOVE_NAME (NewInfo->Signature, Table->Signature);
 815 
 816         AcpiOsUnmapMemory (Table, sizeof (*Table));
 817 
 818         NewInfo->Instance = Instance;
 819         NewInfo->Address = TableAddress;
 820         Info->Next = NewInfo;
 821         Info = NewInfo;
 822         Gbl_TableListHead->Instance++;
 823     }
 824 
 825     Gbl_TableListInitialized = TRUE;
 826     return (AE_OK);
 827 }
 828 
 829 
 830 /******************************************************************************
 831  *
 832  * FUNCTION:    OslMapTable
 833  *
 834  * PARAMETERS:  Address             - Address of the table in memory
 835  *              Signature           - Optional ACPI Signature for desired table.
 836  *                                    Null terminated 4-character string.
 837  *              Table               - Where a pointer to the mapped table is
 838  *                                    returned
 839  *
 840  * RETURN:      Status; Mapped table is returned if AE_OK.
 841  *
 842  * DESCRIPTION: Map entire ACPI table into caller's address space. Also
 843  *              validates the table and checksum.
 844  *
 845  *****************************************************************************/
 846 
 847 static ACPI_STATUS
 848 OslMapTable (
 849     ACPI_SIZE               Address,
 850     char                    *Signature,
 851     ACPI_TABLE_HEADER       **Table)
 852 {
 853     ACPI_TABLE_HEADER       *MappedTable;
 854     UINT32                  Length;
 855 
 856 
 857     /* Map the header so we can get the table length */
 858 
 859     MappedTable = AcpiOsMapMemory (Address, sizeof (*MappedTable));
 860     if (!MappedTable)
 861     {
 862         return (AE_BAD_ADDRESS);
 863     }
 864 
 865     /* Check if table is valid */
 866 
 867     if (!ApIsValidHeader (MappedTable))
 868     {
 869         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
 870         return (AE_BAD_HEADER);
 871     }
 872 
 873     /* If specified, signature must match */
 874 
 875     if (Signature &&
 876         !ACPI_COMPARE_NAME (Signature, MappedTable->Signature))
 877     {
 878         AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
 879         return (AE_NOT_EXIST);
 880     }
 881 
 882     /* Map the entire table */
 883 
 884     Length = MappedTable->Length;
 885     AcpiOsUnmapMemory (MappedTable, sizeof (*MappedTable));
 886 
 887     MappedTable = AcpiOsMapMemory (Address, Length);
 888     if (!MappedTable)
 889     {
 890         return (AE_BAD_ADDRESS);
 891     }
 892 
 893     (void) ApIsValidChecksum (MappedTable);
 894 
 895     *Table = MappedTable;
 896 
 897     return (AE_OK);
 898 }