1 /****************************************************************************** 2 * 3 * Module Name: tbxfroot - Find the root ACPI table (RSDT) 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2015, 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 #include <contrib/dev/acpica/include/acpi.h> 45 #include <contrib/dev/acpica/include/accommon.h> 46 #include <contrib/dev/acpica/include/actables.h> 47 48 49 #define _COMPONENT ACPI_TABLES 50 ACPI_MODULE_NAME ("tbxfroot") 51 52 53 /******************************************************************************* 54 * 55 * FUNCTION: AcpiTbGetRsdpLength 56 * 57 * PARAMETERS: Rsdp - Pointer to RSDP 58 * 59 * RETURN: Table length 60 * 61 * DESCRIPTION: Get the length of the RSDP 62 * 63 ******************************************************************************/ 64 65 UINT32 66 AcpiTbGetRsdpLength ( 67 ACPI_TABLE_RSDP *Rsdp) 68 { 69 70 if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) 71 { 72 /* BAD Signature */ 73 74 return (0); 75 } 76 77 /* "Length" field is available if table version >= 2 */ 78 79 if (Rsdp->Revision >= 2) 80 { 81 return (Rsdp->Length); 82 } 83 else 84 { 85 return (ACPI_RSDP_CHECKSUM_LENGTH); 86 } 87 } 88 89 90 /******************************************************************************* 91 * 92 * FUNCTION: AcpiTbValidateRsdp 93 * 94 * PARAMETERS: Rsdp - Pointer to unvalidated RSDP 95 * 96 * RETURN: Status 97 * 98 * DESCRIPTION: Validate the RSDP (ptr) 99 * 100 ******************************************************************************/ 101 102 ACPI_STATUS 103 AcpiTbValidateRsdp ( 104 ACPI_TABLE_RSDP *Rsdp) 105 { 106 107 /* 108 * The signature and checksum must both be correct 109 * 110 * Note: Sometimes there exists more than one RSDP in memory; the valid 111 * RSDP has a valid checksum, all others have an invalid checksum. 112 */ 113 if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) 114 { 115 /* Nope, BAD Signature */ 116 117 return (AE_BAD_SIGNATURE); 118 } 119 120 /* Check the standard checksum */ 121 122 if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) 123 { 124 return (AE_BAD_CHECKSUM); 125 } 126 127 /* Check extended checksum if table version >= 2 */ 128 129 if ((Rsdp->Revision >= 2) && 130 (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) 131 { 132 return (AE_BAD_CHECKSUM); 133 } 134 135 return (AE_OK); 136 } 137 138 139 /******************************************************************************* 140 * 141 * FUNCTION: AcpiFindRootPointer 142 * 143 * PARAMETERS: TableAddress - Where the table pointer is returned 144 * 145 * RETURN: Status, RSDP physical address 146 * 147 * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 148 * pointer structure. If it is found, set *RSDP to point to it. 149 * 150 * NOTE1: The RSDP must be either in the first 1K of the Extended 151 * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 152 * Only a 32-bit physical address is necessary. 153 * 154 * NOTE2: This function is always available, regardless of the 155 * initialization state of the rest of ACPI. 156 * 157 ******************************************************************************/ 158 159 ACPI_STATUS 160 AcpiFindRootPointer ( 161 ACPI_PHYSICAL_ADDRESS *TableAddress) 162 { 163 UINT8 *TablePtr; 164 UINT8 *MemRover; 165 UINT32 PhysicalAddress; 166 167 168 ACPI_FUNCTION_TRACE (AcpiFindRootPointer); 169 170 171 /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 172 173 TablePtr = AcpiOsMapMemory ( 174 (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, 175 ACPI_EBDA_PTR_LENGTH); 176 if (!TablePtr) 177 { 178 ACPI_ERROR ((AE_INFO, 179 "Could not map memory at 0x%8.8X for length %u", 180 ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 181 182 return_ACPI_STATUS (AE_NO_MEMORY); 183 } 184 185 ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); 186 187 /* Convert segment part to physical address */ 188 189 PhysicalAddress <<= 4; 190 AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); 191 192 /* EBDA present? */ 193 194 if (PhysicalAddress > 0x400) 195 { 196 /* 197 * 1b) Search EBDA paragraphs (EBDA is required to be a 198 * minimum of 1K length) 199 */ 200 TablePtr = AcpiOsMapMemory ( 201 (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, 202 ACPI_EBDA_WINDOW_SIZE); 203 if (!TablePtr) 204 { 205 ACPI_ERROR ((AE_INFO, 206 "Could not map memory at 0x%8.8X for length %u", 207 PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); 208 209 return_ACPI_STATUS (AE_NO_MEMORY); 210 } 211 212 MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); 213 AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); 214 215 if (MemRover) 216 { 217 /* Return the physical address */ 218 219 PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); 220 221 *TableAddress = (ACPI_PHYSICAL_ADDRESS) PhysicalAddress; 222 return_ACPI_STATUS (AE_OK); 223 } 224 } 225 226 /* 227 * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 228 */ 229 TablePtr = AcpiOsMapMemory ( 230 (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, 231 ACPI_HI_RSDP_WINDOW_SIZE); 232 233 if (!TablePtr) 234 { 235 ACPI_ERROR ((AE_INFO, 236 "Could not map memory at 0x%8.8X for length %u", 237 ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); 238 239 return_ACPI_STATUS (AE_NO_MEMORY); 240 } 241 242 MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 243 AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 244 245 if (MemRover) 246 { 247 /* Return the physical address */ 248 249 PhysicalAddress = (UINT32) 250 (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); 251 252 *TableAddress = (ACPI_PHYSICAL_ADDRESS) PhysicalAddress; 253 return_ACPI_STATUS (AE_OK); 254 } 255 256 /* A valid RSDP was not found */ 257 258 ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); 259 return_ACPI_STATUS (AE_NOT_FOUND); 260 } 261 262 ACPI_EXPORT_SYMBOL (AcpiFindRootPointer) 263 264 265 /******************************************************************************* 266 * 267 * FUNCTION: AcpiTbScanMemoryForRsdp 268 * 269 * PARAMETERS: StartAddress - Starting pointer for search 270 * Length - Maximum length to search 271 * 272 * RETURN: Pointer to the RSDP if found, otherwise NULL. 273 * 274 * DESCRIPTION: Search a block of memory for the RSDP signature 275 * 276 ******************************************************************************/ 277 278 UINT8 * 279 AcpiTbScanMemoryForRsdp ( 280 UINT8 *StartAddress, 281 UINT32 Length) 282 { 283 ACPI_STATUS Status; 284 UINT8 *MemRover; 285 UINT8 *EndAddress; 286 287 288 ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); 289 290 291 EndAddress = StartAddress + Length; 292 293 /* Search from given start address for the requested length */ 294 295 for (MemRover = StartAddress; MemRover < EndAddress; 296 MemRover += ACPI_RSDP_SCAN_STEP) 297 { 298 /* The RSDP signature and checksum must both be correct */ 299 300 Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); 301 if (ACPI_SUCCESS (Status)) 302 { 303 /* Sig and checksum valid, we have found a real RSDP */ 304 305 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 306 "RSDP located at physical address %p\n", MemRover)); 307 return_PTR (MemRover); 308 } 309 310 /* No sig match or bad checksum, keep searching */ 311 } 312 313 /* Searched entire block, no RSDP was found */ 314 315 ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 316 "Searched entire block from %p, valid RSDP was not found\n", 317 StartAddress)); 318 return_PTR (NULL); 319 } 320