1229982Sjkim/****************************************************************************** 2229982Sjkim * 3229982Sjkim * Module Name: utaddress - OpRegion address range check 4229982Sjkim * 5229982Sjkim *****************************************************************************/ 6229982Sjkim 7229982Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9229982Sjkim * All rights reserved. 10229982Sjkim * 11229982Sjkim * Redistribution and use in source and binary forms, with or without 12229982Sjkim * modification, are permitted provided that the following conditions 13229982Sjkim * are met: 14229982Sjkim * 1. Redistributions of source code must retain the above copyright 15229982Sjkim * notice, this list of conditions, and the following disclaimer, 16229982Sjkim * without modification. 17229982Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18229982Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19229982Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20229982Sjkim * including a substantially similar Disclaimer requirement for further 21229982Sjkim * binary redistribution. 22229982Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23229982Sjkim * of any contributors may be used to endorse or promote products derived 24229982Sjkim * from this software without specific prior written permission. 25229982Sjkim * 26229982Sjkim * Alternatively, this software may be distributed under the terms of the 27229982Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28229982Sjkim * Software Foundation. 29229982Sjkim * 30229982Sjkim * NO WARRANTY 31229982Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32229982Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33229982Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34229982Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35229982Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36229982Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37229982Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38229982Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39229982Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40229982Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41229982Sjkim * POSSIBILITY OF SUCH DAMAGES. 42229982Sjkim */ 43229982Sjkim 44229989Sjkim#include <contrib/dev/acpica/include/acpi.h> 45229989Sjkim#include <contrib/dev/acpica/include/accommon.h> 46229989Sjkim#include <contrib/dev/acpica/include/acnamesp.h> 47229982Sjkim 48229982Sjkim 49229982Sjkim#define _COMPONENT ACPI_UTILITIES 50229982Sjkim ACPI_MODULE_NAME ("utaddress") 51229982Sjkim 52229982Sjkim 53229982Sjkim/******************************************************************************* 54229982Sjkim * 55229982Sjkim * FUNCTION: AcpiUtAddAddressRange 56229982Sjkim * 57229982Sjkim * PARAMETERS: SpaceId - Address space ID 58229982Sjkim * Address - OpRegion start address 59229982Sjkim * Length - OpRegion length 60229982Sjkim * RegionNode - OpRegion namespace node 61229982Sjkim * 62229982Sjkim * RETURN: Status 63229982Sjkim * 64229982Sjkim * DESCRIPTION: Add the Operation Region address range to the global list. 65229982Sjkim * The only supported Space IDs are Memory and I/O. Called when 66229982Sjkim * the OpRegion address/length operands are fully evaluated. 67229982Sjkim * 68229982Sjkim * MUTEX: Locks the namespace 69229982Sjkim * 70229982Sjkim * NOTE: Because this interface is only called when an OpRegion argument 71229982Sjkim * list is evaluated, there cannot be any duplicate RegionNodes. 72229982Sjkim * Duplicate Address/Length values are allowed, however, so that multiple 73229982Sjkim * address conflicts can be detected. 74229982Sjkim * 75229982Sjkim ******************************************************************************/ 76229982Sjkim 77229982SjkimACPI_STATUS 78229982SjkimAcpiUtAddAddressRange ( 79229982Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 80229982Sjkim ACPI_PHYSICAL_ADDRESS Address, 81229982Sjkim UINT32 Length, 82229982Sjkim ACPI_NAMESPACE_NODE *RegionNode) 83229982Sjkim{ 84229982Sjkim ACPI_ADDRESS_RANGE *RangeInfo; 85229982Sjkim ACPI_STATUS Status; 86229982Sjkim 87229982Sjkim 88229982Sjkim ACPI_FUNCTION_TRACE (UtAddAddressRange); 89229982Sjkim 90229982Sjkim 91229982Sjkim if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 92229982Sjkim (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 93229982Sjkim { 94229982Sjkim return_ACPI_STATUS (AE_OK); 95229982Sjkim } 96229982Sjkim 97229982Sjkim /* Allocate/init a new info block, add it to the appropriate list */ 98229982Sjkim 99229982Sjkim RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE)); 100229982Sjkim if (!RangeInfo) 101229982Sjkim { 102229982Sjkim return_ACPI_STATUS (AE_NO_MEMORY); 103229982Sjkim } 104229982Sjkim 105229982Sjkim RangeInfo->StartAddress = Address; 106229982Sjkim RangeInfo->EndAddress = (Address + Length - 1); 107229982Sjkim RangeInfo->RegionNode = RegionNode; 108229982Sjkim 109229982Sjkim Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 110229982Sjkim if (ACPI_FAILURE (Status)) 111229982Sjkim { 112229982Sjkim ACPI_FREE (RangeInfo); 113229982Sjkim return_ACPI_STATUS (Status); 114229982Sjkim } 115229982Sjkim 116229982Sjkim RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId]; 117229982Sjkim AcpiGbl_AddressRangeList[SpaceId] = RangeInfo; 118229982Sjkim 119229982Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 120281687Sjkim "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", 121229982Sjkim AcpiUtGetNodeName (RangeInfo->RegionNode), 122281687Sjkim ACPI_FORMAT_UINT64 (Address), 123281687Sjkim ACPI_FORMAT_UINT64 (RangeInfo->EndAddress))); 124229982Sjkim 125229982Sjkim (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 126229982Sjkim return_ACPI_STATUS (AE_OK); 127229982Sjkim} 128229982Sjkim 129229982Sjkim 130229982Sjkim/******************************************************************************* 131229982Sjkim * 132229982Sjkim * FUNCTION: AcpiUtRemoveAddressRange 133229982Sjkim * 134229982Sjkim * PARAMETERS: SpaceId - Address space ID 135229982Sjkim * RegionNode - OpRegion namespace node 136229982Sjkim * 137229982Sjkim * RETURN: None 138229982Sjkim * 139229982Sjkim * DESCRIPTION: Remove the Operation Region from the global list. The only 140229982Sjkim * supported Space IDs are Memory and I/O. Called when an 141229982Sjkim * OpRegion is deleted. 142229982Sjkim * 143229982Sjkim * MUTEX: Assumes the namespace is locked 144229982Sjkim * 145229982Sjkim ******************************************************************************/ 146229982Sjkim 147229982Sjkimvoid 148229982SjkimAcpiUtRemoveAddressRange ( 149229982Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 150229982Sjkim ACPI_NAMESPACE_NODE *RegionNode) 151229982Sjkim{ 152229982Sjkim ACPI_ADDRESS_RANGE *RangeInfo; 153229982Sjkim ACPI_ADDRESS_RANGE *Prev; 154229982Sjkim 155229982Sjkim 156229982Sjkim ACPI_FUNCTION_TRACE (UtRemoveAddressRange); 157229982Sjkim 158229982Sjkim 159229982Sjkim if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 160229982Sjkim (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 161229982Sjkim { 162229982Sjkim return_VOID; 163229982Sjkim } 164229982Sjkim 165229982Sjkim /* Get the appropriate list head and check the list */ 166229982Sjkim 167229982Sjkim RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId]; 168229982Sjkim while (RangeInfo) 169229982Sjkim { 170229982Sjkim if (RangeInfo->RegionNode == RegionNode) 171229982Sjkim { 172229982Sjkim if (RangeInfo == Prev) /* Found at list head */ 173229982Sjkim { 174229982Sjkim AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next; 175229982Sjkim } 176229982Sjkim else 177229982Sjkim { 178229982Sjkim Prev->Next = RangeInfo->Next; 179229982Sjkim } 180229982Sjkim 181229982Sjkim ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 182281687Sjkim "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", 183229982Sjkim AcpiUtGetNodeName (RangeInfo->RegionNode), 184281687Sjkim ACPI_FORMAT_UINT64 (RangeInfo->StartAddress), 185281687Sjkim ACPI_FORMAT_UINT64 (RangeInfo->EndAddress))); 186229982Sjkim 187229982Sjkim ACPI_FREE (RangeInfo); 188229982Sjkim return_VOID; 189229982Sjkim } 190229982Sjkim 191229982Sjkim Prev = RangeInfo; 192229982Sjkim RangeInfo = RangeInfo->Next; 193229982Sjkim } 194229982Sjkim 195229982Sjkim return_VOID; 196229982Sjkim} 197229982Sjkim 198229982Sjkim 199229982Sjkim/******************************************************************************* 200229982Sjkim * 201229982Sjkim * FUNCTION: AcpiUtCheckAddressRange 202229982Sjkim * 203229982Sjkim * PARAMETERS: SpaceId - Address space ID 204229982Sjkim * Address - Start address 205229982Sjkim * Length - Length of address range 206229982Sjkim * Warn - TRUE if warning on overlap desired 207229982Sjkim * 208229982Sjkim * RETURN: Count of the number of conflicts detected. Zero is always 209229982Sjkim * returned for Space IDs other than Memory or I/O. 210229982Sjkim * 211229982Sjkim * DESCRIPTION: Check if the input address range overlaps any of the 212229982Sjkim * ASL operation region address ranges. The only supported 213229982Sjkim * Space IDs are Memory and I/O. 214229982Sjkim * 215229982Sjkim * MUTEX: Assumes the namespace is locked. 216229982Sjkim * 217229982Sjkim ******************************************************************************/ 218229982Sjkim 219229982SjkimUINT32 220229982SjkimAcpiUtCheckAddressRange ( 221229982Sjkim ACPI_ADR_SPACE_TYPE SpaceId, 222229982Sjkim ACPI_PHYSICAL_ADDRESS Address, 223229982Sjkim UINT32 Length, 224229982Sjkim BOOLEAN Warn) 225229982Sjkim{ 226229982Sjkim ACPI_ADDRESS_RANGE *RangeInfo; 227229982Sjkim ACPI_PHYSICAL_ADDRESS EndAddress; 228229982Sjkim char *Pathname; 229229982Sjkim UINT32 OverlapCount = 0; 230229982Sjkim 231229982Sjkim 232229982Sjkim ACPI_FUNCTION_TRACE (UtCheckAddressRange); 233229982Sjkim 234229982Sjkim 235229982Sjkim if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 236229982Sjkim (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 237229982Sjkim { 238246849Sjkim return_UINT32 (0); 239229982Sjkim } 240229982Sjkim 241229982Sjkim RangeInfo = AcpiGbl_AddressRangeList[SpaceId]; 242229982Sjkim EndAddress = Address + Length - 1; 243229982Sjkim 244229982Sjkim /* Check entire list for all possible conflicts */ 245229982Sjkim 246229982Sjkim while (RangeInfo) 247229982Sjkim { 248229982Sjkim /* 249281075Sdim * Check if the requested address/length overlaps this 250281075Sdim * address range. There are four cases to consider: 251229982Sjkim * 252281075Sdim * 1) Input address/length is contained completely in the 253281075Sdim * address range 254229982Sjkim * 2) Input address/length overlaps range at the range start 255229982Sjkim * 3) Input address/length overlaps range at the range end 256229982Sjkim * 4) Input address/length completely encompasses the range 257229982Sjkim */ 258229982Sjkim if ((Address <= RangeInfo->EndAddress) && 259229982Sjkim (EndAddress >= RangeInfo->StartAddress)) 260229982Sjkim { 261229982Sjkim /* Found an address range overlap */ 262229982Sjkim 263229982Sjkim OverlapCount++; 264229982Sjkim if (Warn) /* Optional warning message */ 265229982Sjkim { 266306536Sjkim Pathname = AcpiNsGetNormalizedPathname (RangeInfo->RegionNode, TRUE); 267229982Sjkim 268229982Sjkim ACPI_WARNING ((AE_INFO, 269281687Sjkim "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)", 270281075Sdim AcpiUtGetRegionName (SpaceId), 271281687Sjkim ACPI_FORMAT_UINT64 (Address), 272281687Sjkim ACPI_FORMAT_UINT64 (EndAddress), 273281687Sjkim ACPI_FORMAT_UINT64 (RangeInfo->StartAddress), 274281687Sjkim ACPI_FORMAT_UINT64 (RangeInfo->EndAddress), 275281075Sdim Pathname)); 276229982Sjkim ACPI_FREE (Pathname); 277229982Sjkim } 278229982Sjkim } 279229982Sjkim 280229982Sjkim RangeInfo = RangeInfo->Next; 281229982Sjkim } 282229982Sjkim 283246849Sjkim return_UINT32 (OverlapCount); 284229982Sjkim} 285229982Sjkim 286229982Sjkim 287229982Sjkim/******************************************************************************* 288229982Sjkim * 289229982Sjkim * FUNCTION: AcpiUtDeleteAddressLists 290229982Sjkim * 291229982Sjkim * PARAMETERS: None 292229982Sjkim * 293229982Sjkim * RETURN: None 294229982Sjkim * 295229982Sjkim * DESCRIPTION: Delete all global address range lists (called during 296229982Sjkim * subsystem shutdown). 297229982Sjkim * 298229982Sjkim ******************************************************************************/ 299229982Sjkim 300229982Sjkimvoid 301229982SjkimAcpiUtDeleteAddressLists ( 302229982Sjkim void) 303229982Sjkim{ 304229982Sjkim ACPI_ADDRESS_RANGE *Next; 305229982Sjkim ACPI_ADDRESS_RANGE *RangeInfo; 306229982Sjkim int i; 307229982Sjkim 308229982Sjkim 309229982Sjkim /* Delete all elements in all address range lists */ 310229982Sjkim 311229982Sjkim for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) 312229982Sjkim { 313229982Sjkim Next = AcpiGbl_AddressRangeList[i]; 314229982Sjkim 315229982Sjkim while (Next) 316229982Sjkim { 317229982Sjkim RangeInfo = Next; 318229982Sjkim Next = RangeInfo->Next; 319229982Sjkim ACPI_FREE (RangeInfo); 320229982Sjkim } 321229982Sjkim 322229982Sjkim AcpiGbl_AddressRangeList[i] = NULL; 323229982Sjkim } 324229982Sjkim} 325