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