tbutils.c revision 207344
167754Smsmith/****************************************************************************** 267754Smsmith * 3167802Sjkim * Module Name: tbutils - table utilities 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 767754Smsmith/****************************************************************************** 867754Smsmith * 967754Smsmith * 1. Copyright Notice 1067754Smsmith * 11202771Sjkim * Some or all of this work - Copyright (c) 1999 - 2010, Intel Corp. 1270243Smsmith * All rights reserved. 1367754Smsmith * 1467754Smsmith * 2. License 1567754Smsmith * 1667754Smsmith * 2.1. This is your license from Intel Corp. under its intellectual property 1767754Smsmith * rights. You may have additional license terms from the party that provided 1867754Smsmith * you this software, covering your right to use that party's intellectual 1967754Smsmith * property rights. 2067754Smsmith * 2167754Smsmith * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 2267754Smsmith * copy of the source code appearing in this file ("Covered Code") an 2367754Smsmith * irrevocable, perpetual, worldwide license under Intel's copyrights in the 2467754Smsmith * base code distributed originally by Intel ("Original Intel Code") to copy, 2567754Smsmith * make derivatives, distribute, use and display any portion of the Covered 2667754Smsmith * Code in any form, with the right to sublicense such rights; and 2767754Smsmith * 2867754Smsmith * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 2967754Smsmith * license (with the right to sublicense), under only those claims of Intel 3067754Smsmith * patents that are infringed by the Original Intel Code, to make, use, sell, 3167754Smsmith * offer to sell, and import the Covered Code and derivative works thereof 3267754Smsmith * solely to the minimum extent necessary to exercise the above copyright 3367754Smsmith * license, and in no event shall the patent license extend to any additions 3467754Smsmith * to or modifications of the Original Intel Code. No other license or right 3567754Smsmith * is granted directly or by implication, estoppel or otherwise; 3667754Smsmith * 3767754Smsmith * The above copyright and patent license is granted only if the following 3867754Smsmith * conditions are met: 3967754Smsmith * 4067754Smsmith * 3. Conditions 4167754Smsmith * 4267754Smsmith * 3.1. Redistribution of Source with Rights to Further Distribute Source. 4367754Smsmith * Redistribution of source code of any substantial portion of the Covered 4467754Smsmith * Code or modification with rights to further distribute source must include 4567754Smsmith * the above Copyright Notice, the above License, this list of Conditions, 4667754Smsmith * and the following Disclaimer and Export Compliance provision. In addition, 4767754Smsmith * Licensee must cause all Covered Code to which Licensee contributes to 4867754Smsmith * contain a file documenting the changes Licensee made to create that Covered 4967754Smsmith * Code and the date of any change. Licensee must include in that file the 5067754Smsmith * documentation of any changes made by any predecessor Licensee. Licensee 5167754Smsmith * must include a prominent statement that the modification is derived, 5267754Smsmith * directly or indirectly, from Original Intel Code. 5367754Smsmith * 5467754Smsmith * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 5567754Smsmith * Redistribution of source code of any substantial portion of the Covered 5667754Smsmith * Code or modification without rights to further distribute source must 5767754Smsmith * include the following Disclaimer and Export Compliance provision in the 5867754Smsmith * documentation and/or other materials provided with distribution. In 5967754Smsmith * addition, Licensee may not authorize further sublicense of source of any 6067754Smsmith * portion of the Covered Code, and must include terms to the effect that the 6167754Smsmith * license from Licensee to its licensee is limited to the intellectual 6267754Smsmith * property embodied in the software Licensee provides to its licensee, and 6367754Smsmith * not to intellectual property embodied in modifications its licensee may 6467754Smsmith * make. 6567754Smsmith * 6667754Smsmith * 3.3. Redistribution of Executable. Redistribution in executable form of any 6767754Smsmith * substantial portion of the Covered Code or modification must reproduce the 6867754Smsmith * above Copyright Notice, and the following Disclaimer and Export Compliance 6967754Smsmith * provision in the documentation and/or other materials provided with the 7067754Smsmith * distribution. 7167754Smsmith * 7267754Smsmith * 3.4. Intel retains all right, title, and interest in and to the Original 7367754Smsmith * Intel Code. 7467754Smsmith * 7567754Smsmith * 3.5. Neither the name Intel nor any other trademark owned or controlled by 7667754Smsmith * Intel shall be used in advertising or otherwise to promote the sale, use or 7767754Smsmith * other dealings in products derived from or relating to the Covered Code 7867754Smsmith * without prior written authorization from Intel. 7967754Smsmith * 8067754Smsmith * 4. Disclaimer and Export Compliance 8167754Smsmith * 8267754Smsmith * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 8367754Smsmith * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 8467754Smsmith * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 8567754Smsmith * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 8667754Smsmith * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 8767754Smsmith * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 8867754Smsmith * PARTICULAR PURPOSE. 8967754Smsmith * 9067754Smsmith * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 9167754Smsmith * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 9267754Smsmith * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 9367754Smsmith * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 9467754Smsmith * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 9567754Smsmith * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 9667754Smsmith * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 9767754Smsmith * LIMITED REMEDY. 9867754Smsmith * 9967754Smsmith * 4.3. Licensee shall not export, either directly or indirectly, any of this 10067754Smsmith * software or system incorporating such software without first obtaining any 10167754Smsmith * required license or other approval from the U. S. Department of Commerce or 10267754Smsmith * any other agency or department of the United States Government. In the 10367754Smsmith * event Licensee exports any such software from the United States or 10467754Smsmith * re-exports any such software from a foreign destination, Licensee shall 10567754Smsmith * ensure that the distribution and export/re-export of the software is in 10667754Smsmith * compliance with all laws, regulations, orders, or other restrictions of the 10767754Smsmith * U.S. Export Administration Regulations. Licensee agrees that neither it nor 10867754Smsmith * any of its subsidiaries will export/re-export any technical data, process, 10967754Smsmith * software, or service, directly or indirectly, to any country for which the 11067754Smsmith * United States government or any agency thereof requires an export license, 11167754Smsmith * other governmental approval, or letter of assurance, without first obtaining 11267754Smsmith * such license, approval or letter. 11367754Smsmith * 11467754Smsmith *****************************************************************************/ 11567754Smsmith 11667754Smsmith#define __TBUTILS_C__ 11767754Smsmith 118193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 119193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 120193341Sjkim#include <contrib/dev/acpica/include/actables.h> 12167754Smsmith 12277424Smsmith#define _COMPONENT ACPI_TABLES 12391116Smsmith ACPI_MODULE_NAME ("tbutils") 12467754Smsmith 125151937Sjkim/* Local prototypes */ 12667754Smsmith 127197104Sjkimstatic void 128197104SjkimAcpiTbFixString ( 129197104Sjkim char *String, 130197104Sjkim ACPI_SIZE Length); 131197104Sjkim 132197104Sjkimstatic void 133197104SjkimAcpiTbCleanupTableHeader ( 134197104Sjkim ACPI_TABLE_HEADER *OutHeader, 135197104Sjkim ACPI_TABLE_HEADER *Header); 136197104Sjkim 137167802Sjkimstatic ACPI_PHYSICAL_ADDRESS 138167802SjkimAcpiTbGetRootTableEntry ( 139167802Sjkim UINT8 *TableEntry, 140193267Sjkim UINT32 TableEntrySize); 141151937Sjkim 142151937Sjkim 14367754Smsmith/******************************************************************************* 14467754Smsmith * 145193267Sjkim * FUNCTION: AcpiTbInitializeFacs 146193267Sjkim * 147193267Sjkim * PARAMETERS: None 148193267Sjkim * 149193267Sjkim * RETURN: Status 150193267Sjkim * 151193267Sjkim * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global 152193267Sjkim * for accessing the Global Lock and Firmware Waking Vector 153193267Sjkim * 154193267Sjkim ******************************************************************************/ 155193267Sjkim 156193267SjkimACPI_STATUS 157193267SjkimAcpiTbInitializeFacs ( 158193267Sjkim void) 159193267Sjkim{ 160193267Sjkim ACPI_STATUS Status; 161193267Sjkim 162193267Sjkim 163193267Sjkim Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, 164193267Sjkim ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); 165193267Sjkim return (Status); 166193267Sjkim} 167193267Sjkim 168193267Sjkim 169193267Sjkim/******************************************************************************* 170193267Sjkim * 171167802Sjkim * FUNCTION: AcpiTbTablesLoaded 17267754Smsmith * 173167802Sjkim * PARAMETERS: None 17467754Smsmith * 175167802Sjkim * RETURN: TRUE if required ACPI tables are loaded 17667754Smsmith * 177167802Sjkim * DESCRIPTION: Determine if the minimum required ACPI tables are present 178167802Sjkim * (FADT, FACS, DSDT) 179151937Sjkim * 18067754Smsmith ******************************************************************************/ 18167754Smsmith 182167802SjkimBOOLEAN 183167802SjkimAcpiTbTablesLoaded ( 184167802Sjkim void) 18567754Smsmith{ 18667754Smsmith 187207344Sjkim if (AcpiGbl_RootTableList.CurrentTableCount >= 3) 188167802Sjkim { 189167802Sjkim return (TRUE); 190167802Sjkim } 19183174Smsmith 192167802Sjkim return (FALSE); 193167802Sjkim} 19467754Smsmith 19582367Smsmith 196167802Sjkim/******************************************************************************* 197167802Sjkim * 198197104Sjkim * FUNCTION: AcpiTbFixString 199197104Sjkim * 200197104Sjkim * PARAMETERS: String - String to be repaired 201197104Sjkim * Length - Maximum length 202197104Sjkim * 203197104Sjkim * RETURN: None 204197104Sjkim * 205197104Sjkim * DESCRIPTION: Replace every non-printable or non-ascii byte in the string 206197104Sjkim * with a question mark '?'. 207197104Sjkim * 208197104Sjkim ******************************************************************************/ 209197104Sjkim 210197104Sjkimstatic void 211197104SjkimAcpiTbFixString ( 212197104Sjkim char *String, 213197104Sjkim ACPI_SIZE Length) 214197104Sjkim{ 215197104Sjkim 216197104Sjkim while (Length && *String) 217197104Sjkim { 218197104Sjkim if (!ACPI_IS_PRINT (*String)) 219197104Sjkim { 220197104Sjkim *String = '?'; 221197104Sjkim } 222197104Sjkim String++; 223197104Sjkim Length--; 224197104Sjkim } 225197104Sjkim} 226197104Sjkim 227197104Sjkim 228197104Sjkim/******************************************************************************* 229197104Sjkim * 230197104Sjkim * FUNCTION: AcpiTbCleanupTableHeader 231197104Sjkim * 232197104Sjkim * PARAMETERS: OutHeader - Where the cleaned header is returned 233197104Sjkim * Header - Input ACPI table header 234197104Sjkim * 235197104Sjkim * RETURN: Returns the cleaned header in OutHeader 236197104Sjkim * 237197104Sjkim * DESCRIPTION: Copy the table header and ensure that all "string" fields in 238197104Sjkim * the header consist of printable characters. 239197104Sjkim * 240197104Sjkim ******************************************************************************/ 241197104Sjkim 242197104Sjkimstatic void 243197104SjkimAcpiTbCleanupTableHeader ( 244197104Sjkim ACPI_TABLE_HEADER *OutHeader, 245197104Sjkim ACPI_TABLE_HEADER *Header) 246197104Sjkim{ 247197104Sjkim 248197104Sjkim ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); 249197104Sjkim 250197104Sjkim AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE); 251197104Sjkim AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); 252197104Sjkim AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE); 253197104Sjkim AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE); 254197104Sjkim} 255197104Sjkim 256197104Sjkim 257197104Sjkim/******************************************************************************* 258197104Sjkim * 259167802Sjkim * FUNCTION: AcpiTbPrintTableHeader 260167802Sjkim * 261167802Sjkim * PARAMETERS: Address - Table physical address 262167802Sjkim * Header - Table header 263167802Sjkim * 264167802Sjkim * RETURN: None 265167802Sjkim * 266167802Sjkim * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 267167802Sjkim * 268167802Sjkim ******************************************************************************/ 269151937Sjkim 270167802Sjkimvoid 271167802SjkimAcpiTbPrintTableHeader ( 272167802Sjkim ACPI_PHYSICAL_ADDRESS Address, 273167802Sjkim ACPI_TABLE_HEADER *Header) 274167802Sjkim{ 275197104Sjkim ACPI_TABLE_HEADER LocalHeader; 276151937Sjkim 277197104Sjkim 278193267Sjkim /* 279193267Sjkim * The reason that the Address is cast to a void pointer is so that we 280193267Sjkim * can use %p which will work properly on both 32-bit and 64-bit hosts. 281193267Sjkim */ 282167802Sjkim if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) 283167802Sjkim { 284193267Sjkim /* FACS only has signature and length fields */ 285151937Sjkim 286193267Sjkim ACPI_INFO ((AE_INFO, "%4.4s %p %05X", 287193267Sjkim Header->Signature, ACPI_CAST_PTR (void, Address), 288193267Sjkim Header->Length)); 289167802Sjkim } 290167802Sjkim else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) 29167754Smsmith { 292167802Sjkim /* RSDP has no common fields */ 29367754Smsmith 294197104Sjkim ACPI_MEMCPY (LocalHeader.OemId, 295197104Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE); 296197104Sjkim AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); 297197104Sjkim 298193267Sjkim ACPI_INFO ((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", 299167802Sjkim ACPI_CAST_PTR (void, Address), 300167802Sjkim (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? 301167802Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, 302167802Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, 303197104Sjkim LocalHeader.OemId)); 304167802Sjkim } 305167802Sjkim else 306167802Sjkim { 307167802Sjkim /* Standard ACPI table with full common header */ 308151937Sjkim 309197104Sjkim AcpiTbCleanupTableHeader (&LocalHeader, Header); 310197104Sjkim 311167802Sjkim ACPI_INFO ((AE_INFO, 312193267Sjkim "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", 313197104Sjkim LocalHeader.Signature, ACPI_CAST_PTR (void, Address), 314197104Sjkim LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId, 315197104Sjkim LocalHeader.OemTableId, LocalHeader.OemRevision, 316197104Sjkim LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision)); 31767754Smsmith } 31867754Smsmith} 31967754Smsmith 32067754Smsmith 32167754Smsmith/******************************************************************************* 32267754Smsmith * 323167802Sjkim * FUNCTION: AcpiTbValidateChecksum 32467754Smsmith * 325167802Sjkim * PARAMETERS: Table - ACPI table to verify 326167802Sjkim * Length - Length of entire table 32767754Smsmith * 32867754Smsmith * RETURN: Status 32967754Smsmith * 330167802Sjkim * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 331167802Sjkim * exception on bad checksum. 33267754Smsmith * 33367754Smsmith ******************************************************************************/ 33467754Smsmith 33567754SmsmithACPI_STATUS 336167802SjkimAcpiTbVerifyChecksum ( 337167802Sjkim ACPI_TABLE_HEADER *Table, 338167802Sjkim UINT32 Length) 33967754Smsmith{ 340167802Sjkim UINT8 Checksum; 34167754Smsmith 34267754Smsmith 343167802Sjkim /* Compute the checksum on the table */ 34477424Smsmith 345167802Sjkim Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); 34677424Smsmith 347167802Sjkim /* Checksum ok? (should be zero) */ 34867754Smsmith 349167802Sjkim if (Checksum) 35067754Smsmith { 351167802Sjkim ACPI_WARNING ((AE_INFO, 352204773Sjkim "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", 353193267Sjkim Table->Signature, Table->Checksum, 354193267Sjkim (UINT8) (Table->Checksum - Checksum))); 355151937Sjkim 356167802Sjkim#if (ACPI_CHECKSUM_ABORT) 357167802Sjkim return (AE_BAD_CHECKSUM); 358167802Sjkim#endif 35967754Smsmith } 36067754Smsmith 361167802Sjkim return (AE_OK); 362167802Sjkim} 36367754Smsmith 36467754Smsmith 365167802Sjkim/******************************************************************************* 366167802Sjkim * 367167802Sjkim * FUNCTION: AcpiTbChecksum 368167802Sjkim * 369167802Sjkim * PARAMETERS: Buffer - Pointer to memory region to be checked 370167802Sjkim * Length - Length of this memory region 371167802Sjkim * 372167802Sjkim * RETURN: Checksum (UINT8) 373167802Sjkim * 374167802Sjkim * DESCRIPTION: Calculates circular checksum of memory region. 375167802Sjkim * 376167802Sjkim ******************************************************************************/ 377151937Sjkim 378167802SjkimUINT8 379167802SjkimAcpiTbChecksum ( 380167802Sjkim UINT8 *Buffer, 381193267Sjkim UINT32 Length) 382167802Sjkim{ 383167802Sjkim UINT8 Sum = 0; 384167802Sjkim UINT8 *End = Buffer + Length; 38567754Smsmith 38667754Smsmith 387167802Sjkim while (Buffer < End) 38867754Smsmith { 389167802Sjkim Sum = (UINT8) (Sum + *(Buffer++)); 39067754Smsmith } 39167754Smsmith 392167802Sjkim return Sum; 39367754Smsmith} 39467754Smsmith 39567754Smsmith 39667754Smsmith/******************************************************************************* 39767754Smsmith * 398206117Sjkim * FUNCTION: AcpiTbCheckDsdtHeader 399206117Sjkim * 400206117Sjkim * PARAMETERS: None 401206117Sjkim * 402206117Sjkim * RETURN: None 403206117Sjkim * 404206117Sjkim * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect 405206117Sjkim * if the DSDT has been replaced from outside the OS and/or if 406206117Sjkim * the DSDT header has been corrupted. 407206117Sjkim * 408206117Sjkim ******************************************************************************/ 409206117Sjkim 410206117Sjkimvoid 411206117SjkimAcpiTbCheckDsdtHeader ( 412206117Sjkim void) 413206117Sjkim{ 414206117Sjkim 415206117Sjkim /* Compare original length and checksum to current values */ 416206117Sjkim 417206117Sjkim if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || 418206117Sjkim AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) 419206117Sjkim { 420206117Sjkim ACPI_ERROR ((AE_INFO, 421206117Sjkim "The DSDT has been corrupted or replaced - old, new headers below")); 422206117Sjkim AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); 423206117Sjkim AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); 424206117Sjkim 425206117Sjkim /* Disable further error messages */ 426206117Sjkim 427206117Sjkim AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; 428206117Sjkim AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; 429206117Sjkim } 430206117Sjkim} 431206117Sjkim 432206117Sjkim 433206117Sjkim/******************************************************************************* 434206117Sjkim * 435206117Sjkim * FUNCTION: AcpiTbCopyDsdt 436206117Sjkim * 437206117Sjkim * PARAMETERS: TableDesc - Installed table to copy 438206117Sjkim * 439206117Sjkim * RETURN: None 440206117Sjkim * 441206117Sjkim * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. 442206117Sjkim * Some very bad BIOSs are known to either corrupt the DSDT or 443206117Sjkim * install a new, bad DSDT. This copy works around the problem. 444206117Sjkim * 445206117Sjkim ******************************************************************************/ 446206117Sjkim 447206117SjkimACPI_TABLE_HEADER * 448206117SjkimAcpiTbCopyDsdt ( 449206117Sjkim UINT32 TableIndex) 450206117Sjkim{ 451206117Sjkim ACPI_TABLE_HEADER *NewTable; 452206117Sjkim ACPI_TABLE_DESC *TableDesc; 453206117Sjkim 454206117Sjkim 455206117Sjkim TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; 456206117Sjkim 457206117Sjkim NewTable = ACPI_ALLOCATE (TableDesc->Length); 458206117Sjkim if (!NewTable) 459206117Sjkim { 460206117Sjkim ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", 461206117Sjkim TableDesc->Length)); 462206117Sjkim return (NULL); 463206117Sjkim } 464206117Sjkim 465206117Sjkim ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); 466206117Sjkim AcpiTbDeleteTable (TableDesc); 467206117Sjkim TableDesc->Pointer = NewTable; 468206117Sjkim TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED; 469206117Sjkim 470206117Sjkim ACPI_INFO ((AE_INFO, 471206117Sjkim "Forced DSDT copy: length 0x%05X copied locally, original unmapped", 472206117Sjkim NewTable->Length)); 473206117Sjkim 474206117Sjkim return (NewTable); 475206117Sjkim} 476206117Sjkim 477206117Sjkim 478206117Sjkim/******************************************************************************* 479206117Sjkim * 480167802Sjkim * FUNCTION: AcpiTbInstallTable 48167754Smsmith * 482167802Sjkim * PARAMETERS: Address - Physical address of DSDT or FACS 483167802Sjkim * Signature - Table signature, NULL if no need to 484167802Sjkim * match 485167802Sjkim * TableIndex - Index into root table array 48667754Smsmith * 487167802Sjkim * RETURN: None 48867754Smsmith * 489193267Sjkim * DESCRIPTION: Install an ACPI table into the global data structure. The 490193267Sjkim * table override mechanism is implemented here to allow the host 491193267Sjkim * OS to replace any table before it is installed in the root 492193267Sjkim * table array. 49367754Smsmith * 49467754Smsmith ******************************************************************************/ 49567754Smsmith 496167802Sjkimvoid 497167802SjkimAcpiTbInstallTable ( 498167802Sjkim ACPI_PHYSICAL_ADDRESS Address, 499167802Sjkim char *Signature, 500193267Sjkim UINT32 TableIndex) 50167754Smsmith{ 502193267Sjkim UINT8 Flags; 503193267Sjkim ACPI_STATUS Status; 504193267Sjkim ACPI_TABLE_HEADER *TableToInstall; 505193267Sjkim ACPI_TABLE_HEADER *MappedTable; 506193267Sjkim ACPI_TABLE_HEADER *OverrideTable = NULL; 50767754Smsmith 50867754Smsmith 509167802Sjkim if (!Address) 510167802Sjkim { 511167802Sjkim ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 512167802Sjkim Signature)); 513167802Sjkim return; 514167802Sjkim } 51567754Smsmith 516167802Sjkim /* Map just the table header */ 51767754Smsmith 518193267Sjkim MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 519193267Sjkim if (!MappedTable) 520167802Sjkim { 521167802Sjkim return; 522167802Sjkim } 52367754Smsmith 524193453Sjkim /* Skip SSDT when DSDT is overriden */ 525193453Sjkim 526193453Sjkim if (ACPI_COMPARE_NAME (MappedTable->Signature, ACPI_SIG_SSDT) && 527193453Sjkim (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & 528193453Sjkim ACPI_TABLE_ORIGIN_OVERRIDE)) 529193453Sjkim { 530193453Sjkim ACPI_INFO ((AE_INFO, 531193453Sjkim "%4.4s @ 0x%p Table override, replaced with:", ACPI_SIG_SSDT, 532193453Sjkim ACPI_CAST_PTR (void, Address))); 533193453Sjkim AcpiTbPrintTableHeader ( 534193453Sjkim AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Address, 535193453Sjkim AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer); 536193453Sjkim goto UnmapAndExit; 537193453Sjkim } 538193453Sjkim 539193267Sjkim /* If a particular signature is expected (DSDT/FACS), it must match */ 54067754Smsmith 541167802Sjkim if (Signature && 542193267Sjkim !ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 543167802Sjkim { 544193267Sjkim ACPI_ERROR ((AE_INFO, 545193267Sjkim "Invalid signature 0x%X for ACPI table, expected [%s]", 546193267Sjkim *ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature)); 547167802Sjkim goto UnmapAndExit; 548167802Sjkim } 54967754Smsmith 550193267Sjkim /* 551193267Sjkim * ACPI Table Override: 552193267Sjkim * 553193267Sjkim * Before we install the table, let the host OS override it with a new 554193267Sjkim * one if desired. Any table within the RSDT/XSDT can be replaced, 555193267Sjkim * including the DSDT which is pointed to by the FADT. 556193267Sjkim */ 557193267Sjkim Status = AcpiOsTableOverride (MappedTable, &OverrideTable); 558193267Sjkim if (ACPI_SUCCESS (Status) && OverrideTable) 559193267Sjkim { 560193267Sjkim ACPI_INFO ((AE_INFO, 561193267Sjkim "%4.4s @ 0x%p Table override, replaced with:", 562193267Sjkim MappedTable->Signature, ACPI_CAST_PTR (void, Address))); 563193267Sjkim 564193267Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable; 565193267Sjkim Address = ACPI_PTR_TO_PHYSADDR (OverrideTable); 566193267Sjkim 567193267Sjkim TableToInstall = OverrideTable; 568193267Sjkim Flags = ACPI_TABLE_ORIGIN_OVERRIDE; 569193267Sjkim } 570193267Sjkim else 571193267Sjkim { 572193267Sjkim TableToInstall = MappedTable; 573193267Sjkim Flags = ACPI_TABLE_ORIGIN_MAPPED; 574193267Sjkim } 575193267Sjkim 576167802Sjkim /* Initialize the table entry */ 577167802Sjkim 578167802Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Address = Address; 579193267Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length; 580167802Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags; 581167802Sjkim 582167802Sjkim ACPI_MOVE_32_TO_32 ( 583167802Sjkim &(AcpiGbl_RootTableList.Tables[TableIndex].Signature), 584193267Sjkim TableToInstall->Signature); 585167802Sjkim 586193267Sjkim AcpiTbPrintTableHeader (Address, TableToInstall); 587167802Sjkim 588167802Sjkim if (TableIndex == ACPI_TABLE_INDEX_DSDT) 58967754Smsmith { 590167802Sjkim /* Global integer width is based upon revision of the DSDT */ 59167754Smsmith 592193267Sjkim AcpiUtSetIntegerWidth (TableToInstall->Revision); 59367754Smsmith } 594167802Sjkim 595167802SjkimUnmapAndExit: 596193267Sjkim AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 59767754Smsmith} 59867754Smsmith 59967754Smsmith 60067754Smsmith/******************************************************************************* 60167754Smsmith * 602167802Sjkim * FUNCTION: AcpiTbGetRootTableEntry 60367754Smsmith * 604167802Sjkim * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry 605167802Sjkim * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) 60667754Smsmith * 607167802Sjkim * RETURN: Physical address extracted from the root table 60867754Smsmith * 609167802Sjkim * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on 610167802Sjkim * both 32-bit and 64-bit platforms 61167754Smsmith * 612167802Sjkim * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on 613167802Sjkim * 64-bit platforms. 614167802Sjkim * 61567754Smsmith ******************************************************************************/ 61667754Smsmith 617167802Sjkimstatic ACPI_PHYSICAL_ADDRESS 618167802SjkimAcpiTbGetRootTableEntry ( 619167802Sjkim UINT8 *TableEntry, 620193267Sjkim UINT32 TableEntrySize) 62167754Smsmith{ 622167802Sjkim UINT64 Address64; 62367754Smsmith 62467754Smsmith 625167802Sjkim /* 626167802Sjkim * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): 627167802Sjkim * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT 628167802Sjkim */ 629167802Sjkim if (TableEntrySize == sizeof (UINT32)) 63067754Smsmith { 631167802Sjkim /* 632167802Sjkim * 32-bit platform, RSDT: Return 32-bit table entry 633167802Sjkim * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return 634167802Sjkim */ 635167802Sjkim return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); 636167802Sjkim } 637167802Sjkim else 638167802Sjkim { 639167802Sjkim /* 640167802Sjkim * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return 641193267Sjkim * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, 642193267Sjkim * return 64-bit 643167802Sjkim */ 644167802Sjkim ACPI_MOVE_64_TO_64 (&Address64, TableEntry); 64567754Smsmith 646167802Sjkim#if ACPI_MACHINE_WIDTH == 32 647167802Sjkim if (Address64 > ACPI_UINT32_MAX) 648167802Sjkim { 649167802Sjkim /* Will truncate 64-bit address to 32 bits, issue warning */ 65067754Smsmith 651167802Sjkim ACPI_WARNING ((AE_INFO, 652204773Sjkim "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," 653193267Sjkim " truncating", 654167802Sjkim ACPI_FORMAT_UINT64 (Address64))); 65567754Smsmith } 656167802Sjkim#endif 657167802Sjkim return ((ACPI_PHYSICAL_ADDRESS) (Address64)); 65867754Smsmith } 65967754Smsmith} 66067754Smsmith 66167754Smsmith 662151937Sjkim/******************************************************************************* 663151937Sjkim * 664167802Sjkim * FUNCTION: AcpiTbParseRootTable 665151937Sjkim * 666167802Sjkim * PARAMETERS: Rsdp - Pointer to the RSDP 667151937Sjkim * 668167802Sjkim * RETURN: Status 669151937Sjkim * 670167802Sjkim * DESCRIPTION: This function is called to parse the Root System Description 671167802Sjkim * Table (RSDT or XSDT) 672167802Sjkim * 673167802Sjkim * NOTE: Tables are mapped (not copied) for efficiency. The FACS must 674167802Sjkim * be mapped and cannot be copied because it contains the actual 675167802Sjkim * memory location of the ACPI Global Lock. 676167802Sjkim * 677151937Sjkim ******************************************************************************/ 678151937Sjkim 679151937SjkimACPI_STATUS 680167802SjkimAcpiTbParseRootTable ( 681193267Sjkim ACPI_PHYSICAL_ADDRESS RsdpAddress) 682151937Sjkim{ 683167802Sjkim ACPI_TABLE_RSDP *Rsdp; 684193267Sjkim UINT32 TableEntrySize; 685193267Sjkim UINT32 i; 686167802Sjkim UINT32 TableCount; 687167802Sjkim ACPI_TABLE_HEADER *Table; 688167802Sjkim ACPI_PHYSICAL_ADDRESS Address; 689167802Sjkim UINT32 Length; 690167802Sjkim UINT8 *TableEntry; 691167802Sjkim ACPI_STATUS Status; 692151937Sjkim 693151937Sjkim 694167802Sjkim ACPI_FUNCTION_TRACE (TbParseRootTable); 695151937Sjkim 696151937Sjkim 697167802Sjkim /* 698167802Sjkim * Map the entire RSDP and extract the address of the RSDT or XSDT 699167802Sjkim */ 700167802Sjkim Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); 701167802Sjkim if (!Rsdp) 702151937Sjkim { 703167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 704167802Sjkim } 705167802Sjkim 706193267Sjkim AcpiTbPrintTableHeader (RsdpAddress, 707193267Sjkim ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); 708167802Sjkim 709167802Sjkim /* Differentiate between RSDT and XSDT root tables */ 710167802Sjkim 711167802Sjkim if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) 712167802Sjkim { 713167802Sjkim /* 714167802Sjkim * Root table is an XSDT (64-bit physical addresses). We must use the 715167802Sjkim * XSDT if the revision is > 1 and the XSDT pointer is present, as per 716167802Sjkim * the ACPI specification. 717167802Sjkim */ 718167802Sjkim Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; 719167802Sjkim TableEntrySize = sizeof (UINT64); 720167802Sjkim } 721167802Sjkim else 722167802Sjkim { 723167802Sjkim /* Root table is an RSDT (32-bit physical addresses) */ 724167802Sjkim 725167802Sjkim Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; 726167802Sjkim TableEntrySize = sizeof (UINT32); 727167802Sjkim } 728167802Sjkim 729167802Sjkim /* 730167802Sjkim * It is not possible to map more than one entry in some environments, 731167802Sjkim * so unmap the RSDP here before mapping other tables 732167802Sjkim */ 733167802Sjkim AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); 734167802Sjkim 735167802Sjkim 736167802Sjkim /* Map the RSDT/XSDT table header to get the full table length */ 737167802Sjkim 738167802Sjkim Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 739167802Sjkim if (!Table) 740167802Sjkim { 741167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 742167802Sjkim } 743167802Sjkim 744167802Sjkim AcpiTbPrintTableHeader (Address, Table); 745167802Sjkim 746167802Sjkim /* Get the length of the full table, verify length and map entire table */ 747167802Sjkim 748167802Sjkim Length = Table->Length; 749167802Sjkim AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 750167802Sjkim 751167802Sjkim if (Length < sizeof (ACPI_TABLE_HEADER)) 752167802Sjkim { 753167802Sjkim ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); 754167802Sjkim return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 755167802Sjkim } 756167802Sjkim 757167802Sjkim Table = AcpiOsMapMemory (Address, Length); 758167802Sjkim if (!Table) 759167802Sjkim { 760167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 761167802Sjkim } 762167802Sjkim 763167802Sjkim /* Validate the root table checksum */ 764167802Sjkim 765167802Sjkim Status = AcpiTbVerifyChecksum (Table, Length); 766167802Sjkim if (ACPI_FAILURE (Status)) 767167802Sjkim { 768167802Sjkim AcpiOsUnmapMemory (Table, Length); 769167802Sjkim return_ACPI_STATUS (Status); 770167802Sjkim } 771167802Sjkim 772167802Sjkim /* Calculate the number of tables described in the root table */ 773167802Sjkim 774193267Sjkim TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / 775193267Sjkim TableEntrySize); 776167802Sjkim 777167802Sjkim /* 778193267Sjkim * First two entries in the table array are reserved for the DSDT 779193267Sjkim * and FACS, which are not actually present in the RSDT/XSDT - they 780193267Sjkim * come from the FADT 781167802Sjkim */ 782167802Sjkim TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); 783207344Sjkim AcpiGbl_RootTableList.CurrentTableCount = 2; 784167802Sjkim 785167802Sjkim /* 786167802Sjkim * Initialize the root table array from the RSDT/XSDT 787167802Sjkim */ 788167802Sjkim for (i = 0; i < TableCount; i++) 789167802Sjkim { 790207344Sjkim if (AcpiGbl_RootTableList.CurrentTableCount >= 791207344Sjkim AcpiGbl_RootTableList.MaxTableCount) 792151937Sjkim { 793167802Sjkim /* There is no more room in the root table array, attempt resize */ 794167802Sjkim 795167802Sjkim Status = AcpiTbResizeRootTableList (); 796167802Sjkim if (ACPI_FAILURE (Status)) 797151937Sjkim { 798167802Sjkim ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", 799193267Sjkim (unsigned) (TableCount - 800207344Sjkim (AcpiGbl_RootTableList.CurrentTableCount - 2)))); 801167802Sjkim break; 802151937Sjkim } 803167802Sjkim } 804151937Sjkim 805167802Sjkim /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ 806167802Sjkim 807207344Sjkim AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address = 808167802Sjkim AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); 809167802Sjkim 810167802Sjkim TableEntry += TableEntrySize; 811207344Sjkim AcpiGbl_RootTableList.CurrentTableCount++; 812167802Sjkim } 813167802Sjkim 814167802Sjkim /* 815167802Sjkim * It is not possible to map more than one entry in some environments, 816167802Sjkim * so unmap the root table here before mapping other tables 817167802Sjkim */ 818167802Sjkim AcpiOsUnmapMemory (Table, Length); 819167802Sjkim 820167802Sjkim /* 821167802Sjkim * Complete the initialization of the root table array by examining 822167802Sjkim * the header of each table 823167802Sjkim */ 824207344Sjkim for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 825167802Sjkim { 826167802Sjkim AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, 827193267Sjkim NULL, i); 828167802Sjkim 829167802Sjkim /* Special case for FADT - get the DSDT and FACS */ 830167802Sjkim 831167802Sjkim if (ACPI_COMPARE_NAME ( 832167802Sjkim &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) 833167802Sjkim { 834193267Sjkim AcpiTbParseFadt (i); 835151937Sjkim } 836151937Sjkim } 837151937Sjkim 838167802Sjkim return_ACPI_STATUS (AE_OK); 839151937Sjkim} 840