167754Smsmith/****************************************************************************** 267754Smsmith * 367754Smsmith * Module Name: tbxfroot - Find the root ACPI table (RSDT) 467754Smsmith * 567754Smsmith *****************************************************************************/ 667754Smsmith 7217365Sjkim/* 8245582Sjkim * Copyright (C) 2000 - 2013, 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 5467754Smsmith 5567754Smsmith/******************************************************************************* 5667754Smsmith * 57151937Sjkim * FUNCTION: AcpiTbValidateRsdp 58151937Sjkim * 59167802Sjkim * PARAMETERS: Rsdp - Pointer to unvalidated RSDP 60151937Sjkim * 61151937Sjkim * RETURN: Status 62151937Sjkim * 63151937Sjkim * DESCRIPTION: Validate the RSDP (ptr) 64151937Sjkim * 65151937Sjkim ******************************************************************************/ 66151937Sjkim 67253690SjkimACPI_STATUS 68151937SjkimAcpiTbValidateRsdp ( 69167802Sjkim ACPI_TABLE_RSDP *Rsdp) 70151937Sjkim{ 71151937Sjkim 72151937Sjkim /* 73167802Sjkim * The signature and checksum must both be correct 74167802Sjkim * 75167802Sjkim * Note: Sometimes there exists more than one RSDP in memory; the valid 76167802Sjkim * RSDP has a valid checksum, all others have an invalid checksum. 77151937Sjkim */ 78254745Sjkim if (!ACPI_VALIDATE_RSDP_SIG (Rsdp->Signature)) 79151937Sjkim { 80151937Sjkim /* Nope, BAD Signature */ 81151937Sjkim 82151937Sjkim return (AE_BAD_SIGNATURE); 83151937Sjkim } 84151937Sjkim 85151937Sjkim /* Check the standard checksum */ 86151937Sjkim 87167802Sjkim if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) 88151937Sjkim { 89151937Sjkim return (AE_BAD_CHECKSUM); 90151937Sjkim } 91151937Sjkim 92151937Sjkim /* Check extended checksum if table version >= 2 */ 93151937Sjkim 94151937Sjkim if ((Rsdp->Revision >= 2) && 95167802Sjkim (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) 96151937Sjkim { 97151937Sjkim return (AE_BAD_CHECKSUM); 98151937Sjkim } 99151937Sjkim 100151937Sjkim return (AE_OK); 101151937Sjkim} 102151937Sjkim 103151937Sjkim 104151937Sjkim/******************************************************************************* 105151937Sjkim * 106193267Sjkim * FUNCTION: AcpiFindRootPointer 10767754Smsmith * 108167802Sjkim * PARAMETERS: TableAddress - Where the table pointer is returned 10967754Smsmith * 110167802Sjkim * RETURN: Status, RSDP physical address 11167754Smsmith * 112167802Sjkim * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 113241973Sjkim * pointer structure. If it is found, set *RSDP to point to it. 11467754Smsmith * 115167802Sjkim * NOTE1: The RSDP must be either in the first 1K of the Extended 116167802Sjkim * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 117167802Sjkim * Only a 32-bit physical address is necessary. 11878986Smsmith * 119167802Sjkim * NOTE2: This function is always available, regardless of the 120167802Sjkim * initialization state of the rest of ACPI. 12178986Smsmith * 12278986Smsmith ******************************************************************************/ 12367754Smsmith 12478986SmsmithACPI_STATUS 125167802SjkimAcpiFindRootPointer ( 126193267Sjkim ACPI_SIZE *TableAddress) 12778986Smsmith{ 128167802Sjkim UINT8 *TablePtr; 129167802Sjkim UINT8 *MemRover; 130167802Sjkim UINT32 PhysicalAddress; 13178986Smsmith 13278986Smsmith 133167802Sjkim ACPI_FUNCTION_TRACE (AcpiFindRootPointer); 13478986Smsmith 13578986Smsmith 136167802Sjkim /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 13767754Smsmith 138167802Sjkim TablePtr = AcpiOsMapMemory ( 139167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, 140167802Sjkim ACPI_EBDA_PTR_LENGTH); 141167802Sjkim if (!TablePtr) 14284491Smsmith { 143167802Sjkim ACPI_ERROR ((AE_INFO, 144204773Sjkim "Could not map memory at 0x%8.8X for length %u", 145167802Sjkim ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 14667754Smsmith 147138287Smarks return_ACPI_STATUS (AE_NO_MEMORY); 148138287Smarks } 149138287Smarks 150167802Sjkim ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); 15167754Smsmith 152167802Sjkim /* Convert segment part to physical address */ 15367754Smsmith 154167802Sjkim PhysicalAddress <<= 4; 155167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); 156138287Smarks 157167802Sjkim /* EBDA present? */ 158138287Smarks 159167802Sjkim if (PhysicalAddress > 0x400) 160138287Smarks { 161151937Sjkim /* 162167802Sjkim * 1b) Search EBDA paragraphs (EBDA is required to be a 163167802Sjkim * minimum of 1K length) 164151937Sjkim */ 165167802Sjkim TablePtr = AcpiOsMapMemory ( 166193267Sjkim (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, 167167802Sjkim ACPI_EBDA_WINDOW_SIZE); 168167802Sjkim if (!TablePtr) 16978986Smsmith { 170167802Sjkim ACPI_ERROR ((AE_INFO, 171204773Sjkim "Could not map memory at 0x%8.8X for length %u", 172167802Sjkim PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); 17367754Smsmith 174167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 17578986Smsmith } 17678986Smsmith 177167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); 178167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); 17978986Smsmith 180167802Sjkim if (MemRover) 18178986Smsmith { 182167802Sjkim /* Return the physical address */ 18378986Smsmith 184167802Sjkim PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); 18578986Smsmith 186167802Sjkim *TableAddress = PhysicalAddress; 187167802Sjkim return_ACPI_STATUS (AE_OK); 18878986Smsmith } 18967754Smsmith } 19067754Smsmith 191167802Sjkim /* 192167802Sjkim * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 193167802Sjkim */ 194167802Sjkim TablePtr = AcpiOsMapMemory ( 195167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, 196167802Sjkim ACPI_HI_RSDP_WINDOW_SIZE); 19767754Smsmith 198167802Sjkim if (!TablePtr) 199151937Sjkim { 200167802Sjkim ACPI_ERROR ((AE_INFO, 201204773Sjkim "Could not map memory at 0x%8.8X for length %u", 202167802Sjkim ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); 203138287Smarks 204167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 205138287Smarks } 20667754Smsmith 207167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 208167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 20967754Smsmith 210167802Sjkim if (MemRover) 211167802Sjkim { 212167802Sjkim /* Return the physical address */ 21391116Smsmith 214167802Sjkim PhysicalAddress = (UINT32) 215167802Sjkim (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); 21691116Smsmith 217167802Sjkim *TableAddress = PhysicalAddress; 218167802Sjkim return_ACPI_STATUS (AE_OK); 219167802Sjkim } 22091116Smsmith 221167802Sjkim /* A valid RSDP was not found */ 22291116Smsmith 223238381Sjkim ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); 224167802Sjkim return_ACPI_STATUS (AE_NOT_FOUND); 225167802Sjkim} 22691116Smsmith 227167802SjkimACPI_EXPORT_SYMBOL (AcpiFindRootPointer) 22891116Smsmith 22991116Smsmith 23091116Smsmith/******************************************************************************* 23191116Smsmith * 23291116Smsmith * FUNCTION: AcpiTbScanMemoryForRsdp 23391116Smsmith * 23491116Smsmith * PARAMETERS: StartAddress - Starting pointer for search 23591116Smsmith * Length - Maximum length to search 23691116Smsmith * 23791116Smsmith * RETURN: Pointer to the RSDP if found, otherwise NULL. 23891116Smsmith * 23991116Smsmith * DESCRIPTION: Search a block of memory for the RSDP signature 24091116Smsmith * 24191116Smsmith ******************************************************************************/ 24291116Smsmith 243252279SjkimUINT8 * 24491116SmsmithAcpiTbScanMemoryForRsdp ( 24591116Smsmith UINT8 *StartAddress, 24691116Smsmith UINT32 Length) 24791116Smsmith{ 248151937Sjkim ACPI_STATUS Status; 24991116Smsmith UINT8 *MemRover; 250138287Smarks UINT8 *EndAddress; 25191116Smsmith 25291116Smsmith 253167802Sjkim ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); 25491116Smsmith 25591116Smsmith 256138287Smarks EndAddress = StartAddress + Length; 25791116Smsmith 258138287Smarks /* Search from given start address for the requested length */ 259138287Smarks 260138287Smarks for (MemRover = StartAddress; MemRover < EndAddress; 261138287Smarks MemRover += ACPI_RSDP_SCAN_STEP) 26291116Smsmith { 263151937Sjkim /* The RSDP signature and checksum must both be correct */ 26491116Smsmith 265167802Sjkim Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); 266151937Sjkim if (ACPI_SUCCESS (Status)) 26791116Smsmith { 268151937Sjkim /* Sig and checksum valid, we have found a real RSDP */ 26991116Smsmith 27091116Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 271138287Smarks "RSDP located at physical address %p\n", MemRover)); 27291116Smsmith return_PTR (MemRover); 27391116Smsmith } 274138287Smarks 275151937Sjkim /* No sig match or bad checksum, keep searching */ 27691116Smsmith } 27791116Smsmith 27891116Smsmith /* Searched entire block, no RSDP was found */ 27991116Smsmith 280138287Smarks ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 281151937Sjkim "Searched entire block from %p, valid RSDP was not found\n", 282151937Sjkim StartAddress)); 28391116Smsmith return_PTR (NULL); 28491116Smsmith} 285