167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: tbxfroot - Find the root ACPI table (RSDT) 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8217365Sjkim * Copyright (C) 2000 - 2011, Intel Corp. 970243Smsmith * All rights reserved. 1067754Smsmith * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 2567754Smsmith * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 2967754Smsmith * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 4367754Smsmith 4467754Smsmith#define __TBXFROOT_C__ 4567754Smsmith 46193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 47193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 48193341Sjkim#include <contrib/dev/acpica/include/actables.h> 4967754Smsmith 5067754Smsmith 5177424Smsmith#define _COMPONENT ACPI_TABLES 5291116Smsmith ACPI_MODULE_NAME ("tbxfroot") 5367754Smsmith 54151937Sjkim/* Local prototypes */ 5567754Smsmith 56151937Sjkimstatic UINT8 * 57151937SjkimAcpiTbScanMemoryForRsdp ( 58151937Sjkim UINT8 *StartAddress, 59151937Sjkim UINT32 Length); 60151937Sjkim 61167802Sjkimstatic ACPI_STATUS 62167802SjkimAcpiTbValidateRsdp ( 63167802Sjkim ACPI_TABLE_RSDP *Rsdp); 64151937Sjkim 65167802Sjkim 6667754Smsmith/******************************************************************************* 6767754Smsmith * 68151937Sjkim * FUNCTION: AcpiTbValidateRsdp 69151937Sjkim * 70167802Sjkim * PARAMETERS: Rsdp - Pointer to unvalidated RSDP 71151937Sjkim * 72151937Sjkim * RETURN: Status 73151937Sjkim * 74151937Sjkim * DESCRIPTION: Validate the RSDP (ptr) 75151937Sjkim * 76151937Sjkim ******************************************************************************/ 77151937Sjkim 78167802Sjkimstatic ACPI_STATUS 79151937SjkimAcpiTbValidateRsdp ( 80167802Sjkim ACPI_TABLE_RSDP *Rsdp) 81151937Sjkim{ 82151937Sjkim ACPI_FUNCTION_ENTRY (); 83151937Sjkim 84151937Sjkim 85151937Sjkim /* 86167802Sjkim * The signature and checksum must both be correct 87167802Sjkim * 88167802Sjkim * Note: Sometimes there exists more than one RSDP in memory; the valid 89167802Sjkim * RSDP has a valid checksum, all others have an invalid checksum. 90151937Sjkim */ 91193267Sjkim if (ACPI_STRNCMP ((char *) Rsdp, ACPI_SIG_RSDP, 92193267Sjkim sizeof (ACPI_SIG_RSDP)-1) != 0) 93151937Sjkim { 94151937Sjkim /* Nope, BAD Signature */ 95151937Sjkim 96151937Sjkim return (AE_BAD_SIGNATURE); 97151937Sjkim } 98151937Sjkim 99151937Sjkim /* Check the standard checksum */ 100151937Sjkim 101167802Sjkim if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) 102151937Sjkim { 103151937Sjkim return (AE_BAD_CHECKSUM); 104151937Sjkim } 105151937Sjkim 106151937Sjkim /* Check extended checksum if table version >= 2 */ 107151937Sjkim 108151937Sjkim if ((Rsdp->Revision >= 2) && 109167802Sjkim (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) 110151937Sjkim { 111151937Sjkim return (AE_BAD_CHECKSUM); 112151937Sjkim } 113151937Sjkim 114151937Sjkim return (AE_OK); 115151937Sjkim} 116151937Sjkim 117151937Sjkim 118151937Sjkim/******************************************************************************* 119151937Sjkim * 120193267Sjkim * FUNCTION: AcpiFindRootPointer 12167754Smsmith * 122167802Sjkim * PARAMETERS: TableAddress - Where the table pointer is returned 12367754Smsmith * 124167802Sjkim * RETURN: Status, RSDP physical address 12567754Smsmith * 126167802Sjkim * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 127167802Sjkim * pointer structure. If it is found, set *RSDP to point to it. 12867754Smsmith * 129167802Sjkim * NOTE1: The RSDP must be either in the first 1K of the Extended 130167802Sjkim * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 131167802Sjkim * Only a 32-bit physical address is necessary. 13278986Smsmith * 133167802Sjkim * NOTE2: This function is always available, regardless of the 134167802Sjkim * initialization state of the rest of ACPI. 13578986Smsmith * 13678986Smsmith ******************************************************************************/ 13767754Smsmith 13878986SmsmithACPI_STATUS 139167802SjkimAcpiFindRootPointer ( 140193267Sjkim ACPI_SIZE *TableAddress) 14178986Smsmith{ 142167802Sjkim UINT8 *TablePtr; 143167802Sjkim UINT8 *MemRover; 144167802Sjkim UINT32 PhysicalAddress; 14578986Smsmith 14678986Smsmith 147167802Sjkim ACPI_FUNCTION_TRACE (AcpiFindRootPointer); 14878986Smsmith 14978986Smsmith 150167802Sjkim /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 15167754Smsmith 152167802Sjkim TablePtr = AcpiOsMapMemory ( 153167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, 154167802Sjkim ACPI_EBDA_PTR_LENGTH); 155167802Sjkim if (!TablePtr) 15684491Smsmith { 157167802Sjkim ACPI_ERROR ((AE_INFO, 158204773Sjkim "Could not map memory at 0x%8.8X for length %u", 159167802Sjkim ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 16067754Smsmith 161138287Smarks return_ACPI_STATUS (AE_NO_MEMORY); 162138287Smarks } 163138287Smarks 164167802Sjkim ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); 16567754Smsmith 166167802Sjkim /* Convert segment part to physical address */ 16767754Smsmith 168167802Sjkim PhysicalAddress <<= 4; 169167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); 170138287Smarks 171167802Sjkim /* EBDA present? */ 172138287Smarks 173167802Sjkim if (PhysicalAddress > 0x400) 174138287Smarks { 175151937Sjkim /* 176167802Sjkim * 1b) Search EBDA paragraphs (EBDA is required to be a 177167802Sjkim * minimum of 1K length) 178151937Sjkim */ 179167802Sjkim TablePtr = AcpiOsMapMemory ( 180193267Sjkim (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, 181167802Sjkim ACPI_EBDA_WINDOW_SIZE); 182167802Sjkim if (!TablePtr) 18378986Smsmith { 184167802Sjkim ACPI_ERROR ((AE_INFO, 185204773Sjkim "Could not map memory at 0x%8.8X for length %u", 186167802Sjkim PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); 18767754Smsmith 188167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 18978986Smsmith } 19078986Smsmith 191167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); 192167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); 19378986Smsmith 194167802Sjkim if (MemRover) 19578986Smsmith { 196167802Sjkim /* Return the physical address */ 19778986Smsmith 198167802Sjkim PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); 19978986Smsmith 200167802Sjkim *TableAddress = PhysicalAddress; 201167802Sjkim return_ACPI_STATUS (AE_OK); 20278986Smsmith } 20367754Smsmith } 20467754Smsmith 205167802Sjkim /* 206167802Sjkim * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 207167802Sjkim */ 208167802Sjkim TablePtr = AcpiOsMapMemory ( 209167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, 210167802Sjkim ACPI_HI_RSDP_WINDOW_SIZE); 21167754Smsmith 212167802Sjkim if (!TablePtr) 213151937Sjkim { 214167802Sjkim ACPI_ERROR ((AE_INFO, 215204773Sjkim "Could not map memory at 0x%8.8X for length %u", 216167802Sjkim ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); 217138287Smarks 218167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 219138287Smarks } 22067754Smsmith 221167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 222167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 22367754Smsmith 224167802Sjkim if (MemRover) 225167802Sjkim { 226167802Sjkim /* Return the physical address */ 22791116Smsmith 228167802Sjkim PhysicalAddress = (UINT32) 229167802Sjkim (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); 23091116Smsmith 231167802Sjkim *TableAddress = PhysicalAddress; 232167802Sjkim return_ACPI_STATUS (AE_OK); 233167802Sjkim } 23491116Smsmith 235167802Sjkim /* A valid RSDP was not found */ 23691116Smsmith 237167802Sjkim ACPI_ERROR ((AE_INFO, "A valid RSDP was not found")); 238167802Sjkim return_ACPI_STATUS (AE_NOT_FOUND); 239167802Sjkim} 24091116Smsmith 241167802SjkimACPI_EXPORT_SYMBOL (AcpiFindRootPointer) 24291116Smsmith 24391116Smsmith 24491116Smsmith/******************************************************************************* 24591116Smsmith * 24691116Smsmith * FUNCTION: AcpiTbScanMemoryForRsdp 24791116Smsmith * 24891116Smsmith * PARAMETERS: StartAddress - Starting pointer for search 24991116Smsmith * Length - Maximum length to search 25091116Smsmith * 25191116Smsmith * RETURN: Pointer to the RSDP if found, otherwise NULL. 25291116Smsmith * 25391116Smsmith * DESCRIPTION: Search a block of memory for the RSDP signature 25491116Smsmith * 25591116Smsmith ******************************************************************************/ 25691116Smsmith 257151937Sjkimstatic UINT8 * 25891116SmsmithAcpiTbScanMemoryForRsdp ( 25991116Smsmith UINT8 *StartAddress, 26091116Smsmith UINT32 Length) 26191116Smsmith{ 262151937Sjkim ACPI_STATUS Status; 26391116Smsmith UINT8 *MemRover; 264138287Smarks UINT8 *EndAddress; 26591116Smsmith 26691116Smsmith 267167802Sjkim ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); 26891116Smsmith 26991116Smsmith 270138287Smarks EndAddress = StartAddress + Length; 27191116Smsmith 272138287Smarks /* Search from given start address for the requested length */ 273138287Smarks 274138287Smarks for (MemRover = StartAddress; MemRover < EndAddress; 275138287Smarks MemRover += ACPI_RSDP_SCAN_STEP) 27691116Smsmith { 277151937Sjkim /* The RSDP signature and checksum must both be correct */ 27891116Smsmith 279167802Sjkim Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); 280151937Sjkim if (ACPI_SUCCESS (Status)) 28191116Smsmith { 282151937Sjkim /* Sig and checksum valid, we have found a real RSDP */ 28391116Smsmith 28491116Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 285138287Smarks "RSDP located at physical address %p\n", MemRover)); 28691116Smsmith return_PTR (MemRover); 28791116Smsmith } 288138287Smarks 289151937Sjkim /* No sig match or bad checksum, keep searching */ 29091116Smsmith } 29191116Smsmith 29291116Smsmith /* Searched entire block, no RSDP was found */ 29391116Smsmith 294138287Smarks ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 295151937Sjkim "Searched entire block from %p, valid RSDP was not found\n", 296151937Sjkim StartAddress)); 29791116Smsmith return_PTR (NULL); 29891116Smsmith} 29991116Smsmith 300