1f654c0feSLin Ming /****************************************************************************** 2f654c0feSLin Ming * 3f654c0feSLin Ming * Module Name: utaddress - op_region address range check 4f654c0feSLin Ming * 5f654c0feSLin Ming *****************************************************************************/ 6f654c0feSLin Ming 7f654c0feSLin Ming /* 825f044e6SBob Moore * Copyright (C) 2000 - 2013, Intel Corp. 9f654c0feSLin Ming * All rights reserved. 10f654c0feSLin Ming * 11f654c0feSLin Ming * Redistribution and use in source and binary forms, with or without 12f654c0feSLin Ming * modification, are permitted provided that the following conditions 13f654c0feSLin Ming * are met: 14f654c0feSLin Ming * 1. Redistributions of source code must retain the above copyright 15f654c0feSLin Ming * notice, this list of conditions, and the following disclaimer, 16f654c0feSLin Ming * without modification. 17f654c0feSLin Ming * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18f654c0feSLin Ming * substantially similar to the "NO WARRANTY" disclaimer below 19f654c0feSLin Ming * ("Disclaimer") and any redistribution must be conditioned upon 20f654c0feSLin Ming * including a substantially similar Disclaimer requirement for further 21f654c0feSLin Ming * binary redistribution. 22f654c0feSLin Ming * 3. Neither the names of the above-listed copyright holders nor the names 23f654c0feSLin Ming * of any contributors may be used to endorse or promote products derived 24f654c0feSLin Ming * from this software without specific prior written permission. 25f654c0feSLin Ming * 26f654c0feSLin Ming * Alternatively, this software may be distributed under the terms of the 27f654c0feSLin Ming * GNU General Public License ("GPL") version 2 as published by the Free 28f654c0feSLin Ming * Software Foundation. 29f654c0feSLin Ming * 30f654c0feSLin Ming * NO WARRANTY 31f654c0feSLin Ming * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32f654c0feSLin Ming * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33f654c0feSLin Ming * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34f654c0feSLin Ming * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35f654c0feSLin Ming * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36f654c0feSLin Ming * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37f654c0feSLin Ming * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38f654c0feSLin Ming * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39f654c0feSLin Ming * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40f654c0feSLin Ming * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41f654c0feSLin Ming * POSSIBILITY OF SUCH DAMAGES. 42f654c0feSLin Ming */ 43f654c0feSLin Ming 44f654c0feSLin Ming #include <acpi/acpi.h> 45f654c0feSLin Ming #include "accommon.h" 46f654c0feSLin Ming #include "acnamesp.h" 47f654c0feSLin Ming 48f654c0feSLin Ming #define _COMPONENT ACPI_UTILITIES 49f654c0feSLin Ming ACPI_MODULE_NAME("utaddress") 50f654c0feSLin Ming 51f654c0feSLin Ming /******************************************************************************* 52f654c0feSLin Ming * 53f654c0feSLin Ming * FUNCTION: acpi_ut_add_address_range 54f654c0feSLin Ming * 55f654c0feSLin Ming * PARAMETERS: space_id - Address space ID 56ba494beeSBob Moore * address - op_region start address 57ba494beeSBob Moore * length - op_region length 58f654c0feSLin Ming * region_node - op_region namespace node 59f654c0feSLin Ming * 60f654c0feSLin Ming * RETURN: Status 61f654c0feSLin Ming * 62f654c0feSLin Ming * DESCRIPTION: Add the Operation Region address range to the global list. 63f654c0feSLin Ming * The only supported Space IDs are Memory and I/O. Called when 64f654c0feSLin Ming * the op_region address/length operands are fully evaluated. 65f654c0feSLin Ming * 66f654c0feSLin Ming * MUTEX: Locks the namespace 67f654c0feSLin Ming * 68f654c0feSLin Ming * NOTE: Because this interface is only called when an op_region argument 69f654c0feSLin Ming * list is evaluated, there cannot be any duplicate region_nodes. 70f654c0feSLin Ming * Duplicate Address/Length values are allowed, however, so that multiple 71f654c0feSLin Ming * address conflicts can be detected. 72f654c0feSLin Ming * 73f654c0feSLin Ming ******************************************************************************/ 74f654c0feSLin Ming acpi_status 75f654c0feSLin Ming acpi_ut_add_address_range(acpi_adr_space_type space_id, 76f654c0feSLin Ming acpi_physical_address address, 77f654c0feSLin Ming u32 length, struct acpi_namespace_node *region_node) 78f654c0feSLin Ming { 79f654c0feSLin Ming struct acpi_address_range *range_info; 80f654c0feSLin Ming acpi_status status; 81f654c0feSLin Ming 82f654c0feSLin Ming ACPI_FUNCTION_TRACE(ut_add_address_range); 83f654c0feSLin Ming 84f654c0feSLin Ming if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 85f654c0feSLin Ming (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 86f654c0feSLin Ming return_ACPI_STATUS(AE_OK); 87f654c0feSLin Ming } 88f654c0feSLin Ming 89f654c0feSLin Ming /* Allocate/init a new info block, add it to the appropriate list */ 90f654c0feSLin Ming 91f654c0feSLin Ming range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range)); 92f654c0feSLin Ming if (!range_info) { 93f654c0feSLin Ming return_ACPI_STATUS(AE_NO_MEMORY); 94f654c0feSLin Ming } 95f654c0feSLin Ming 96f654c0feSLin Ming range_info->start_address = address; 97f654c0feSLin Ming range_info->end_address = (address + length - 1); 98f654c0feSLin Ming range_info->region_node = region_node; 99f654c0feSLin Ming 100f654c0feSLin Ming status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE); 101f654c0feSLin Ming if (ACPI_FAILURE(status)) { 102f654c0feSLin Ming ACPI_FREE(range_info); 103f654c0feSLin Ming return_ACPI_STATUS(status); 104f654c0feSLin Ming } 105f654c0feSLin Ming 106f654c0feSLin Ming range_info->next = acpi_gbl_address_range_list[space_id]; 107f654c0feSLin Ming acpi_gbl_address_range_list[space_id] = range_info; 108f654c0feSLin Ming 109f654c0feSLin Ming ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 110f654c0feSLin Ming "\nAdded [%4.4s] address range: 0x%p-0x%p\n", 111f654c0feSLin Ming acpi_ut_get_node_name(range_info->region_node), 112f654c0feSLin Ming ACPI_CAST_PTR(void, address), 113f654c0feSLin Ming ACPI_CAST_PTR(void, range_info->end_address))); 114f654c0feSLin Ming 115f654c0feSLin Ming (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE); 116f654c0feSLin Ming return_ACPI_STATUS(AE_OK); 117f654c0feSLin Ming } 118f654c0feSLin Ming 119f654c0feSLin Ming /******************************************************************************* 120f654c0feSLin Ming * 121f654c0feSLin Ming * FUNCTION: acpi_ut_remove_address_range 122f654c0feSLin Ming * 123f654c0feSLin Ming * PARAMETERS: space_id - Address space ID 124f654c0feSLin Ming * region_node - op_region namespace node 125f654c0feSLin Ming * 126f654c0feSLin Ming * RETURN: None 127f654c0feSLin Ming * 128f654c0feSLin Ming * DESCRIPTION: Remove the Operation Region from the global list. The only 129f654c0feSLin Ming * supported Space IDs are Memory and I/O. Called when an 130f654c0feSLin Ming * op_region is deleted. 131f654c0feSLin Ming * 132f654c0feSLin Ming * MUTEX: Assumes the namespace is locked 133f654c0feSLin Ming * 134f654c0feSLin Ming ******************************************************************************/ 135f654c0feSLin Ming 136f654c0feSLin Ming void 137f654c0feSLin Ming acpi_ut_remove_address_range(acpi_adr_space_type space_id, 138f654c0feSLin Ming struct acpi_namespace_node *region_node) 139f654c0feSLin Ming { 140f654c0feSLin Ming struct acpi_address_range *range_info; 141f654c0feSLin Ming struct acpi_address_range *prev; 142f654c0feSLin Ming 143f654c0feSLin Ming ACPI_FUNCTION_TRACE(ut_remove_address_range); 144f654c0feSLin Ming 145f654c0feSLin Ming if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 146f654c0feSLin Ming (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 147f654c0feSLin Ming return_VOID; 148f654c0feSLin Ming } 149f654c0feSLin Ming 150f654c0feSLin Ming /* Get the appropriate list head and check the list */ 151f654c0feSLin Ming 152f654c0feSLin Ming range_info = prev = acpi_gbl_address_range_list[space_id]; 153f654c0feSLin Ming while (range_info) { 154f654c0feSLin Ming if (range_info->region_node == region_node) { 155f654c0feSLin Ming if (range_info == prev) { /* Found at list head */ 156f654c0feSLin Ming acpi_gbl_address_range_list[space_id] = 157f654c0feSLin Ming range_info->next; 158f654c0feSLin Ming } else { 159f654c0feSLin Ming prev->next = range_info->next; 160f654c0feSLin Ming } 161f654c0feSLin Ming 162f654c0feSLin Ming ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 163f654c0feSLin Ming "\nRemoved [%4.4s] address range: 0x%p-0x%p\n", 164f654c0feSLin Ming acpi_ut_get_node_name(range_info-> 165f654c0feSLin Ming region_node), 166f654c0feSLin Ming ACPI_CAST_PTR(void, 167f654c0feSLin Ming range_info-> 168f654c0feSLin Ming start_address), 169f654c0feSLin Ming ACPI_CAST_PTR(void, 170f654c0feSLin Ming range_info-> 171f654c0feSLin Ming end_address))); 172f654c0feSLin Ming 173f654c0feSLin Ming ACPI_FREE(range_info); 174f654c0feSLin Ming return_VOID; 175f654c0feSLin Ming } 176f654c0feSLin Ming 177f654c0feSLin Ming prev = range_info; 178f654c0feSLin Ming range_info = range_info->next; 179f654c0feSLin Ming } 180f654c0feSLin Ming 181f654c0feSLin Ming return_VOID; 182f654c0feSLin Ming } 183f654c0feSLin Ming 184f654c0feSLin Ming /******************************************************************************* 185f654c0feSLin Ming * 186f654c0feSLin Ming * FUNCTION: acpi_ut_check_address_range 187f654c0feSLin Ming * 188f654c0feSLin Ming * PARAMETERS: space_id - Address space ID 189ba494beeSBob Moore * address - Start address 190ba494beeSBob Moore * length - Length of address range 191ba494beeSBob Moore * warn - TRUE if warning on overlap desired 192f654c0feSLin Ming * 193f654c0feSLin Ming * RETURN: Count of the number of conflicts detected. Zero is always 194f654c0feSLin Ming * returned for Space IDs other than Memory or I/O. 195f654c0feSLin Ming * 196f654c0feSLin Ming * DESCRIPTION: Check if the input address range overlaps any of the 197f654c0feSLin Ming * ASL operation region address ranges. The only supported 198f654c0feSLin Ming * Space IDs are Memory and I/O. 199f654c0feSLin Ming * 200f654c0feSLin Ming * MUTEX: Assumes the namespace is locked. 201f654c0feSLin Ming * 202f654c0feSLin Ming ******************************************************************************/ 203f654c0feSLin Ming 204f654c0feSLin Ming u32 205f654c0feSLin Ming acpi_ut_check_address_range(acpi_adr_space_type space_id, 206f654c0feSLin Ming acpi_physical_address address, u32 length, u8 warn) 207f654c0feSLin Ming { 208f654c0feSLin Ming struct acpi_address_range *range_info; 209f654c0feSLin Ming acpi_physical_address end_address; 210f654c0feSLin Ming char *pathname; 211f654c0feSLin Ming u32 overlap_count = 0; 212f654c0feSLin Ming 213f654c0feSLin Ming ACPI_FUNCTION_TRACE(ut_check_address_range); 214f654c0feSLin Ming 215f654c0feSLin Ming if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 216f654c0feSLin Ming (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 217fd1af712SBob Moore return_UINT32(0); 218f654c0feSLin Ming } 219f654c0feSLin Ming 220f654c0feSLin Ming range_info = acpi_gbl_address_range_list[space_id]; 221f654c0feSLin Ming end_address = address + length - 1; 222f654c0feSLin Ming 223f654c0feSLin Ming /* Check entire list for all possible conflicts */ 224f654c0feSLin Ming 225f654c0feSLin Ming while (range_info) { 226f654c0feSLin Ming /* 227*0f607cb5SBob Moore * Check if the requested address/length overlaps this 228*0f607cb5SBob Moore * address range. There are four cases to consider: 229f654c0feSLin Ming * 230*0f607cb5SBob Moore * 1) Input address/length is contained completely in the 231*0f607cb5SBob Moore * address range 232f654c0feSLin Ming * 2) Input address/length overlaps range at the range start 233f654c0feSLin Ming * 3) Input address/length overlaps range at the range end 234f654c0feSLin Ming * 4) Input address/length completely encompasses the range 235f654c0feSLin Ming */ 236f654c0feSLin Ming if ((address <= range_info->end_address) && 237f654c0feSLin Ming (end_address >= range_info->start_address)) { 238f654c0feSLin Ming 239f654c0feSLin Ming /* Found an address range overlap */ 240f654c0feSLin Ming 241f654c0feSLin Ming overlap_count++; 242f654c0feSLin Ming if (warn) { /* Optional warning message */ 243f654c0feSLin Ming pathname = 244f654c0feSLin Ming acpi_ns_get_external_pathname(range_info-> 245f654c0feSLin Ming region_node); 246f654c0feSLin Ming 247f654c0feSLin Ming ACPI_WARNING((AE_INFO, 248*0f607cb5SBob Moore "%s range 0x%p-0x%p conflicts with OpRegion 0x%p-0x%p (%s)", 249*0f607cb5SBob Moore acpi_ut_get_region_name(space_id), 250f654c0feSLin Ming ACPI_CAST_PTR(void, address), 251f654c0feSLin Ming ACPI_CAST_PTR(void, end_address), 252*0f607cb5SBob Moore ACPI_CAST_PTR(void, 253*0f607cb5SBob Moore range_info-> 254*0f607cb5SBob Moore start_address), 255*0f607cb5SBob Moore ACPI_CAST_PTR(void, 256*0f607cb5SBob Moore range_info-> 257*0f607cb5SBob Moore end_address), 258*0f607cb5SBob Moore pathname)); 259f654c0feSLin Ming ACPI_FREE(pathname); 260f654c0feSLin Ming } 261f654c0feSLin Ming } 262f654c0feSLin Ming 263f654c0feSLin Ming range_info = range_info->next; 264f654c0feSLin Ming } 265f654c0feSLin Ming 266fd1af712SBob Moore return_UINT32(overlap_count); 267f654c0feSLin Ming } 268f654c0feSLin Ming 269f654c0feSLin Ming /******************************************************************************* 270f654c0feSLin Ming * 271f654c0feSLin Ming * FUNCTION: acpi_ut_delete_address_lists 272f654c0feSLin Ming * 273f654c0feSLin Ming * PARAMETERS: None 274f654c0feSLin Ming * 275f654c0feSLin Ming * RETURN: None 276f654c0feSLin Ming * 277f654c0feSLin Ming * DESCRIPTION: Delete all global address range lists (called during 278f654c0feSLin Ming * subsystem shutdown). 279f654c0feSLin Ming * 280f654c0feSLin Ming ******************************************************************************/ 281f654c0feSLin Ming 282f654c0feSLin Ming void acpi_ut_delete_address_lists(void) 283f654c0feSLin Ming { 284f654c0feSLin Ming struct acpi_address_range *next; 285f654c0feSLin Ming struct acpi_address_range *range_info; 286f654c0feSLin Ming int i; 287f654c0feSLin Ming 288f654c0feSLin Ming /* Delete all elements in all address range lists */ 289f654c0feSLin Ming 290f654c0feSLin Ming for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { 291f654c0feSLin Ming next = acpi_gbl_address_range_list[i]; 292f654c0feSLin Ming 293f654c0feSLin Ming while (next) { 294f654c0feSLin Ming range_info = next; 295f654c0feSLin Ming next = range_info->next; 296f654c0feSLin Ming ACPI_FREE(range_info); 297f654c0feSLin Ming } 298f654c0feSLin Ming 299f654c0feSLin Ming acpi_gbl_address_range_list[i] = NULL; 300f654c0feSLin Ming } 301f654c0feSLin Ming } 302