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