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