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