1 /****************************************************************************** 2 * 3 * Module Name: utaddress - OpRegion address range check 4 * 5 *****************************************************************************/ 6 7 /* 8 * Copyright (C) 2000 - 2014, 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 __UTADDRESS_C__ 45 46 #include "acpi.h" 47 #include "accommon.h" 48 #include "acnamesp.h" 49 50 51 #define _COMPONENT ACPI_UTILITIES 52 ACPI_MODULE_NAME ("utaddress") 53 54 55 /******************************************************************************* 56 * 57 * FUNCTION: AcpiUtAddAddressRange 58 * 59 * PARAMETERS: SpaceId - Address space ID 60 * Address - OpRegion start address 61 * Length - OpRegion length 62 * RegionNode - OpRegion namespace node 63 * 64 * RETURN: Status 65 * 66 * DESCRIPTION: Add the Operation Region address range to the global list. 67 * The only supported Space IDs are Memory and I/O. Called when 68 * the OpRegion address/length operands are fully evaluated. 69 * 70 * MUTEX: Locks the namespace 71 * 72 * NOTE: Because this interface is only called when an OpRegion argument 73 * list is evaluated, there cannot be any duplicate RegionNodes. 74 * Duplicate Address/Length values are allowed, however, so that multiple 75 * address conflicts can be detected. 76 * 77 ******************************************************************************/ 78 79 ACPI_STATUS 80 AcpiUtAddAddressRange ( 81 ACPI_ADR_SPACE_TYPE SpaceId, 82 ACPI_PHYSICAL_ADDRESS Address, 83 UINT32 Length, 84 ACPI_NAMESPACE_NODE *RegionNode) 85 { 86 ACPI_ADDRESS_RANGE *RangeInfo; 87 ACPI_STATUS Status; 88 89 90 ACPI_FUNCTION_TRACE (UtAddAddressRange); 91 92 93 if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 94 (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 95 { 96 return_ACPI_STATUS (AE_OK); 97 } 98 99 /* Allocate/init a new info block, add it to the appropriate list */ 100 101 RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE)); 102 if (!RangeInfo) 103 { 104 return_ACPI_STATUS (AE_NO_MEMORY); 105 } 106 107 RangeInfo->StartAddress = Address; 108 RangeInfo->EndAddress = (Address + Length - 1); 109 RangeInfo->RegionNode = RegionNode; 110 111 Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE); 112 if (ACPI_FAILURE (Status)) 113 { 114 ACPI_FREE (RangeInfo); 115 return_ACPI_STATUS (Status); 116 } 117 118 RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId]; 119 AcpiGbl_AddressRangeList[SpaceId] = RangeInfo; 120 121 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 122 "\nAdded [%4.4s] address range: 0x%p-0x%p\n", 123 AcpiUtGetNodeName (RangeInfo->RegionNode), 124 ACPI_CAST_PTR (void, Address), 125 ACPI_CAST_PTR (void, RangeInfo->EndAddress))); 126 127 (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE); 128 return_ACPI_STATUS (AE_OK); 129 } 130 131 132 /******************************************************************************* 133 * 134 * FUNCTION: AcpiUtRemoveAddressRange 135 * 136 * PARAMETERS: SpaceId - Address space ID 137 * RegionNode - OpRegion namespace node 138 * 139 * RETURN: None 140 * 141 * DESCRIPTION: Remove the Operation Region from the global list. The only 142 * supported Space IDs are Memory and I/O. Called when an 143 * OpRegion is deleted. 144 * 145 * MUTEX: Assumes the namespace is locked 146 * 147 ******************************************************************************/ 148 149 void 150 AcpiUtRemoveAddressRange ( 151 ACPI_ADR_SPACE_TYPE SpaceId, 152 ACPI_NAMESPACE_NODE *RegionNode) 153 { 154 ACPI_ADDRESS_RANGE *RangeInfo; 155 ACPI_ADDRESS_RANGE *Prev; 156 157 158 ACPI_FUNCTION_TRACE (UtRemoveAddressRange); 159 160 161 if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 162 (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 163 { 164 return_VOID; 165 } 166 167 /* Get the appropriate list head and check the list */ 168 169 RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId]; 170 while (RangeInfo) 171 { 172 if (RangeInfo->RegionNode == RegionNode) 173 { 174 if (RangeInfo == Prev) /* Found at list head */ 175 { 176 AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next; 177 } 178 else 179 { 180 Prev->Next = RangeInfo->Next; 181 } 182 183 ACPI_DEBUG_PRINT ((ACPI_DB_NAMES, 184 "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", 185 AcpiUtGetNodeName (RangeInfo->RegionNode), 186 ACPI_CAST_PTR (void, RangeInfo->StartAddress), 187 ACPI_CAST_PTR (void, RangeInfo->EndAddress))); 188 189 ACPI_FREE (RangeInfo); 190 return_VOID; 191 } 192 193 Prev = RangeInfo; 194 RangeInfo = RangeInfo->Next; 195 } 196 197 return_VOID; 198 } 199 200 201 /******************************************************************************* 202 * 203 * FUNCTION: AcpiUtCheckAddressRange 204 * 205 * PARAMETERS: SpaceId - Address space ID 206 * Address - Start address 207 * Length - Length of address range 208 * Warn - TRUE if warning on overlap desired 209 * 210 * RETURN: Count of the number of conflicts detected. Zero is always 211 * returned for Space IDs other than Memory or I/O. 212 * 213 * DESCRIPTION: Check if the input address range overlaps any of the 214 * ASL operation region address ranges. The only supported 215 * Space IDs are Memory and I/O. 216 * 217 * MUTEX: Assumes the namespace is locked. 218 * 219 ******************************************************************************/ 220 221 UINT32 222 AcpiUtCheckAddressRange ( 223 ACPI_ADR_SPACE_TYPE SpaceId, 224 ACPI_PHYSICAL_ADDRESS Address, 225 UINT32 Length, 226 BOOLEAN Warn) 227 { 228 ACPI_ADDRESS_RANGE *RangeInfo; 229 ACPI_PHYSICAL_ADDRESS EndAddress; 230 char *Pathname; 231 UINT32 OverlapCount = 0; 232 233 234 ACPI_FUNCTION_TRACE (UtCheckAddressRange); 235 236 237 if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 238 (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO)) 239 { 240 return_UINT32 (0); 241 } 242 243 RangeInfo = AcpiGbl_AddressRangeList[SpaceId]; 244 EndAddress = Address + Length - 1; 245 246 /* Check entire list for all possible conflicts */ 247 248 while (RangeInfo) 249 { 250 /* 251 * Check if the requested address/length overlaps this 252 * address range. There are four cases to consider: 253 * 254 * 1) Input address/length is contained completely in the 255 * address range 256 * 2) Input address/length overlaps range at the range start 257 * 3) Input address/length overlaps range at the range end 258 * 4) Input address/length completely encompasses the range 259 */ 260 if ((Address <= RangeInfo->EndAddress) && 261 (EndAddress >= RangeInfo->StartAddress)) 262 { 263 /* Found an address range overlap */ 264 265 OverlapCount++; 266 if (Warn) /* Optional warning message */ 267 { 268 Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode); 269 270 ACPI_WARNING ((AE_INFO, 271 "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)", 272 AcpiUtGetRegionName (SpaceId), 273 ACPI_CAST_PTR (void, Address), 274 ACPI_CAST_PTR (void, EndAddress), 275 ACPI_CAST_PTR (void, RangeInfo->StartAddress), 276 ACPI_CAST_PTR (void, RangeInfo->EndAddress), 277 Pathname)); 278 ACPI_FREE (Pathname); 279 } 280 } 281 282 RangeInfo = RangeInfo->Next; 283 } 284 285 return_UINT32 (OverlapCount); 286 } 287 288 289 /******************************************************************************* 290 * 291 * FUNCTION: AcpiUtDeleteAddressLists 292 * 293 * PARAMETERS: None 294 * 295 * RETURN: None 296 * 297 * DESCRIPTION: Delete all global address range lists (called during 298 * subsystem shutdown). 299 * 300 ******************************************************************************/ 301 302 void 303 AcpiUtDeleteAddressLists ( 304 void) 305 { 306 ACPI_ADDRESS_RANGE *Next; 307 ACPI_ADDRESS_RANGE *RangeInfo; 308 int i; 309 310 311 /* Delete all elements in all address range lists */ 312 313 for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) 314 { 315 Next = AcpiGbl_AddressRangeList[i]; 316 317 while (Next) 318 { 319 RangeInfo = Next; 320 Next = RangeInfo->Next; 321 ACPI_FREE (RangeInfo); 322 } 323 324 AcpiGbl_AddressRangeList[i] = NULL; 325 } 326 }