tbutils.c revision 233250
1130561Sobrien/****************************************************************************** 277298Sobrien * 3218822Sdim * Module Name: tbutils - table utilities 438889Sjdp * 533965Sjdp *****************************************************************************/ 6130561Sobrien 733965Sjdp/* 8130561Sobrien * Copyright (C) 2000 - 2012, Intel Corp. 9130561Sobrien * All rights reserved. 10130561Sobrien * 11130561Sobrien * Redistribution and use in source and binary forms, with or without 1233965Sjdp * modification, are permitted provided that the following conditions 13130561Sobrien * are met: 14130561Sobrien * 1. Redistributions of source code must retain the above copyright 15130561Sobrien * notice, this list of conditions, and the following disclaimer, 16130561Sobrien * without modification. 1733965Sjdp * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18130561Sobrien * substantially similar to the "NO WARRANTY" disclaimer below 19130561Sobrien * ("Disclaimer") and any redistribution must be conditioned upon 20218822Sdim * including a substantially similar Disclaimer requirement for further 21218822Sdim * binary redistribution. 2233965Sjdp * 3. Neither the names of the above-listed copyright holders nor the names 23130561Sobrien * of any contributors may be used to endorse or promote products derived 2433965Sjdp * from this software without specific prior written permission. 2533965Sjdp * 2633965Sjdp * Alternatively, this software may be distributed under the terms of the 2733965Sjdp * GNU General Public License ("GPL") version 2 as published by the Free 2833965Sjdp * Software Foundation. 2933965Sjdp * 3033965Sjdp * NO WARRANTY 3133965Sjdp * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3233965Sjdp * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3333965Sjdp * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3433965Sjdp * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3533965Sjdp * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3633965Sjdp * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3733965Sjdp * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3833965Sjdp * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3933965Sjdp * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4033965Sjdp * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4133965Sjdp * POSSIBILITY OF SUCH DAMAGES. 4233965Sjdp */ 4333965Sjdp 4433965Sjdp#define __TBUTILS_C__ 4533965Sjdp 4633965Sjdp#include <contrib/dev/acpica/include/acpi.h> 4733965Sjdp#include <contrib/dev/acpica/include/accommon.h> 4833965Sjdp#include <contrib/dev/acpica/include/actables.h> 4933965Sjdp 5033965Sjdp#define _COMPONENT ACPI_TABLES 5133965Sjdp ACPI_MODULE_NAME ("tbutils") 5233965Sjdp 5333965Sjdp 5433965Sjdp/* Local prototypes */ 5533965Sjdp 5633965Sjdpstatic void 5733965SjdpAcpiTbFixString ( 5833965Sjdp char *String, 5933965Sjdp ACPI_SIZE Length); 6033965Sjdp 6133965Sjdpstatic void 6233965SjdpAcpiTbCleanupTableHeader ( 6333965Sjdp ACPI_TABLE_HEADER *OutHeader, 6433965Sjdp ACPI_TABLE_HEADER *Header); 6533965Sjdp 6633965Sjdpstatic ACPI_PHYSICAL_ADDRESS 67130561SobrienAcpiTbGetRootTableEntry ( 6833965Sjdp UINT8 *TableEntry, 6933965Sjdp UINT32 TableEntrySize); 7033965Sjdp 7133965Sjdp 7233965Sjdp#if (!ACPI_REDUCED_HARDWARE) 7333965Sjdp/******************************************************************************* 7433965Sjdp * 7533965Sjdp * FUNCTION: AcpiTbInitializeFacs 7633965Sjdp * 7733965Sjdp * PARAMETERS: None 7833965Sjdp * 7933965Sjdp * RETURN: Status 8033965Sjdp * 8133965Sjdp * DESCRIPTION: Create a permanent mapping for the FADT and save it in a global 8233965Sjdp * for accessing the Global Lock and Firmware Waking Vector 8333965Sjdp * 8433965Sjdp ******************************************************************************/ 8533965Sjdp 8633965SjdpACPI_STATUS 8733965SjdpAcpiTbInitializeFacs ( 88130561Sobrien void) 8933965Sjdp{ 90130561Sobrien ACPI_STATUS Status; 9133965Sjdp 9233965Sjdp 93104834Sobrien /* If Hardware Reduced flag is set, there is no FACS */ 9489857Sobrien 9533965Sjdp if (AcpiGbl_ReducedHardware) 9633965Sjdp { 9733965Sjdp AcpiGbl_FACS = NULL; 9833965Sjdp return (AE_OK); 9938889Sjdp } 10033965Sjdp 10133965Sjdp Status = AcpiGetTableByIndex (ACPI_TABLE_INDEX_FACS, 10233965Sjdp ACPI_CAST_INDIRECT_PTR (ACPI_TABLE_HEADER, &AcpiGbl_FACS)); 10333965Sjdp return (Status); 10433965Sjdp} 10533965Sjdp#endif /* !ACPI_REDUCED_HARDWARE */ 10633965Sjdp 10760484Sobrien 10833965Sjdp/******************************************************************************* 10933965Sjdp * 11060484Sobrien * FUNCTION: AcpiTbTablesLoaded 11133965Sjdp * 11233965Sjdp * PARAMETERS: None 11333965Sjdp * 11433965Sjdp * RETURN: TRUE if required ACPI tables are loaded 11533965Sjdp * 11633965Sjdp * DESCRIPTION: Determine if the minimum required ACPI tables are present 11733965Sjdp * (FADT, FACS, DSDT) 11833965Sjdp * 11977298Sobrien ******************************************************************************/ 120130561Sobrien 121130561SobrienBOOLEAN 12260484SobrienAcpiTbTablesLoaded ( 12360484Sobrien void) 12460484Sobrien{ 12560484Sobrien 12660484Sobrien if (AcpiGbl_RootTableList.CurrentTableCount >= 3) 12777298Sobrien { 12833965Sjdp return (TRUE); 129130561Sobrien } 13077298Sobrien 131130561Sobrien return (FALSE); 132130561Sobrien} 13377298Sobrien 13477298Sobrien 13538889Sjdp/******************************************************************************* 13677298Sobrien * 13733965Sjdp * FUNCTION: AcpiTbFixString 138130561Sobrien * 13933965Sjdp * PARAMETERS: String - String to be repaired 14077298Sobrien * Length - Maximum length 14177298Sobrien * 14233965Sjdp * RETURN: None 14338889Sjdp * 14477298Sobrien * DESCRIPTION: Replace every non-printable or non-ascii byte in the string 14538889Sjdp * with a question mark '?'. 14677298Sobrien * 14777298Sobrien ******************************************************************************/ 14833965Sjdp 14933965Sjdpstatic void 15077298SobrienAcpiTbFixString ( 15177298Sobrien char *String, 152130561Sobrien ACPI_SIZE Length) 15377298Sobrien{ 15438889Sjdp 15533965Sjdp while (Length && *String) 15677298Sobrien { 15777298Sobrien if (!ACPI_IS_PRINT (*String)) 15833965Sjdp { 159130561Sobrien *String = '?'; 160130561Sobrien } 161130561Sobrien String++; 162130561Sobrien Length--; 163130561Sobrien } 164130561Sobrien} 165130561Sobrien 166130561Sobrien 167130561Sobrien/******************************************************************************* 168130561Sobrien * 16977298Sobrien * FUNCTION: AcpiTbCleanupTableHeader 17033965Sjdp * 17138889Sjdp * PARAMETERS: OutHeader - Where the cleaned header is returned 17238889Sjdp * Header - Input ACPI table header 17338889Sjdp * 17438889Sjdp * RETURN: Returns the cleaned header in OutHeader 17538889Sjdp * 17633965Sjdp * DESCRIPTION: Copy the table header and ensure that all "string" fields in 17738889Sjdp * the header consist of printable characters. 17833965Sjdp * 17960484Sobrien ******************************************************************************/ 18060484Sobrien 18160484Sobrienstatic void 18260484SobrienAcpiTbCleanupTableHeader ( 18333965Sjdp ACPI_TABLE_HEADER *OutHeader, 18460484Sobrien ACPI_TABLE_HEADER *Header) 18560484Sobrien{ 18660484Sobrien 18760484Sobrien ACPI_MEMCPY (OutHeader, Header, sizeof (ACPI_TABLE_HEADER)); 18860484Sobrien 18960484Sobrien AcpiTbFixString (OutHeader->Signature, ACPI_NAME_SIZE); 19060484Sobrien AcpiTbFixString (OutHeader->OemId, ACPI_OEM_ID_SIZE); 19160484Sobrien AcpiTbFixString (OutHeader->OemTableId, ACPI_OEM_TABLE_ID_SIZE); 19260484Sobrien AcpiTbFixString (OutHeader->AslCompilerId, ACPI_NAME_SIZE); 19360484Sobrien} 19460484Sobrien 19533965Sjdp 19677298Sobrien/******************************************************************************* 19733965Sjdp * 19838889Sjdp * FUNCTION: AcpiTbPrintTableHeader 19938889Sjdp * 20033965Sjdp * PARAMETERS: Address - Table physical address 20138889Sjdp * Header - Table header 20238889Sjdp * 20338889Sjdp * RETURN: None 20438889Sjdp * 20538889Sjdp * DESCRIPTION: Print an ACPI table header. Special cases for FACS and RSDP. 20633965Sjdp * 20777298Sobrien ******************************************************************************/ 20833965Sjdp 20933965Sjdpvoid 210130561SobrienAcpiTbPrintTableHeader ( 211130561Sobrien ACPI_PHYSICAL_ADDRESS Address, 212130561Sobrien ACPI_TABLE_HEADER *Header) 213130561Sobrien{ 214130561Sobrien ACPI_TABLE_HEADER LocalHeader; 215130561Sobrien 216130561Sobrien 217130561Sobrien /* 218130561Sobrien * The reason that the Address is cast to a void pointer is so that we 219130561Sobrien * can use %p which will work properly on both 32-bit and 64-bit hosts. 220130561Sobrien */ 22133965Sjdp if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_FACS)) 22233965Sjdp { 223130561Sobrien /* FACS only has signature and length fields */ 22433965Sjdp 22533965Sjdp ACPI_INFO ((AE_INFO, "%4.4s %p %05X", 22633965Sjdp Header->Signature, ACPI_CAST_PTR (void, Address), 22777298Sobrien Header->Length)); 22877298Sobrien } 22977298Sobrien else if (ACPI_COMPARE_NAME (Header->Signature, ACPI_SIG_RSDP)) 23077298Sobrien { 23133965Sjdp /* RSDP has no common fields */ 23233965Sjdp 23333965Sjdp ACPI_MEMCPY (LocalHeader.OemId, 23433965Sjdp ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->OemId, ACPI_OEM_ID_SIZE); 23533965Sjdp AcpiTbFixString (LocalHeader.OemId, ACPI_OEM_ID_SIZE); 236130561Sobrien 23733965Sjdp ACPI_INFO ((AE_INFO, "RSDP %p %05X (v%.2d %6.6s)", 23860484Sobrien ACPI_CAST_PTR (void, Address), 23933965Sjdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision > 0) ? 24033965Sjdp ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Length : 20, 24133965Sjdp ACPI_CAST_PTR (ACPI_TABLE_RSDP, Header)->Revision, 242130561Sobrien LocalHeader.OemId)); 24333965Sjdp } 24460484Sobrien else 24533965Sjdp { 24633965Sjdp /* Standard ACPI table with full common header */ 24733965Sjdp 248130561Sobrien AcpiTbCleanupTableHeader (&LocalHeader, Header); 24933965Sjdp 25077298Sobrien ACPI_INFO ((AE_INFO, 25133965Sjdp "%4.4s %p %05X (v%.2d %6.6s %8.8s %08X %4.4s %08X)", 25233965Sjdp LocalHeader.Signature, ACPI_CAST_PTR (void, Address), 25333965Sjdp LocalHeader.Length, LocalHeader.Revision, LocalHeader.OemId, 25433965Sjdp LocalHeader.OemTableId, LocalHeader.OemRevision, 25533965Sjdp LocalHeader.AslCompilerId, LocalHeader.AslCompilerRevision)); 25633965Sjdp } 25733965Sjdp} 25833965Sjdp 25933965Sjdp 26077298Sobrien/******************************************************************************* 261130561Sobrien * 26233965Sjdp * FUNCTION: AcpiTbValidateChecksum 26333965Sjdp * 264104834Sobrien * PARAMETERS: Table - ACPI table to verify 26538889Sjdp * Length - Length of entire table 26633965Sjdp * 26733965Sjdp * RETURN: Status 26833965Sjdp * 26933965Sjdp * DESCRIPTION: Verifies that the table checksums to zero. Optionally returns 27033965Sjdp * exception on bad checksum. 27133965Sjdp * 27233965Sjdp ******************************************************************************/ 273130561Sobrien 27433965SjdpACPI_STATUS 27533965SjdpAcpiTbVerifyChecksum ( 27633965Sjdp ACPI_TABLE_HEADER *Table, 27733965Sjdp UINT32 Length) 27833965Sjdp{ 27933965Sjdp UINT8 Checksum; 280130561Sobrien 28133965Sjdp 28233965Sjdp /* Compute the checksum on the table */ 28333965Sjdp 28433965Sjdp Checksum = AcpiTbChecksum (ACPI_CAST_PTR (UINT8, Table), Length); 28533965Sjdp 28638889Sjdp /* Checksum ok? (should be zero) */ 28733965Sjdp 28833965Sjdp if (Checksum) 28933965Sjdp { 29033965Sjdp ACPI_WARNING ((AE_INFO, 29133965Sjdp "Incorrect checksum in table [%4.4s] - 0x%2.2X, should be 0x%2.2X", 29233965Sjdp Table->Signature, Table->Checksum, 29333965Sjdp (UINT8) (Table->Checksum - Checksum))); 29438889Sjdp 29538889Sjdp#if (ACPI_CHECKSUM_ABORT) 29638889Sjdp return (AE_BAD_CHECKSUM); 29738889Sjdp#endif 29838889Sjdp } 29938889Sjdp 30038889Sjdp return (AE_OK); 30138889Sjdp} 30238889Sjdp 30338889Sjdp 30438889Sjdp/******************************************************************************* 30538889Sjdp * 30638889Sjdp * FUNCTION: AcpiTbChecksum 30738889Sjdp * 30838889Sjdp * PARAMETERS: Buffer - Pointer to memory region to be checked 30938889Sjdp * Length - Length of this memory region 31038889Sjdp * 31138889Sjdp * RETURN: Checksum (UINT8) 31233965Sjdp * 31338889Sjdp * DESCRIPTION: Calculates circular checksum of memory region. 31433965Sjdp * 31577298Sobrien ******************************************************************************/ 31677298Sobrien 31738889SjdpUINT8 31833965SjdpAcpiTbChecksum ( 31933965Sjdp UINT8 *Buffer, 32060484Sobrien UINT32 Length) 32160484Sobrien{ 32260484Sobrien UINT8 Sum = 0; 32360484Sobrien UINT8 *End = Buffer + Length; 32460484Sobrien 32560484Sobrien 32660484Sobrien while (Buffer < End) 32760484Sobrien { 32877298Sobrien Sum = (UINT8) (Sum + *(Buffer++)); 32977298Sobrien } 33077298Sobrien 33177298Sobrien return Sum; 33260484Sobrien} 33360484Sobrien 33460484Sobrien 33577298Sobrien/******************************************************************************* 33660484Sobrien * 33760484Sobrien * FUNCTION: AcpiTbCheckDsdtHeader 33860484Sobrien * 33960484Sobrien * PARAMETERS: None 34077298Sobrien * 34177298Sobrien * RETURN: None 34277298Sobrien * 34377298Sobrien * DESCRIPTION: Quick compare to check validity of the DSDT. This will detect 34460484Sobrien * if the DSDT has been replaced from outside the OS and/or if 34560484Sobrien * the DSDT header has been corrupted. 34660484Sobrien * 34760484Sobrien ******************************************************************************/ 34860484Sobrien 34960484Sobrienvoid 35060484SobrienAcpiTbCheckDsdtHeader ( 35160484Sobrien void) 35277298Sobrien{ 35377298Sobrien 35477298Sobrien /* Compare original length and checksum to current values */ 35560484Sobrien 35660484Sobrien if (AcpiGbl_OriginalDsdtHeader.Length != AcpiGbl_DSDT->Length || 35777298Sobrien AcpiGbl_OriginalDsdtHeader.Checksum != AcpiGbl_DSDT->Checksum) 35860484Sobrien { 35960484Sobrien ACPI_ERROR ((AE_INFO, 36089857Sobrien "The DSDT has been corrupted or replaced - old, new headers below")); 36177298Sobrien AcpiTbPrintTableHeader (0, &AcpiGbl_OriginalDsdtHeader); 36260484Sobrien AcpiTbPrintTableHeader (0, AcpiGbl_DSDT); 36377298Sobrien 36460484Sobrien /* Disable further error messages */ 36560484Sobrien 36677298Sobrien AcpiGbl_OriginalDsdtHeader.Length = AcpiGbl_DSDT->Length; 36760484Sobrien AcpiGbl_OriginalDsdtHeader.Checksum = AcpiGbl_DSDT->Checksum; 36860484Sobrien } 36960484Sobrien} 37060484Sobrien 37138889Sjdp 37238889Sjdp/******************************************************************************* 37338889Sjdp * 374130561Sobrien * FUNCTION: AcpiTbCopyDsdt 37538889Sjdp * 37638889Sjdp * PARAMETERS: TableDesc - Installed table to copy 37733965Sjdp * 37838889Sjdp * RETURN: None 37938889Sjdp * 38077298Sobrien * DESCRIPTION: Implements a subsystem option to copy the DSDT to local memory. 38138889Sjdp * Some very bad BIOSs are known to either corrupt the DSDT or 38238889Sjdp * install a new, bad DSDT. This copy works around the problem. 38338889Sjdp * 38460484Sobrien ******************************************************************************/ 38538889Sjdp 38660484SobrienACPI_TABLE_HEADER * 38777298SobrienAcpiTbCopyDsdt ( 38838889Sjdp UINT32 TableIndex) 38938889Sjdp{ 39038889Sjdp ACPI_TABLE_HEADER *NewTable; 39138889Sjdp ACPI_TABLE_DESC *TableDesc; 39238889Sjdp 39338889Sjdp 39438889Sjdp TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; 39538889Sjdp 39638889Sjdp NewTable = ACPI_ALLOCATE (TableDesc->Length); 39738889Sjdp if (!NewTable) 39838889Sjdp { 39977298Sobrien ACPI_ERROR ((AE_INFO, "Could not copy DSDT of length 0x%X", 40038889Sjdp TableDesc->Length)); 40138889Sjdp return (NULL); 40238889Sjdp } 40338889Sjdp 40438889Sjdp ACPI_MEMCPY (NewTable, TableDesc->Pointer, TableDesc->Length); 40538889Sjdp AcpiTbDeleteTable (TableDesc); 40638889Sjdp TableDesc->Pointer = NewTable; 40738889Sjdp TableDesc->Flags = ACPI_TABLE_ORIGIN_ALLOCATED; 40838889Sjdp 40938889Sjdp ACPI_INFO ((AE_INFO, 41038889Sjdp "Forced DSDT copy: length 0x%05X copied locally, original unmapped", 41138889Sjdp NewTable->Length)); 41238889Sjdp 41338889Sjdp return (NewTable); 41438889Sjdp} 41533965Sjdp 41633965Sjdp 41733965Sjdp/******************************************************************************* 41833965Sjdp * 41933965Sjdp * FUNCTION: AcpiTbInstallTable 42033965Sjdp * 42133965Sjdp * PARAMETERS: Address - Physical address of DSDT or FACS 42233965Sjdp * Signature - Table signature, NULL if no need to 42333965Sjdp * match 424130561Sobrien * TableIndex - Index into root table array 42533965Sjdp * 42633965Sjdp * RETURN: None 42733965Sjdp * 42833965Sjdp * DESCRIPTION: Install an ACPI table into the global data structure. The 42933965Sjdp * table override mechanism is called to allow the host 43033965Sjdp * OS to replace any table before it is installed in the root 43133965Sjdp * table array. 43233965Sjdp * 43333965Sjdp ******************************************************************************/ 43433965Sjdp 43533965Sjdpvoid 43633965SjdpAcpiTbInstallTable ( 43733965Sjdp ACPI_PHYSICAL_ADDRESS Address, 43833965Sjdp char *Signature, 43933965Sjdp UINT32 TableIndex) 44033965Sjdp{ 44133965Sjdp ACPI_TABLE_HEADER *Table; 44233965Sjdp ACPI_TABLE_HEADER *FinalTable; 44333965Sjdp ACPI_TABLE_DESC *TableDesc; 44433965Sjdp 44533965Sjdp 44677298Sobrien if (!Address) 44777298Sobrien { 44877298Sobrien ACPI_ERROR ((AE_INFO, "Null physical address for ACPI table [%s]", 44933965Sjdp Signature)); 45033965Sjdp return; 451130561Sobrien } 45233965Sjdp 45333965Sjdp /* Map just the table header */ 45433965Sjdp 45533965Sjdp Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 45633965Sjdp if (!Table) 45733965Sjdp { 45877298Sobrien ACPI_ERROR ((AE_INFO, "Could not map memory for table [%s] at %p", 45938889Sjdp Signature, ACPI_CAST_PTR (void, Address))); 46038889Sjdp return; 46138889Sjdp } 46238889Sjdp 46338889Sjdp /* Skip SSDT when DSDT is overriden */ 46433965Sjdp 46538889Sjdp if (ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT) && 46638889Sjdp (AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags & 46738889Sjdp ACPI_TABLE_ORIGIN_OVERRIDE)) 46838889Sjdp { 46938889Sjdp ACPI_INFO ((AE_INFO, 47038889Sjdp "%4.4s @ 0x%p Table override, replaced with:", ACPI_SIG_SSDT, 47138889Sjdp ACPI_CAST_PTR (void, Address))); 47289857Sobrien AcpiTbPrintTableHeader ( 47338889Sjdp AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Address, 47438889Sjdp AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer); 47538889Sjdp goto UnmapAndExit; 47638889Sjdp } 47738889Sjdp 47877298Sobrien /* If a particular signature is expected (DSDT/FACS), it must match */ 47938889Sjdp 48038889Sjdp if (Signature && 48177298Sobrien !ACPI_COMPARE_NAME (Table->Signature, Signature)) 48233965Sjdp { 48333965Sjdp ACPI_ERROR ((AE_INFO, 48438889Sjdp "Invalid signature 0x%X for ACPI table, expected [%s]", 48533965Sjdp *ACPI_CAST_PTR (UINT32, Table->Signature), Signature)); 48677298Sobrien goto UnmapAndExit; 48777298Sobrien } 48833965Sjdp 48933965Sjdp /* 49033965Sjdp * Initialize the table entry. Set the pointer to NULL, since the 49133965Sjdp * table is not fully mapped at this time. 49233965Sjdp */ 49333965Sjdp TableDesc = &AcpiGbl_RootTableList.Tables[TableIndex]; 49433965Sjdp 49538889Sjdp TableDesc->Address = Address; 49633965Sjdp TableDesc->Pointer = NULL; 49733965Sjdp TableDesc->Length = Table->Length; 49833965Sjdp TableDesc->Flags = ACPI_TABLE_ORIGIN_MAPPED; 49933965Sjdp ACPI_MOVE_32_TO_32 (TableDesc->Signature.Ascii, Table->Signature); 50033965Sjdp 50189857Sobrien /* 50289857Sobrien * ACPI Table Override: 50389857Sobrien * 50489857Sobrien * Before we install the table, let the host OS override it with a new 50589857Sobrien * one if desired. Any table within the RSDT/XSDT can be replaced, 50689857Sobrien * including the DSDT which is pointed to by the FADT. 50733965Sjdp * 50833965Sjdp * NOTE: If the table is overridden, then FinalTable will contain a 50933965Sjdp * mapped pointer to the full new table. If the table is not overridden, 51033965Sjdp * or if there has been a physical override, then the table will be 51133965Sjdp * fully mapped later (in verify table). In any case, we must 51233965Sjdp * unmap the header that was mapped above. 51333965Sjdp */ 51433965Sjdp FinalTable = AcpiTbTableOverride (Table, TableDesc); 51533965Sjdp if (!FinalTable) 51633965Sjdp { 51777298Sobrien FinalTable = Table; /* There was no override */ 51877298Sobrien } 51977298Sobrien 52033965Sjdp AcpiTbPrintTableHeader (TableDesc->Address, FinalTable); 52133965Sjdp 522130561Sobrien /* Set the global integer width (based upon revision of the DSDT) */ 52333965Sjdp 52433965Sjdp if (TableIndex == ACPI_TABLE_INDEX_DSDT) 52577298Sobrien { 52677298Sobrien AcpiUtSetIntegerWidth (FinalTable->Revision); 52777298Sobrien } 52833965Sjdp 52933965Sjdp /* 53033965Sjdp * If we have a physical override during this early loading of the ACPI 53133965Sjdp * tables, unmap the table for now. It will be mapped again later when 53233965Sjdp * it is actually used. This supports very early loading of ACPI tables, 53333965Sjdp * before virtual memory is fully initialized and running within the 53433965Sjdp * host OS. Note: A logical override has the ACPI_TABLE_ORIGIN_OVERRIDE 53533965Sjdp * flag set and will not be deleted below. 53633965Sjdp */ 53733965Sjdp if (FinalTable != Table) 53833965Sjdp { 53933965Sjdp AcpiTbDeleteTable (TableDesc); 54033965Sjdp } 54133965Sjdp 54233965Sjdp 54333965SjdpUnmapAndExit: 54433965Sjdp 54533965Sjdp /* Always unmap the table header that we mapped above */ 54633965Sjdp 54733965Sjdp AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 54833965Sjdp} 54933965Sjdp 55033965Sjdp 55133965Sjdp/******************************************************************************* 55233965Sjdp * 55333965Sjdp * FUNCTION: AcpiTbGetRootTableEntry 55433965Sjdp * 55533965Sjdp * PARAMETERS: TableEntry - Pointer to the RSDT/XSDT table entry 55633965Sjdp * TableEntrySize - sizeof 32 or 64 (RSDT or XSDT) 55733965Sjdp * 55833965Sjdp * RETURN: Physical address extracted from the root table 55933965Sjdp * 56033965Sjdp * DESCRIPTION: Get one root table entry. Handles 32-bit and 64-bit cases on 56133965Sjdp * both 32-bit and 64-bit platforms 56233965Sjdp * 56333965Sjdp * NOTE: ACPI_PHYSICAL_ADDRESS is 32-bit on 32-bit platforms, 64-bit on 56433965Sjdp * 64-bit platforms. 565130561Sobrien * 56633965Sjdp ******************************************************************************/ 56738889Sjdp 56833965Sjdpstatic ACPI_PHYSICAL_ADDRESS 56977298SobrienAcpiTbGetRootTableEntry ( 57033965Sjdp UINT8 *TableEntry, 57133965Sjdp UINT32 TableEntrySize) 57260484Sobrien{ 57333965Sjdp UINT64 Address64; 57477298Sobrien 57533965Sjdp 57633965Sjdp /* 57733965Sjdp * Get the table physical address (32-bit for RSDT, 64-bit for XSDT): 57833965Sjdp * Note: Addresses are 32-bit aligned (not 64) in both RSDT and XSDT 57933965Sjdp */ 58033965Sjdp if (TableEntrySize == sizeof (UINT32)) 58133965Sjdp { 58233965Sjdp /* 58377298Sobrien * 32-bit platform, RSDT: Return 32-bit table entry 58433965Sjdp * 64-bit platform, RSDT: Expand 32-bit to 64-bit and return 58533965Sjdp */ 58677298Sobrien return ((ACPI_PHYSICAL_ADDRESS) (*ACPI_CAST_PTR (UINT32, TableEntry))); 58760484Sobrien } 58860484Sobrien else 58938889Sjdp { 59033965Sjdp /* 59177298Sobrien * 32-bit platform, XSDT: Truncate 64-bit to 32-bit and return 592130561Sobrien * 64-bit platform, XSDT: Move (unaligned) 64-bit to local, 59333965Sjdp * return 64-bit 59433965Sjdp */ 59533965Sjdp ACPI_MOVE_64_TO_64 (&Address64, TableEntry); 59660484Sobrien 59733965Sjdp#if ACPI_MACHINE_WIDTH == 32 59860484Sobrien if (Address64 > ACPI_UINT32_MAX) 59933965Sjdp { 600104834Sobrien /* Will truncate 64-bit address to 32 bits, issue warning */ 601104834Sobrien 602104834Sobrien ACPI_WARNING ((AE_INFO, 603104834Sobrien "64-bit Physical Address in XSDT is too large (0x%8.8X%8.8X)," 60433965Sjdp " truncating", 605104834Sobrien ACPI_FORMAT_UINT64 (Address64))); 606104834Sobrien } 607104834Sobrien#endif 608104834Sobrien return ((ACPI_PHYSICAL_ADDRESS) (Address64)); 609104834Sobrien } 610104834Sobrien} 611130561Sobrien 612130561Sobrien 613104834Sobrien/******************************************************************************* 614104834Sobrien * 615104834Sobrien * FUNCTION: AcpiTbParseRootTable 616104834Sobrien * 61733965Sjdp * PARAMETERS: Rsdp - Pointer to the RSDP 618104834Sobrien * 619104834Sobrien * RETURN: Status 62033965Sjdp * 621104834Sobrien * DESCRIPTION: This function is called to parse the Root System Description 622104834Sobrien * Table (RSDT or XSDT) 623104834Sobrien * 624104834Sobrien * NOTE: Tables are mapped (not copied) for efficiency. The FACS must 62533965Sjdp * be mapped and cannot be copied because it contains the actual 62633965Sjdp * memory location of the ACPI Global Lock. 62733965Sjdp * 62838889Sjdp ******************************************************************************/ 62933965Sjdp 63033965SjdpACPI_STATUS 63133965SjdpAcpiTbParseRootTable ( 63233965Sjdp ACPI_PHYSICAL_ADDRESS RsdpAddress) 633130561Sobrien{ 634130561Sobrien ACPI_TABLE_RSDP *Rsdp; 63533965Sjdp UINT32 TableEntrySize; 63633965Sjdp UINT32 i; 63733965Sjdp UINT32 TableCount; 63833965Sjdp ACPI_TABLE_HEADER *Table; 63960484Sobrien ACPI_PHYSICAL_ADDRESS Address; 64033965Sjdp UINT32 Length; 64160484Sobrien UINT8 *TableEntry; 64233965Sjdp ACPI_STATUS Status; 64377298Sobrien 64433965Sjdp 64538889Sjdp ACPI_FUNCTION_TRACE (TbParseRootTable); 64677298Sobrien 64777298Sobrien 64877298Sobrien /* 64933965Sjdp * Map the entire RSDP and extract the address of the RSDT or XSDT 65033965Sjdp */ 65133965Sjdp Rsdp = AcpiOsMapMemory (RsdpAddress, sizeof (ACPI_TABLE_RSDP)); 65233965Sjdp if (!Rsdp) 65333965Sjdp { 65433965Sjdp return_ACPI_STATUS (AE_NO_MEMORY); 65577298Sobrien } 65677298Sobrien 65777298Sobrien AcpiTbPrintTableHeader (RsdpAddress, 65833965Sjdp ACPI_CAST_PTR (ACPI_TABLE_HEADER, Rsdp)); 65933965Sjdp 66060484Sobrien /* Differentiate between RSDT and XSDT root tables */ 66133965Sjdp 66260484Sobrien if (Rsdp->Revision > 1 && Rsdp->XsdtPhysicalAddress) 66360484Sobrien { 66460484Sobrien /* 66533965Sjdp * Root table is an XSDT (64-bit physical addresses). We must use the 66660484Sobrien * XSDT if the revision is > 1 and the XSDT pointer is present, as per 66760484Sobrien * the ACPI specification. 66877298Sobrien */ 66960484Sobrien Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->XsdtPhysicalAddress; 67060484Sobrien TableEntrySize = sizeof (UINT64); 67160484Sobrien } 67233965Sjdp else 67360484Sobrien { 67460484Sobrien /* Root table is an RSDT (32-bit physical addresses) */ 67577298Sobrien 67660484Sobrien Address = (ACPI_PHYSICAL_ADDRESS) Rsdp->RsdtPhysicalAddress; 67760484Sobrien TableEntrySize = sizeof (UINT32); 67877298Sobrien } 67960484Sobrien 68033965Sjdp /* 68160484Sobrien * It is not possible to map more than one entry in some environments, 68260484Sobrien * so unmap the RSDP here before mapping other tables 68360484Sobrien */ 68433965Sjdp AcpiOsUnmapMemory (Rsdp, sizeof (ACPI_TABLE_RSDP)); 68577298Sobrien 68660484Sobrien 68760484Sobrien /* Map the RSDT/XSDT table header to get the full table length */ 68877298Sobrien 68960484Sobrien Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER)); 69060484Sobrien if (!Table) 69177298Sobrien { 69260484Sobrien return_ACPI_STATUS (AE_NO_MEMORY); 69360484Sobrien } 69460484Sobrien 69577298Sobrien AcpiTbPrintTableHeader (Address, Table); 69660484Sobrien 69760484Sobrien /* Get the length of the full table, verify length and map entire table */ 69860484Sobrien 69960484Sobrien Length = Table->Length; 70060484Sobrien AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER)); 70160484Sobrien 70277298Sobrien if (Length < sizeof (ACPI_TABLE_HEADER)) 70360484Sobrien { 70460484Sobrien ACPI_ERROR ((AE_INFO, "Invalid length 0x%X in RSDT/XSDT", Length)); 70560484Sobrien return_ACPI_STATUS (AE_INVALID_TABLE_LENGTH); 70677298Sobrien } 70760484Sobrien 70877298Sobrien Table = AcpiOsMapMemory (Address, Length); 70933965Sjdp if (!Table) 71077298Sobrien { 71177298Sobrien return_ACPI_STATUS (AE_NO_MEMORY); 71260484Sobrien } 71377298Sobrien 71460484Sobrien /* Validate the root table checksum */ 71533965Sjdp 71677298Sobrien Status = AcpiTbVerifyChecksum (Table, Length); 71777298Sobrien if (ACPI_FAILURE (Status)) 71877298Sobrien { 71960484Sobrien AcpiOsUnmapMemory (Table, Length); 72060484Sobrien return_ACPI_STATUS (Status); 72160484Sobrien } 72277298Sobrien 72360484Sobrien /* Calculate the number of tables described in the root table */ 72433965Sjdp 72533965Sjdp TableCount = (UINT32) ((Table->Length - sizeof (ACPI_TABLE_HEADER)) / 72633965Sjdp TableEntrySize); 72760484Sobrien 72833965Sjdp /* 72933965Sjdp * First two entries in the table array are reserved for the DSDT 73077298Sobrien * and FACS, which are not actually present in the RSDT/XSDT - they 73160484Sobrien * come from the FADT 73277298Sobrien */ 73333965Sjdp TableEntry = ACPI_CAST_PTR (UINT8, Table) + sizeof (ACPI_TABLE_HEADER); 73433965Sjdp AcpiGbl_RootTableList.CurrentTableCount = 2; 73533965Sjdp 73633965Sjdp /* 73733965Sjdp * Initialize the root table array from the RSDT/XSDT 738130561Sobrien */ 73933965Sjdp for (i = 0; i < TableCount; i++) 74033965Sjdp { 74133965Sjdp if (AcpiGbl_RootTableList.CurrentTableCount >= 74233965Sjdp AcpiGbl_RootTableList.MaxTableCount) 74333965Sjdp { 74433965Sjdp /* There is no more room in the root table array, attempt resize */ 74533965Sjdp 74633965Sjdp Status = AcpiTbResizeRootTableList (); 74733965Sjdp if (ACPI_FAILURE (Status)) 74833965Sjdp { 74938889Sjdp ACPI_WARNING ((AE_INFO, "Truncating %u table entries!", 75038889Sjdp (unsigned) (TableCount - 75133965Sjdp (AcpiGbl_RootTableList.CurrentTableCount - 2)))); 75238889Sjdp break; 75360484Sobrien } 75438889Sjdp } 755218822Sdim 75633965Sjdp /* Get the table physical address (32-bit for RSDT, 64-bit for XSDT) */ 75733965Sjdp 75833965Sjdp AcpiGbl_RootTableList.Tables[AcpiGbl_RootTableList.CurrentTableCount].Address = 75933965Sjdp AcpiTbGetRootTableEntry (TableEntry, TableEntrySize); 76033965Sjdp 76133965Sjdp TableEntry += TableEntrySize; 76233965Sjdp AcpiGbl_RootTableList.CurrentTableCount++; 76333965Sjdp } 76433965Sjdp 76533965Sjdp /* 76633965Sjdp * It is not possible to map more than one entry in some environments, 76733965Sjdp * so unmap the root table here before mapping other tables 76833965Sjdp */ 76933965Sjdp AcpiOsUnmapMemory (Table, Length); 77033965Sjdp 77133965Sjdp /* 77233965Sjdp * Complete the initialization of the root table array by examining 77333965Sjdp * the header of each table 77433965Sjdp */ 77533965Sjdp for (i = 2; i < AcpiGbl_RootTableList.CurrentTableCount; i++) 77633965Sjdp { 77733965Sjdp AcpiTbInstallTable (AcpiGbl_RootTableList.Tables[i].Address, 77833965Sjdp NULL, i); 77933965Sjdp 78033965Sjdp /* Special case for FADT - get the DSDT and FACS */ 78133965Sjdp 78233965Sjdp if (ACPI_COMPARE_NAME ( 78333965Sjdp &AcpiGbl_RootTableList.Tables[i].Signature, ACPI_SIG_FADT)) 78433965Sjdp { 78560484Sobrien AcpiTbParseFadt (i); 78638889Sjdp } 78738889Sjdp } 78860484Sobrien 78960484Sobrien return_ACPI_STATUS (AE_OK); 79038889Sjdp} 79138889Sjdp