167754Smsmith/****************************************************************************** 267754Smsmith * 3167802Sjkim * Module Name: tbutils - table utilities 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4467754Smsmith#define __TBUTILS_C__ 4567754Smsmith 46193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 47193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 48193341Sjkim#include <contrib/dev/acpica/include/actables.h> 4967754Smsmith 5077424Smsmith#define _COMPONENT ACPI_TABLES 5191116Smsmith ACPI_MODULE_NAME ("tbutils") 5267754Smsmith 53151937Sjkim/* Local prototypes */ 5467754Smsmith 55197104Sjkimstatic void 56197104SjkimAcpiTbFixString ( 57197104Sjkim char *String, 58197104Sjkim ACPI_SIZE Length); 59197104Sjkim 60197104Sjkimstatic void 61197104SjkimAcpiTbCleanupTableHeader ( 62197104Sjkim ACPI_TABLE_HEADER *OutHeader, 63197104Sjkim ACPI_TABLE_HEADER *Header); 64197104Sjkim 65167802Sjkimstatic ACPI_PHYSICAL_ADDRESS 66167802SjkimAcpiTbGetRootTableEntry ( 67167802Sjkim UINT8 *TableEntry, 68193267Sjkim UINT32 TableEntrySize); 69151937Sjkim 70151937Sjkim 7167754Smsmith/******************************************************************************* 7267754Smsmith * 73193267Sjkim * FUNCTION: AcpiTbInitializeFacs 74193267Sjkim * 75193267Sjkim * PARAMETERS: None 76193267Sjkim * 77193267Sjkim * RETURN: Status 78193267Sjkim * 79193267Sjkim * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global 80193267Sjkim * for accessing the Global Lock and Firmware Waking Vector 81193267Sjkim * 82193267Sjkim ******************************************************************************/ 83193267Sjkim 84193267SjkimACPI_STATUS 85193267SjkimAcpiTbInitializeFacs ( 86193267Sjkim void) 87193267Sjkim{ 88193267Sjkim ACPI_STATUS Status; 89193267Sjkim 90193267Sjkim 91193267Sjkim Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, 92193267Sjkim ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); 93193267Sjkim return (Status); 94193267Sjkim} 95193267Sjkim 96193267Sjkim 97193267Sjkim/******************************************************************************* 98193267Sjkim * 99167802Sjkim * FUNCTION: AcpiTbTablesLoaded 10067754Smsmith * 101167802Sjkim * PARAMETERS: None 10267754Smsmith * 103167802Sjkim * RETURN: TRUE if required ACPI tables are loaded 10467754Smsmith * 105167802Sjkim * DESCRIPTION: Determine if the minimum required ACPI tables are present 106167802Sjkim * (FADT, FACS, DSDT) 107151937Sjkim * 10867754Smsmith ******************************************************************************/ 10967754Smsmith 110167802SjkimBOOLEAN 111167802SjkimAcpiTbTablesLoaded ( 112167802Sjkim void) 11367754Smsmith{ 11467754Smsmith 115207344Sjkim if (AcpiGbl_RootTableList.CurrentTableCount >= 3) 116167802Sjkim { 117167802Sjkim return (TRUE); 118167802Sjkim } 11983174Smsmith 120167802Sjkim return (FALSE); 121167802Sjkim} 12267754Smsmith 12382367Smsmith 124167802Sjkim/******************************************************************************* 125167802Sjkim * 126197104Sjkim * FUNCTION: AcpiTbFixString 127197104Sjkim * 128197104Sjkim * PARAMETERS: String - String to be repaired 129197104Sjkim * Length - Maximum length 130197104Sjkim * 131197104Sjkim * RETURN: None 132197104Sjkim * 133197104Sjkim * DESCRIPTION: Replace every non-printable or non-ascii byte in the string 134197104Sjkim * with a question mark '?'. 135197104Sjkim * 136197104Sjkim ******************************************************************************/ 137197104Sjkim 138197104Sjkimstatic void 139197104SjkimAcpiTbFixString ( 140197104Sjkim char *String, 141197104Sjkim ACPI_SIZE Length) 142197104Sjkim{ 143197104Sjkim 144197104Sjkim while (Length && *String) 145197104Sjkim { 146197104Sjkim if (!ACPI_IS_PRINT (*String)) 147197104Sjkim { 148197104Sjkim *String = '?'; 149197104Sjkim } 150197104Sjkim String++; 151197104Sjkim Length--; 152197104Sjkim } 153197104Sjkim} 154197104Sjkim 155197104Sjkim 156197104Sjkim/******************************************************************************* 157197104Sjkim * 158197104Sjkim * FUNCTION: AcpiTbCleanupTableHeader 159197104Sjkim * 160197104Sjkim * PARAMETERS: OutHeader - Where the cleaned header is returned 161197104Sjkim * Header - Input ACPI table header 162197104Sjkim * 163197104Sjkim * RETURN: Returns the cleaned header in OutHeader 164197104Sjkim * 165197104Sjkim * DESCRIPTION: Copy the table header and ensure that all "string" fields in 166197104Sjkim * the header consist of printable characters. 167197104Sjkim * 168197104Sjkim ******************************************************************************/ 169197104Sjkim 170197104Sjkimstatic void 171197104SjkimAcpiTbCleanupTableHeader ( 172197104Sjkim ACPI_TABLE_HEADER *OutHeader, 173197104Sjkim ACPI_TABLE_HEADER *Header) 174197104Sjkim{ 175197104Sjkim 176197104Sjkim ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); 177197104Sjkim 178197104Sjkim AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE); 179197104Sjkim AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); 180197104Sjkim AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE); 181197104Sjkim AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE); 182197104Sjkim} 183197104Sjkim 184197104Sjkim 185197104Sjkim/******************************************************************************* 186197104Sjkim * 187167802Sjkim * FUNCTION: AcpiTbPrintTableHeader 188167802Sjkim * 189167802Sjkim * PARAMETERS: Address - Table physical address 190167802Sjkim * Header - Table header 191167802Sjkim * 192167802Sjkim * RETURN: None 193167802Sjkim * 194167802Sjkim * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 195167802Sjkim * 196167802Sjkim ******************************************************************************/ 197151937Sjkim 198167802Sjkimvoid 199167802SjkimAcpiTbPrintTableHeader ( 200167802Sjkim ACPI_PHYSICAL_ADDRESS Address, 201167802Sjkim ACPI_TABLE_HEADER *Header) 202167802Sjkim{ 203197104Sjkim ACPI_TABLE_HEADER LocalHeader; 204151937Sjkim 205197104Sjkim 206193267Sjkim /* 207193267Sjkim * The reason that the Address is cast to a void pointer is so that we 208193267Sjkim * can use %p which will work properly on both 32-bit and 64-bit hosts. 209193267Sjkim */ 210167802Sjkim if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) 211167802Sjkim { 212193267Sjkim /* FACS only has signature and length fields */ 213151937Sjkim 214193267Sjkim ACPI_INFO ((AE_INFO, "%4.4s %p %05X", 215193267Sjkim Header->Signature, ACPI_CAST_PTR (void, Address), 216193267Sjkim Header->Length)); 217167802Sjkim } 218167802Sjkim else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) 21967754Smsmith { 220167802Sjkim /* RSDP has no common fields */ 22167754Smsmith 222197104Sjkim ACPI_MEMCPY (LocalHeader.OemId, 223197104Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE); 224197104Sjkim AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); 225197104Sjkim 226193267Sjkim ACPI_INFO ((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", 227167802Sjkim ACPI_CAST_PTR (void, Address), 228167802Sjkim (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? 229167802Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, 230167802Sjkim ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, 231197104Sjkim LocalHeader.OemId)); 232167802Sjkim } 233167802Sjkim else 234167802Sjkim { 235167802Sjkim /* Standard ACPI table with full common header */ 236151937Sjkim 237197104Sjkim AcpiTbCleanupTableHeader (&LocalHeader, Header); 238197104Sjkim 239167802Sjkim ACPI_INFO ((AE_INFO, 240193267Sjkim "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", 241197104Sjkim LocalHeader.Signature, ACPI_CAST_PTR (void, Address), 242197104Sjkim LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId, 243197104Sjkim LocalHeader.OemTableId, LocalHeader.OemRevision, 244197104Sjkim LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision)); 24567754Smsmith } 24667754Smsmith} 24767754Smsmith 24867754Smsmith 24967754Smsmith/******************************************************************************* 25067754Smsmith * 251167802Sjkim * FUNCTION: AcpiTbValidateChecksum 25267754Smsmith * 253167802Sjkim * PARAMETERS: Table - ACPI table to verify 254167802Sjkim * Length - Length of entire table 25567754Smsmith * 25667754Smsmith * RETURN: Status 25767754Smsmith * 258167802Sjkim * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 259167802Sjkim * exception on bad checksum. 26067754Smsmith * 26167754Smsmith ******************************************************************************/ 26267754Smsmith 26367754SmsmithACPI_STATUS 264167802SjkimAcpiTbVerifyChecksum ( 265167802Sjkim ACPI_TABLE_HEADER *Table, 266167802Sjkim UINT32 Length) 26767754Smsmith{ 268167802Sjkim UINT8 Checksum; 26967754Smsmith 27067754Smsmith 271167802Sjkim /* Compute the checksum on the table */ 27277424Smsmith 273167802Sjkim Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); 27477424Smsmith 275167802Sjkim /* Checksum ok? (should be zero) */ 27667754Smsmith 277167802Sjkim if (Checksum) 27867754Smsmith { 279167802Sjkim ACPI_WARNING ((AE_INFO, 280204773Sjkim "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", 281193267Sjkim Table->Signature, Table->Checksum, 282193267Sjkim (UINT8) (Table->Checksum - Checksum))); 283151937Sjkim 284167802Sjkim#if (ACPI_CHECKSUM_ABORT) 285167802Sjkim return (AE_BAD_CHECKSUM); 286167802Sjkim#endif 28767754Smsmith } 28867754Smsmith 289167802Sjkim return (AE_OK); 290167802Sjkim} 29167754Smsmith 29267754Smsmith 293167802Sjkim/******************************************************************************* 294167802Sjkim * 295167802Sjkim * FUNCTION: AcpiTbChecksum 296167802Sjkim * 297167802Sjkim * PARAMETERS: Buffer - Pointer to memory region to be checked 298167802Sjkim * Length - Length of this memory region 299167802Sjkim * 300167802Sjkim * RETURN: Checksum (UINT8) 301167802Sjkim * 302167802Sjkim * DESCRIPTION: Calculates circular checksum of memory region. 303167802Sjkim * 304167802Sjkim ******************************************************************************/ 305151937Sjkim 306167802SjkimUINT8 307167802SjkimAcpiTbChecksum ( 308167802Sjkim UINT8 *Buffer, 309193267Sjkim UINT32 Length) 310167802Sjkim{ 311167802Sjkim UINT8 Sum = 0; 312167802Sjkim UINT8 *End = Buffer + Length; 31367754Smsmith 31467754Smsmith 315167802Sjkim while (Buffer < End) 31667754Smsmith { 317167802Sjkim Sum = (UINT8) (Sum + *(Buffer++)); 31867754Smsmith } 31967754Smsmith 320167802Sjkim return Sum; 32167754Smsmith} 32267754Smsmith 32367754Smsmith 32467754Smsmith/******************************************************************************* 32567754Smsmith * 326206117Sjkim * FUNCTION: AcpiTbCheckDsdtHeader 327206117Sjkim * 328206117Sjkim * PARAMETERS: None 329206117Sjkim * 330206117Sjkim * RETURN: None 331206117Sjkim * 332206117Sjkim * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect 333206117Sjkim * if the DSDT has been replaced from outside the OS and/or if 334206117Sjkim * the DSDT header has been corrupted. 335206117Sjkim * 336206117Sjkim ******************************************************************************/ 337206117Sjkim 338206117Sjkimvoid 339206117SjkimAcpiTbCheckDsdtHeader ( 340206117Sjkim void) 341206117Sjkim{ 342206117Sjkim 343206117Sjkim /* Compare original length and checksum to current values */ 344206117Sjkim 345206117Sjkim if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || 346206117Sjkim AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) 347206117Sjkim { 348206117Sjkim ACPI_ERROR ((AE_INFO, 349206117Sjkim "The DSDT has been corrupted or replaced - old, new headers below")); 350206117Sjkim AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); 351206117Sjkim AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); 352206117Sjkim 353206117Sjkim /* Disable further error messages */ 354206117Sjkim 355206117Sjkim AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; 356206117Sjkim AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; 357206117Sjkim } 358206117Sjkim} 359206117Sjkim 360206117Sjkim 361206117Sjkim/******************************************************************************* 362206117Sjkim * 363206117Sjkim * FUNCTION: AcpiTbCopyDsdt 364206117Sjkim * 365206117Sjkim * PARAMETERS: TableDesc - Installed table to copy 366206117Sjkim * 367206117Sjkim * RETURN: None 368206117Sjkim * 369206117Sjkim * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. 370206117Sjkim * Some very bad BIOSs are known to either corrupt the DSDT or 371206117Sjkim * install a new, bad DSDT. This copy works around the problem. 372206117Sjkim * 373206117Sjkim ******************************************************************************/ 374206117Sjkim 375206117SjkimACPI_TABLE_HEADER * 376206117SjkimAcpiTbCopyDsdt ( 377206117Sjkim UINT32 TableIndex) 378206117Sjkim{ 379206117Sjkim ACPI_TABLE_HEADER *NewTable; 380206117Sjkim ACPI_TABLE_DESC *TableDesc; 381206117Sjkim 382206117Sjkim 383206117Sjkim TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; 384206117Sjkim 385206117Sjkim NewTable = ACPI_ALLOCATE (TableDesc->Length); 386206117Sjkim if (!NewTable) 387206117Sjkim { 388206117Sjkim ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", 389206117Sjkim TableDesc->Length)); 390206117Sjkim return (NULL); 391206117Sjkim } 392206117Sjkim 393206117Sjkim ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); 394206117Sjkim AcpiTbDeleteTable (TableDesc); 395206117Sjkim TableDesc->Pointer = NewTable; 396206117Sjkim TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED; 397206117Sjkim 398206117Sjkim ACPI_INFO ((AE_INFO, 399206117Sjkim "Forced DSDT copy: length 0x%05X copied locally, original unmapped", 400206117Sjkim NewTable->Length)); 401206117Sjkim 402206117Sjkim return (NewTable); 403206117Sjkim} 404206117Sjkim 405206117Sjkim 406206117Sjkim/******************************************************************************* 407206117Sjkim * 408167802Sjkim * FUNCTION: AcpiTbInstallTable 40967754Smsmith * 410167802Sjkim * PARAMETERS: Address - Physical address of DSDT or FACS 411167802Sjkim * Signature - Table signature, NULL if no need to 412167802Sjkim * match 413167802Sjkim * TableIndex - Index into root table array 41467754Smsmith * 415167802Sjkim * RETURN: None 41667754Smsmith * 417193267Sjkim * DESCRIPTION: Install an ACPI table into the global data structure. The 418193267Sjkim * table override mechanism is implemented here to allow the host 419193267Sjkim * OS to replace any table before it is installed in the root 420193267Sjkim * table array. 42167754Smsmith * 42267754Smsmith ******************************************************************************/ 42367754Smsmith 424167802Sjkimvoid 425167802SjkimAcpiTbInstallTable ( 426167802Sjkim ACPI_PHYSICAL_ADDRESS Address, 427167802Sjkim char *Signature, 428193267Sjkim UINT32 TableIndex) 42967754Smsmith{ 430193267Sjkim UINT8 Flags; 431193267Sjkim ACPI_STATUS Status; 432193267Sjkim ACPI_TABLE_HEADER *TableToInstall; 433193267Sjkim ACPI_TABLE_HEADER *MappedTable; 434193267Sjkim ACPI_TABLE_HEADER *OverrideTable = NULL; 43567754Smsmith 43667754Smsmith 437167802Sjkim if (!Address) 438167802Sjkim { 439167802Sjkim ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 440167802Sjkim Signature)); 441167802Sjkim return; 442167802Sjkim } 44367754Smsmith 444167802Sjkim /* Map just the table header */ 44567754Smsmith 446193267Sjkim MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 447193267Sjkim if (!MappedTable) 448167802Sjkim { 449167802Sjkim return; 450167802Sjkim } 45167754Smsmith 452193453Sjkim /* Skip SSDT when DSDT is overriden */ 453193453Sjkim 454193453Sjkim if (ACPI_COMPARE_NAME (MappedTable->Signature, ACPI_SIG_SSDT) && 455193453Sjkim (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & 456193453Sjkim ACPI_TABLE_ORIGIN_OVERRIDE)) 457193453Sjkim { 458193453Sjkim ACPI_INFO ((AE_INFO, 459193453Sjkim "%4.4s @ 0x%p Table override, replaced with:", ACPI_SIG_SSDT, 460193453Sjkim ACPI_CAST_PTR (void, Address))); 461193453Sjkim AcpiTbPrintTableHeader ( 462193453Sjkim AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Address, 463193453Sjkim AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer); 464193453Sjkim goto UnmapAndExit; 465193453Sjkim } 466193453Sjkim 467193267Sjkim /* If a particular signature is expected (DSDT/FACS), it must match */ 46867754Smsmith 469167802Sjkim if (Signature && 470193267Sjkim !ACPI_COMPARE_NAME (MappedTable->Signature, Signature)) 471167802Sjkim { 472193267Sjkim ACPI_ERROR ((AE_INFO, 473193267Sjkim "Invalid signature 0x%X for ACPI table, expected [%s]", 474193267Sjkim *ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature)); 475167802Sjkim goto UnmapAndExit; 476167802Sjkim } 47767754Smsmith 478193267Sjkim /* 479193267Sjkim * ACPI Table Override: 480193267Sjkim * 481193267Sjkim * Before we install the table, let the host OS override it with a new 482193267Sjkim * one if desired. Any table within the RSDT/XSDT can be replaced, 483193267Sjkim * including the DSDT which is pointed to by the FADT. 484193267Sjkim */ 485193267Sjkim Status = AcpiOsTableOverride (MappedTable, &OverrideTable); 486193267Sjkim if (ACPI_SUCCESS (Status) && OverrideTable) 487193267Sjkim { 488193267Sjkim ACPI_INFO ((AE_INFO, 489193267Sjkim "%4.4s @ 0x%p Table override, replaced with:", 490193267Sjkim MappedTable->Signature, ACPI_CAST_PTR (void, Address))); 491193267Sjkim 492193267Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable; 493193267Sjkim Address = ACPI_PTR_TO_PHYSADDR (OverrideTable); 494193267Sjkim 495193267Sjkim TableToInstall = OverrideTable; 496193267Sjkim Flags = ACPI_TABLE_ORIGIN_OVERRIDE; 497193267Sjkim } 498193267Sjkim else 499193267Sjkim { 500193267Sjkim TableToInstall = MappedTable; 501193267Sjkim Flags = ACPI_TABLE_ORIGIN_MAPPED; 502193267Sjkim } 503193267Sjkim 504167802Sjkim /* Initialize the table entry */ 505167802Sjkim 506167802Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Address = Address; 507193267Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length; 508167802Sjkim AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags; 509167802Sjkim 510167802Sjkim ACPI_MOVE_32_TO_32 ( 511167802Sjkim &(AcpiGbl_RootTableList.Tables[TableIndex].Signature), 512193267Sjkim TableToInstall->Signature); 513167802Sjkim 514193267Sjkim AcpiTbPrintTableHeader (Address, TableToInstall); 515167802Sjkim 516167802Sjkim if (TableIndex == ACPI_TABLE_INDEX_DSDT) 51767754Smsmith { 518167802Sjkim /* Global integer width is based upon revision of the DSDT */ 51967754Smsmith 520193267Sjkim AcpiUtSetIntegerWidth (TableToInstall->Revision); 52167754Smsmith } 522167802Sjkim 523167802SjkimUnmapAndExit: 524193267Sjkim AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER)); 52567754Smsmith} 52667754Smsmith 52767754Smsmith 52867754Smsmith/******************************************************************************* 52967754Smsmith * 530167802Sjkim * FUNCTION: AcpiTbGetRootTableEntry 53167754Smsmith * 532167802Sjkim * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry 533167802Sjkim * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) 53467754Smsmith * 535167802Sjkim * RETURN: Physical address extracted from the root table 53667754Smsmith * 537167802Sjkim * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on 538167802Sjkim * both 32-bit and 64-bit platforms 53967754Smsmith * 540167802Sjkim * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on 541167802Sjkim * 64-bit platforms. 542167802Sjkim * 54367754Smsmith ******************************************************************************/ 54467754Smsmith 545167802Sjkimstatic ACPI_PHYSICAL_ADDRESS 546167802SjkimAcpiTbGetRootTableEntry ( 547167802Sjkim UINT8 *TableEntry, 548193267Sjkim UINT32 TableEntrySize) 54967754Smsmith{ 550167802Sjkim UINT64 Address64; 55167754Smsmith 55267754Smsmith 553167802Sjkim /* 554167802Sjkim * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): 555167802Sjkim * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT 556167802Sjkim */ 557167802Sjkim if (TableEntrySize == sizeof (UINT32)) 55867754Smsmith { 559167802Sjkim /* 560167802Sjkim * 32-bit platform, RSDT: Return 32-bit table entry 561167802Sjkim * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return 562167802Sjkim */ 563167802Sjkim return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); 564167802Sjkim } 565167802Sjkim else 566167802Sjkim { 567167802Sjkim /* 568167802Sjkim * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return 569193267Sjkim * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, 570193267Sjkim * return 64-bit 571167802Sjkim */ 572167802Sjkim ACPI_MOVE_64_TO_64 (&Address64, TableEntry); 57367754Smsmith 574167802Sjkim#if ACPI_MACHINE_WIDTH == 32 575167802Sjkim if (Address64 > ACPI_UINT32_MAX) 576167802Sjkim { 577167802Sjkim /* Will truncate 64-bit address to 32 bits, issue warning */ 57867754Smsmith 579167802Sjkim ACPI_WARNING ((AE_INFO, 580204773Sjkim "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," 581193267Sjkim " truncating", 582167802Sjkim ACPI_FORMAT_UINT64 (Address64))); 58367754Smsmith } 584167802Sjkim#endif 585167802Sjkim return ((ACPI_PHYSICAL_ADDRESS) (Address64)); 58667754Smsmith } 58767754Smsmith} 58867754Smsmith 58967754Smsmith 590151937Sjkim/******************************************************************************* 591151937Sjkim * 592167802Sjkim * FUNCTION: AcpiTbParseRootTable 593151937Sjkim * 594167802Sjkim * PARAMETERS: Rsdp - Pointer to the RSDP 595151937Sjkim * 596167802Sjkim * RETURN: Status 597151937Sjkim * 598167802Sjkim * DESCRIPTION: This function is called to parse the Root System Description 599167802Sjkim * Table (RSDT or XSDT) 600167802Sjkim * 601167802Sjkim * NOTE: Tables are mapped (not copied) for efficiency. The FACS must 602167802Sjkim * be mapped and cannot be copied because it contains the actual 603167802Sjkim * memory location of the ACPI Global Lock. 604167802Sjkim * 605151937Sjkim ******************************************************************************/ 606151937Sjkim 607151937SjkimACPI_STATUS 608167802SjkimAcpiTbParseRootTable ( 609193267Sjkim ACPI_PHYSICAL_ADDRESS RsdpAddress) 610151937Sjkim{ 611167802Sjkim ACPI_TABLE_RSDP *Rsdp; 612193267Sjkim UINT32 TableEntrySize; 613193267Sjkim UINT32 i; 614167802Sjkim UINT32 TableCount; 615167802Sjkim ACPI_TABLE_HEADER *Table; 616167802Sjkim ACPI_PHYSICAL_ADDRESS Address; 617167802Sjkim UINT32 Length; 618167802Sjkim UINT8 *TableEntry; 619167802Sjkim ACPI_STATUS Status; 620151937Sjkim 621151937Sjkim 622167802Sjkim ACPI_FUNCTION_TRACE (TbParseRootTable); 623151937Sjkim 624151937Sjkim 625167802Sjkim /* 626167802Sjkim * Map the entire RSDP and extract the address of the RSDT or XSDT 627167802Sjkim */ 628167802Sjkim Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); 629167802Sjkim if (!Rsdp) 630151937Sjkim { 631167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 632167802Sjkim } 633167802Sjkim 634193267Sjkim AcpiTbPrintTableHeader (RsdpAddress, 635193267Sjkim ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); 636167802Sjkim 637167802Sjkim /* Differentiate between RSDT and XSDT root tables */ 638167802Sjkim 639167802Sjkim if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) 640167802Sjkim { 641167802Sjkim /* 642167802Sjkim * Root table is an XSDT (64-bit physical addresses). We must use the 643167802Sjkim * XSDT if the revision is > 1 and the XSDT pointer is present, as per 644167802Sjkim * the ACPI specification. 645167802Sjkim */ 646167802Sjkim Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; 647167802Sjkim TableEntrySize = sizeof (UINT64); 648167802Sjkim } 649167802Sjkim else 650167802Sjkim { 651167802Sjkim /* Root table is an RSDT (32-bit physical addresses) */ 652167802Sjkim 653167802Sjkim Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; 654167802Sjkim TableEntrySize = sizeof (UINT32); 655167802Sjkim } 656167802Sjkim 657167802Sjkim /* 658167802Sjkim * It is not possible to map more than one entry in some environments, 659167802Sjkim * so unmap the RSDP here before mapping other tables 660167802Sjkim */ 661167802Sjkim AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); 662167802Sjkim 663167802Sjkim 664167802Sjkim /* Map the RSDT/XSDT table header to get the full table length */ 665167802Sjkim 666167802Sjkim Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 667167802Sjkim if (!Table) 668167802Sjkim { 669167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 670167802Sjkim } 671167802Sjkim 672167802Sjkim AcpiTbPrintTableHeader (Address, Table); 673167802Sjkim 674167802Sjkim /* Get the length of the full table, verify length and map entire table */ 675167802Sjkim 676167802Sjkim Length = Table->Length; 677167802Sjkim AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 678167802Sjkim 679167802Sjkim if (Length < sizeof (ACPI_TABLE_HEADER)) 680167802Sjkim { 681167802Sjkim ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); 682167802Sjkim return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 683167802Sjkim } 684167802Sjkim 685167802Sjkim Table = AcpiOsMapMemory (Address, Length); 686167802Sjkim if (!Table) 687167802Sjkim { 688167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 689167802Sjkim } 690167802Sjkim 691167802Sjkim /* Validate the root table checksum */ 692167802Sjkim 693167802Sjkim Status = AcpiTbVerifyChecksum (Table, Length); 694167802Sjkim if (ACPI_FAILURE (Status)) 695167802Sjkim { 696167802Sjkim AcpiOsUnmapMemory (Table, Length); 697167802Sjkim return_ACPI_STATUS (Status); 698167802Sjkim } 699167802Sjkim 700167802Sjkim /* Calculate the number of tables described in the root table */ 701167802Sjkim 702193267Sjkim TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / 703193267Sjkim TableEntrySize); 704167802Sjkim 705167802Sjkim /* 706193267Sjkim * First two entries in the table array are reserved for the DSDT 707193267Sjkim * and FACS, which are not actually present in the RSDT/XSDT - they 708193267Sjkim * come from the FADT 709167802Sjkim */ 710167802Sjkim TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); 711207344Sjkim AcpiGbl_RootTableList.CurrentTableCount = 2; 712167802Sjkim 713167802Sjkim /* 714167802Sjkim * Initialize the root table array from the RSDT/XSDT 715167802Sjkim */ 716167802Sjkim for (i = 0; i < TableCount; i++) 717167802Sjkim { 718207344Sjkim if (AcpiGbl_RootTableList.CurrentTableCount >= 719207344Sjkim AcpiGbl_RootTableList.MaxTableCount) 720151937Sjkim { 721167802Sjkim /* There is no more room in the root table array, attempt resize */ 722167802Sjkim 723167802Sjkim Status = AcpiTbResizeRootTableList (); 724167802Sjkim if (ACPI_FAILURE (Status)) 725151937Sjkim { 726167802Sjkim ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", 727193267Sjkim (unsigned) (TableCount - 728207344Sjkim (AcpiGbl_RootTableList.CurrentTableCount - 2)))); 729167802Sjkim break; 730151937Sjkim } 731167802Sjkim } 732151937Sjkim 733167802Sjkim /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ 734167802Sjkim 735207344Sjkim AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address = 736167802Sjkim AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); 737167802Sjkim 738167802Sjkim TableEntry += TableEntrySize; 739207344Sjkim AcpiGbl_RootTableList.CurrentTableCount++; 740167802Sjkim } 741167802Sjkim 742167802Sjkim /* 743167802Sjkim * It is not possible to map more than one entry in some environments, 744167802Sjkim * so unmap the root table here before mapping other tables 745167802Sjkim */ 746167802Sjkim AcpiOsUnmapMemory (Table, Length); 747167802Sjkim 748167802Sjkim /* 749167802Sjkim * Complete the initialization of the root table array by examining 750167802Sjkim * the header of each table 751167802Sjkim */ 752207344Sjkim for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 753167802Sjkim { 754167802Sjkim AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, 755193267Sjkim NULL, i); 756167802Sjkim 757167802Sjkim /* Special case for FADT - get the DSDT and FACS */ 758167802Sjkim 759167802Sjkim if (ACPI_COMPARE_NAME ( 760167802Sjkim &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) 761167802Sjkim { 762193267Sjkim AcpiTbParseFadt (i); 763151937Sjkim } 764151937Sjkim } 765151937Sjkim 766167802Sjkim return_ACPI_STATUS (AE_OK); 767151937Sjkim} 768