tbxfroot.c revision 253690
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 */ 78253690Sjkim if (ACPI_STRNCMP ((char *) Rsdp->Signature, ACPI_SIG_RSDP, 79193267Sjkim sizeof (ACPI_SIG_RSDP)-1) != 0) 80151937Sjkim { 81151937Sjkim /* Nope, BAD Signature */ 82151937Sjkim 83151937Sjkim return (AE_BAD_SIGNATURE); 84151937Sjkim } 85151937Sjkim 86151937Sjkim /* Check the standard checksum */ 87151937Sjkim 88167802Sjkim if (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_CHECKSUM_LENGTH) != 0) 89151937Sjkim { 90151937Sjkim return (AE_BAD_CHECKSUM); 91151937Sjkim } 92151937Sjkim 93151937Sjkim /* Check extended checksum if table version >= 2 */ 94151937Sjkim 95151937Sjkim if ((Rsdp->Revision >= 2) && 96167802Sjkim (AcpiTbChecksum ((UINT8 *) Rsdp, ACPI_RSDP_XCHECKSUM_LENGTH) != 0)) 97151937Sjkim { 98151937Sjkim return (AE_BAD_CHECKSUM); 99151937Sjkim } 100151937Sjkim 101151937Sjkim return (AE_OK); 102151937Sjkim} 103151937Sjkim 104151937Sjkim 105151937Sjkim/******************************************************************************* 106151937Sjkim * 107193267Sjkim * FUNCTION: AcpiFindRootPointer 10867754Smsmith * 109167802Sjkim * PARAMETERS: TableAddress - Where the table pointer is returned 11067754Smsmith * 111167802Sjkim * RETURN: Status, RSDP physical address 11267754Smsmith * 113167802Sjkim * DESCRIPTION: Search lower 1Mbyte of memory for the root system descriptor 114241973Sjkim * pointer structure. If it is found, set *RSDP to point to it. 11567754Smsmith * 116167802Sjkim * NOTE1: The RSDP must be either in the first 1K of the Extended 117167802Sjkim * BIOS Data Area or between E0000 and FFFFF (From ACPI Spec.) 118167802Sjkim * Only a 32-bit physical address is necessary. 11978986Smsmith * 120167802Sjkim * NOTE2: This function is always available, regardless of the 121167802Sjkim * initialization state of the rest of ACPI. 12278986Smsmith * 12378986Smsmith ******************************************************************************/ 12467754Smsmith 12578986SmsmithACPI_STATUS 126167802SjkimAcpiFindRootPointer ( 127193267Sjkim ACPI_SIZE *TableAddress) 12878986Smsmith{ 129167802Sjkim UINT8 *TablePtr; 130167802Sjkim UINT8 *MemRover; 131167802Sjkim UINT32 PhysicalAddress; 13278986Smsmith 13378986Smsmith 134167802Sjkim ACPI_FUNCTION_TRACE (AcpiFindRootPointer); 13578986Smsmith 13678986Smsmith 137167802Sjkim /* 1a) Get the location of the Extended BIOS Data Area (EBDA) */ 13867754Smsmith 139167802Sjkim TablePtr = AcpiOsMapMemory ( 140167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_EBDA_PTR_LOCATION, 141167802Sjkim ACPI_EBDA_PTR_LENGTH); 142167802Sjkim if (!TablePtr) 14384491Smsmith { 144167802Sjkim ACPI_ERROR ((AE_INFO, 145204773Sjkim "Could not map memory at 0x%8.8X for length %u", 146167802Sjkim ACPI_EBDA_PTR_LOCATION, ACPI_EBDA_PTR_LENGTH)); 14767754Smsmith 148138287Smarks return_ACPI_STATUS (AE_NO_MEMORY); 149138287Smarks } 150138287Smarks 151167802Sjkim ACPI_MOVE_16_TO_32 (&PhysicalAddress, TablePtr); 15267754Smsmith 153167802Sjkim /* Convert segment part to physical address */ 15467754Smsmith 155167802Sjkim PhysicalAddress <<= 4; 156167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_PTR_LENGTH); 157138287Smarks 158167802Sjkim /* EBDA present? */ 159138287Smarks 160167802Sjkim if (PhysicalAddress > 0x400) 161138287Smarks { 162151937Sjkim /* 163167802Sjkim * 1b) Search EBDA paragraphs (EBDA is required to be a 164167802Sjkim * minimum of 1K length) 165151937Sjkim */ 166167802Sjkim TablePtr = AcpiOsMapMemory ( 167193267Sjkim (ACPI_PHYSICAL_ADDRESS) PhysicalAddress, 168167802Sjkim ACPI_EBDA_WINDOW_SIZE); 169167802Sjkim if (!TablePtr) 17078986Smsmith { 171167802Sjkim ACPI_ERROR ((AE_INFO, 172204773Sjkim "Could not map memory at 0x%8.8X for length %u", 173167802Sjkim PhysicalAddress, ACPI_EBDA_WINDOW_SIZE)); 17467754Smsmith 175167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 17678986Smsmith } 17778986Smsmith 178167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_EBDA_WINDOW_SIZE); 179167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_EBDA_WINDOW_SIZE); 18078986Smsmith 181167802Sjkim if (MemRover) 18278986Smsmith { 183167802Sjkim /* Return the physical address */ 18478986Smsmith 185167802Sjkim PhysicalAddress += (UINT32) ACPI_PTR_DIFF (MemRover, TablePtr); 18678986Smsmith 187167802Sjkim *TableAddress = PhysicalAddress; 188167802Sjkim return_ACPI_STATUS (AE_OK); 18978986Smsmith } 19067754Smsmith } 19167754Smsmith 192167802Sjkim /* 193167802Sjkim * 2) Search upper memory: 16-byte boundaries in E0000h-FFFFFh 194167802Sjkim */ 195167802Sjkim TablePtr = AcpiOsMapMemory ( 196167802Sjkim (ACPI_PHYSICAL_ADDRESS) ACPI_HI_RSDP_WINDOW_BASE, 197167802Sjkim ACPI_HI_RSDP_WINDOW_SIZE); 19867754Smsmith 199167802Sjkim if (!TablePtr) 200151937Sjkim { 201167802Sjkim ACPI_ERROR ((AE_INFO, 202204773Sjkim "Could not map memory at 0x%8.8X for length %u", 203167802Sjkim ACPI_HI_RSDP_WINDOW_BASE, ACPI_HI_RSDP_WINDOW_SIZE)); 204138287Smarks 205167802Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 206138287Smarks } 20767754Smsmith 208167802Sjkim MemRover = AcpiTbScanMemoryForRsdp (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 209167802Sjkim AcpiOsUnmapMemory (TablePtr, ACPI_HI_RSDP_WINDOW_SIZE); 21067754Smsmith 211167802Sjkim if (MemRover) 212167802Sjkim { 213167802Sjkim /* Return the physical address */ 21491116Smsmith 215167802Sjkim PhysicalAddress = (UINT32) 216167802Sjkim (ACPI_HI_RSDP_WINDOW_BASE + ACPI_PTR_DIFF (MemRover, TablePtr)); 21791116Smsmith 218167802Sjkim *TableAddress = PhysicalAddress; 219167802Sjkim return_ACPI_STATUS (AE_OK); 220167802Sjkim } 22191116Smsmith 222167802Sjkim /* A valid RSDP was not found */ 22391116Smsmith 224238381Sjkim ACPI_BIOS_ERROR ((AE_INFO, "A valid RSDP was not found")); 225167802Sjkim return_ACPI_STATUS (AE_NOT_FOUND); 226167802Sjkim} 22791116Smsmith 228167802SjkimACPI_EXPORT_SYMBOL (AcpiFindRootPointer) 22991116Smsmith 23091116Smsmith 23191116Smsmith/******************************************************************************* 23291116Smsmith * 23391116Smsmith * FUNCTION: AcpiTbScanMemoryForRsdp 23491116Smsmith * 23591116Smsmith * PARAMETERS: StartAddress - Starting pointer for search 23691116Smsmith * Length - Maximum length to search 23791116Smsmith * 23891116Smsmith * RETURN: Pointer to the RSDP if found, otherwise NULL. 23991116Smsmith * 24091116Smsmith * DESCRIPTION: Search a block of memory for the RSDP signature 24191116Smsmith * 24291116Smsmith ******************************************************************************/ 24391116Smsmith 244252279SjkimUINT8 * 24591116SmsmithAcpiTbScanMemoryForRsdp ( 24691116Smsmith UINT8 *StartAddress, 24791116Smsmith UINT32 Length) 24891116Smsmith{ 249151937Sjkim ACPI_STATUS Status; 25091116Smsmith UINT8 *MemRover; 251138287Smarks UINT8 *EndAddress; 25291116Smsmith 25391116Smsmith 254167802Sjkim ACPI_FUNCTION_TRACE (TbScanMemoryForRsdp); 25591116Smsmith 25691116Smsmith 257138287Smarks EndAddress = StartAddress + Length; 25891116Smsmith 259138287Smarks /* Search from given start address for the requested length */ 260138287Smarks 261138287Smarks for (MemRover = StartAddress; MemRover < EndAddress; 262138287Smarks MemRover += ACPI_RSDP_SCAN_STEP) 26391116Smsmith { 264151937Sjkim /* The RSDP signature and checksum must both be correct */ 26591116Smsmith 266167802Sjkim Status = AcpiTbValidateRsdp (ACPI_CAST_PTR (ACPI_TABLE_RSDP, MemRover)); 267151937Sjkim if (ACPI_SUCCESS (Status)) 26891116Smsmith { 269151937Sjkim /* Sig and checksum valid, we have found a real RSDP */ 27091116Smsmith 27191116Smsmith ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 272138287Smarks "RSDP located at physical address %p\n", MemRover)); 27391116Smsmith return_PTR (MemRover); 27491116Smsmith } 275138287Smarks 276151937Sjkim /* No sig match or bad checksum, keep searching */ 27791116Smsmith } 27891116Smsmith 27991116Smsmith /* Searched entire block, no RSDP was found */ 28091116Smsmith 281138287Smarks ACPI_DEBUG_PRINT ((ACPI_DB_INFO, 282151937Sjkim "Searched entire block from %p, valid RSDP was not found\n", 283151937Sjkim StartAddress)); 28491116Smsmith return_PTR (NULL); 28591116Smsmith} 286