1ae115bc7Smrj /****************************************************************************** 2ae115bc7Smrj * 3ae115bc7Smrj * Module Name: tbxfroot - Find the root ACPI table (RSDT) 4ae115bc7Smrj * 5ae115bc7Smrj *****************************************************************************/ 6ae115bc7Smrj 726f3cdf0SGordon Ross /* 8*385cc6b4SJerry Jelinek * Copyright (C) 2000 - 2016, Intel Corp. 9ae115bc7Smrj * All rights reserved. 10ae115bc7Smrj * 1126f3cdf0SGordon Ross * Redistribution and use in source and binary forms, with or without 1226f3cdf0SGordon Ross * modification, are permitted provided that the following conditions 1326f3cdf0SGordon Ross * are met: 1426f3cdf0SGordon Ross * 1. Redistributions of source code must retain the above copyright 1526f3cdf0SGordon Ross * notice, this list of conditions, and the following disclaimer, 1626f3cdf0SGordon Ross * without modification. 1726f3cdf0SGordon Ross * 2. Redistributions in binary form must reproduce at minimum a disclaimer 1826f3cdf0SGordon Ross * substantially similar to the "NO WARRANTY" disclaimer below 1926f3cdf0SGordon Ross * ("Disclaimer") and any redistribution must be conditioned upon 2026f3cdf0SGordon Ross * including a substantially similar Disclaimer requirement for further 2126f3cdf0SGordon Ross * binary redistribution. 2226f3cdf0SGordon Ross * 3. Neither the names of the above-listed copyright holders nor the names 2326f3cdf0SGordon Ross * of any contributors may be used to endorse or promote products derived 2426f3cdf0SGordon Ross * from this software without specific prior written permission. 25ae115bc7Smrj * 2626f3cdf0SGordon Ross * Alternatively, this software may be distributed under the terms of the 2726f3cdf0SGordon Ross * GNU General Public License ("GPL") version 2 as published by the Free 2826f3cdf0SGordon Ross * Software Foundation. 29ae115bc7Smrj * 3026f3cdf0SGordon Ross * NO WARRANTY 3126f3cdf0SGordon Ross * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 3226f3cdf0SGordon Ross * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 3326f3cdf0SGordon Ross * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 3426f3cdf0SGordon Ross * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 3526f3cdf0SGordon Ross * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 3626f3cdf0SGordon Ross * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 3726f3cdf0SGordon Ross * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 3826f3cdf0SGordon Ross * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 3926f3cdf0SGordon Ross * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 4026f3cdf0SGordon Ross * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 4126f3cdf0SGordon Ross * POSSIBILITY OF SUCH DAMAGES. 4226f3cdf0SGordon Ross */ 43ae115bc7Smrj 44ae115bc7Smrj #include "acpi.h" 45aa2aa9a6SDana Myers #include "accommon.h" 46ae115bc7Smrj #include "actables.h" 47ae115bc7Smrj 48ae115bc7Smrj 49ae115bc7Smrj #define _COMPONENT ACPI_TABLES 50ae115bc7Smrj ACPI_MODULE_NAME ("tbxfroot") 51ae115bc7Smrj 52ae115bc7Smrj 53*385cc6b4SJerry Jelinek /******************************************************************************* 54*385cc6b4SJerry Jelinek * 55*385cc6b4SJerry Jelinek * FUNCTION: AcpiTbGetRsdpLength 56*385cc6b4SJerry Jelinek * 57*385cc6b4SJerry Jelinek * PARAMETERS: Rsdp - Pointer to RSDP 58*385cc6b4SJerry Jelinek * 59*385cc6b4SJerry Jelinek * RETURN: Table length 60*385cc6b4SJerry Jelinek * 61*385cc6b4SJerry Jelinek * DESCRIPTION: Get the length of the RSDP 62*385cc6b4SJerry Jelinek * 63*385cc6b4SJerry Jelinek ******************************************************************************/ 64ae115bc7Smrj 65*385cc6b4SJerry Jelinek UINT32 66*385cc6b4SJerry Jelinek AcpiTbGetRsdpLength ( 67*385cc6b4SJerry Jelinek ACPI_TABLE_RSDP *Rsdp) 68*385cc6b4SJerry Jelinek { 69*385cc6b4SJerry Jelinek 70*385cc6b4SJerry Jelinek if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) 71*385cc6b4SJerry Jelinek { 72*385cc6b4SJerry Jelinek /* BAD Signature */ 73*385cc6b4SJerry Jelinek 74*385cc6b4SJerry Jelinek return (0); 75*385cc6b4SJerry Jelinek } 76*385cc6b4SJerry Jelinek 77*385cc6b4SJerry Jelinek /* "Length" field is available if table version >= 2 */ 78*385cc6b4SJerry Jelinek 79*385cc6b4SJerry Jelinek if (Rsdp->Revision >= 2) 80*385cc6b4SJerry Jelinek { 81*385cc6b4SJerry Jelinek return (Rsdp->Length); 82*385cc6b4SJerry Jelinek } 83*385cc6b4SJerry Jelinek else 84*385cc6b4SJerry Jelinek { 85*385cc6b4SJerry Jelinek return (ACPI_RSDP_CHECKSUM_LENGTH); 86*385cc6b4SJerry Jelinek } 87*385cc6b4SJerry Jelinek } 88db2bae30SDana Myers 89ae115bc7Smrj 90ae115bc7Smrj /******************************************************************************* 91ae115bc7Smrj * 92ae115bc7Smrj * FUNCTION: AcpiTbValidateRsdp 93ae115bc7Smrj * 94ae115bc7Smrj * PARAMETERS: Rsdp - Pointer to unvalidated RSDP 95ae115bc7Smrj * 96ae115bc7Smrj * RETURN: Status 97ae115bc7Smrj * 98ae115bc7Smrj * DESCRIPTION: Validate the RSDP (ptr) 99ae115bc7Smrj * 100ae115bc7Smrj ******************************************************************************/ 101ae115bc7Smrj 102*385cc6b4SJerry Jelinek ACPI_STATUS 103ae115bc7Smrj AcpiTbValidateRsdp ( 104db2bae30SDana Myers ACPI_TABLE_RSDP *Rsdp) 105ae115bc7Smrj { 106ae115bc7Smrj 107ae115bc7Smrj /* 108ae115bc7Smrj * The signature and checksum must both be correct 109db2bae30SDana Myers * 110db2bae30SDana Myers * Note: Sometimes there exists more than one RSDP in memory; the valid 111db2bae30SDana Myers * RSDP has a valid checksum, all others have an invalid checksum. 112ae115bc7Smrj */ 113*385cc6b4SJerry Jelinek if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) 114ae115bc7Smrj { 115ae115bc7Smrj /* Nope, BAD Signature */ 116ae115bc7Smrj 117ae115bc7Smrj return (AE_BAD_SIGNATURE); 118ae115bc7Smrj } 119ae115bc7Smrj 120ae115bc7Smrj /* Check the standard checksum */ 121ae115bc7Smrj 122db2bae30SDana Myers if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) 123ae115bc7Smrj { 124ae115bc7Smrj return (AE_BAD_CHECKSUM); 125ae115bc7Smrj } 126ae115bc7Smrj 127ae115bc7Smrj /* Check extended checksum if table version >= 2 */ 128ae115bc7Smrj 129ae115bc7Smrj if ((Rsdp->Revision >= 2) && 130db2bae30SDana Myers (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) 131ae115bc7Smrj { 132ae115bc7Smrj return (AE_BAD_CHECKSUM); 133ae115bc7Smrj } 134ae115bc7Smrj 135ae115bc7Smrj return (AE_OK); 136ae115bc7Smrj } 137ae115bc7Smrj 138ae115bc7Smrj 139ae115bc7Smrj /******************************************************************************* 140ae115bc7Smrj * 141aa2aa9a6SDana Myers * FUNCTION: AcpiFindRootPointer 142ae115bc7Smrj * 143db2bae30SDana Myers * PARAMETERS: TableAddress - Where the table pointer is returned 144ae115bc7Smrj * 145db2bae30SDana Myers * RETURN: Status, RSDP physical address 146ae115bc7Smrj * 147db2bae30SDana Myers * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 148db2bae30SDana Myers * pointer structure. If it is found, set *RSDP to point to it. 149ae115bc7Smrj * 150db2bae30SDana Myers * NOTE1: The RSDP must be either in the first 1K of the Extended 151db2bae30SDana Myers * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 152db2bae30SDana Myers * Only a 32-bit physical address is necessary. 153ae115bc7Smrj * 154db2bae30SDana Myers * NOTE2: This function is always available, regardless of the 155db2bae30SDana Myers * initialization state of the rest of ACPI. 156ae115bc7Smrj * 157ae115bc7Smrj ******************************************************************************/ 158ae115bc7Smrj 159ae115bc7Smrj ACPI_STATUS 160ae115bc7Smrj AcpiFindRootPointer ( 161*385cc6b4SJerry Jelinek ACPI_PHYSICAL_ADDRESS *TableAddress) 162ae115bc7Smrj { 163db2bae30SDana Myers UINT8 *TablePtr; 164db2bae30SDana Myers UINT8 *MemRover; 165db2bae30SDana Myers UINT32 PhysicalAddress; 166ae115bc7Smrj 167ae115bc7Smrj 168ae115bc7Smrj ACPI_FUNCTION_TRACE (AcpiFindRootPointer); 169ae115bc7Smrj 170ae115bc7Smrj 171db2bae30SDana Myers /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 172ae115bc7Smrj 173db2bae30SDana Myers TablePtr = AcpiOsMapMemory ( 174db2bae30SDana Myers (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, 175db2bae30SDana Myers ACPI_EBDA_PTR_LENGTH); 176db2bae30SDana Myers if (!TablePtr) 177ae115bc7Smrj { 178db2bae30SDana Myers ACPI_ERROR ((AE_INFO, 17926f3cdf0SGordon Ross "Could not map memory at 0x%8.8X for length %u", 180db2bae30SDana Myers ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 181ae115bc7Smrj 182db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 183ae115bc7Smrj } 184ae115bc7Smrj 185db2bae30SDana Myers ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); 186db2bae30SDana Myers 187db2bae30SDana Myers /* Convert segment part to physical address */ 188db2bae30SDana Myers 189db2bae30SDana Myers PhysicalAddress <<= 4; 190db2bae30SDana Myers AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); 191db2bae30SDana Myers 192db2bae30SDana Myers /* EBDA present? */ 193db2bae30SDana Myers 194db2bae30SDana Myers if (PhysicalAddress > 0x400) 195db2bae30SDana Myers { 196db2bae30SDana Myers /* 197db2bae30SDana Myers * 1b) Search EBDA paragraphs (EBDA is required to be a 198db2bae30SDana Myers * minimum of 1K length) 199db2bae30SDana Myers */ 200db2bae30SDana Myers TablePtr = AcpiOsMapMemory ( 201db2bae30SDana Myers (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, 202db2bae30SDana Myers ACPI_EBDA_WINDOW_SIZE); 203db2bae30SDana Myers if (!TablePtr) 204db2bae30SDana Myers { 205db2bae30SDana Myers ACPI_ERROR ((AE_INFO, 20626f3cdf0SGordon Ross "Could not map memory at 0x%8.8X for length %u", 207db2bae30SDana Myers PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); 208db2bae30SDana Myers 209db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 210db2bae30SDana Myers } 211db2bae30SDana Myers 212*385cc6b4SJerry Jelinek MemRover = AcpiTbScanMemoryForRsdp ( 213*385cc6b4SJerry Jelinek TablePtr, ACPI_EBDA_WINDOW_SIZE); 214db2bae30SDana Myers AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); 215db2bae30SDana Myers 216db2bae30SDana Myers if (MemRover) 217db2bae30SDana Myers { 218db2bae30SDana Myers /* Return the physical address */ 219db2bae30SDana Myers 220*385cc6b4SJerry Jelinek PhysicalAddress += 221*385cc6b4SJerry Jelinek (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); 222db2bae30SDana Myers 223*385cc6b4SJerry Jelinek *TableAddress = (ACPI_PHYSICAL_ADDRESS) PhysicalAddress; 224ae115bc7Smrj return_ACPI_STATUS (AE_OK); 225ae115bc7Smrj } 226db2bae30SDana Myers } 227db2bae30SDana Myers 228db2bae30SDana Myers /* 229db2bae30SDana Myers * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 230db2bae30SDana Myers */ 231db2bae30SDana Myers TablePtr = AcpiOsMapMemory ( 232db2bae30SDana Myers (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, 233db2bae30SDana Myers ACPI_HI_RSDP_WINDOW_SIZE); 234db2bae30SDana Myers 235db2bae30SDana Myers if (!TablePtr) 236db2bae30SDana Myers { 237db2bae30SDana Myers ACPI_ERROR ((AE_INFO, 23826f3cdf0SGordon Ross "Could not map memory at 0x%8.8X for length %u", 239db2bae30SDana Myers ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); 240db2bae30SDana Myers 241db2bae30SDana Myers return_ACPI_STATUS (AE_NO_MEMORY); 242db2bae30SDana Myers } 243db2bae30SDana Myers 244*385cc6b4SJerry Jelinek MemRover = AcpiTbScanMemoryForRsdp ( 245*385cc6b4SJerry Jelinek TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 246db2bae30SDana Myers AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 247db2bae30SDana Myers 248db2bae30SDana Myers if (MemRover) 249db2bae30SDana Myers { 250db2bae30SDana Myers /* Return the physical address */ 251db2bae30SDana Myers 252db2bae30SDana Myers PhysicalAddress = (UINT32) 253db2bae30SDana Myers (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); 254db2bae30SDana Myers 255*385cc6b4SJerry Jelinek *TableAddress = (ACPI_PHYSICAL_ADDRESS) PhysicalAddress; 256db2bae30SDana Myers return_ACPI_STATUS (AE_OK); 257db2bae30SDana Myers } 258db2bae30SDana Myers 259db2bae30SDana Myers /* A valid RSDP was not found */ 260db2bae30SDana Myers 261*385cc6b4SJerry Jelinek ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); 262db2bae30SDana Myers return_ACPI_STATUS (AE_NOT_FOUND); 263db2bae30SDana Myers } 264ae115bc7Smrj 265ae115bc7Smrj ACPI_EXPORT_SYMBOL (AcpiFindRootPointer) 266ae115bc7Smrj 267ae115bc7Smrj 268ae115bc7Smrj /******************************************************************************* 269ae115bc7Smrj * 270ae115bc7Smrj * FUNCTION: AcpiTbScanMemoryForRsdp 271ae115bc7Smrj * 272ae115bc7Smrj * PARAMETERS: StartAddress - Starting pointer for search 273ae115bc7Smrj * Length - Maximum length to search 274ae115bc7Smrj * 275ae115bc7Smrj * RETURN: Pointer to the RSDP if found, otherwise NULL. 276ae115bc7Smrj * 277ae115bc7Smrj * DESCRIPTION: Search a block of memory for the RSDP signature 278ae115bc7Smrj * 279ae115bc7Smrj ******************************************************************************/ 280ae115bc7Smrj 281*385cc6b4SJerry Jelinek UINT8 * 282ae115bc7Smrj AcpiTbScanMemoryForRsdp ( 283ae115bc7Smrj UINT8 *StartAddress, 284ae115bc7Smrj UINT32 Length) 285ae115bc7Smrj { 286ae115bc7Smrj ACPI_STATUS Status; 287ae115bc7Smrj UINT8 *MemRover; 288ae115bc7Smrj UINT8 *EndAddress; 289ae115bc7Smrj 290ae115bc7Smrj 291ae115bc7Smrj ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); 292ae115bc7Smrj 293ae115bc7Smrj 294ae115bc7Smrj EndAddress = StartAddress + Length; 295ae115bc7Smrj 296ae115bc7Smrj /* Search from given start address for the requested length */ 297ae115bc7Smrj 298ae115bc7Smrj for (MemRover = StartAddress; MemRover < EndAddress; 299ae115bc7Smrj MemRover += ACPI_RSDP_SCAN_STEP) 300ae115bc7Smrj { 301ae115bc7Smrj /* The RSDP signature and checksum must both be correct */ 302ae115bc7Smrj 303*385cc6b4SJerry Jelinek Status = AcpiTbValidateRsdp ( 304*385cc6b4SJerry Jelinek ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); 305ae115bc7Smrj if (ACPI_SUCCESS (Status)) 306ae115bc7Smrj { 307ae115bc7Smrj /* Sig and checksum valid, we have found a real RSDP */ 308ae115bc7Smrj 309ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 310ae115bc7Smrj "RSDP located at physical address %p\n", MemRover)); 311ae115bc7Smrj return_PTR (MemRover); 312ae115bc7Smrj } 313ae115bc7Smrj 314ae115bc7Smrj /* No sig match or bad checksum, keep searching */ 315ae115bc7Smrj } 316ae115bc7Smrj 317ae115bc7Smrj /* Searched entire block, no RSDP was found */ 318ae115bc7Smrj 319ae115bc7Smrj ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 320ae115bc7Smrj "Searched entire block from %p, valid RSDP was not found\n", 321ae115bc7Smrj StartAddress)); 322ae115bc7Smrj return_PTR (NULL); 323ae115bc7Smrj } 324