Branch data Line data Source code
1 : : // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 2 : : /****************************************************************************** 3 : : * 4 : : * Module Name: utaddress - op_region address range check 5 : : * 6 : : * Copyright (C) 2000 - 2020, Intel Corp. 7 : : * 8 : : *****************************************************************************/ 9 : : 10 : : #include <acpi/acpi.h> 11 : : #include "accommon.h" 12 : : #include "acnamesp.h" 13 : : 14 : : #define _COMPONENT ACPI_UTILITIES 15 : : ACPI_MODULE_NAME("utaddress") 16 : : 17 : : /******************************************************************************* 18 : : * 19 : : * FUNCTION: acpi_ut_add_address_range 20 : : * 21 : : * PARAMETERS: space_id - Address space ID 22 : : * address - op_region start address 23 : : * length - op_region length 24 : : * region_node - op_region namespace node 25 : : * 26 : : * RETURN: Status 27 : : * 28 : : * DESCRIPTION: Add the Operation Region address range to the global list. 29 : : * The only supported Space IDs are Memory and I/O. Called when 30 : : * the op_region address/length operands are fully evaluated. 31 : : * 32 : : * MUTEX: Locks the namespace 33 : : * 34 : : * NOTE: Because this interface is only called when an op_region argument 35 : : * list is evaluated, there cannot be any duplicate region_nodes. 36 : : * Duplicate Address/Length values are allowed, however, so that multiple 37 : : * address conflicts can be detected. 38 : : * 39 : : ******************************************************************************/ 40 : : acpi_status 41 : 224 : acpi_ut_add_address_range(acpi_adr_space_type space_id, 42 : : acpi_physical_address address, 43 : : u32 length, struct acpi_namespace_node *region_node) 44 : : { 45 : 224 : struct acpi_address_range *range_info; 46 : : 47 : 224 : ACPI_FUNCTION_TRACE(ut_add_address_range); 48 : : 49 [ + + ]: 224 : if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 50 : : (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 51 : : return_ACPI_STATUS(AE_OK); 52 : : } 53 : : 54 : : /* Allocate/init a new info block, add it to the appropriate list */ 55 : : 56 : 168 : range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range)); 57 [ + - ]: 168 : if (!range_info) { 58 : : return_ACPI_STATUS(AE_NO_MEMORY); 59 : : } 60 : : 61 : 168 : range_info->start_address = address; 62 : 168 : range_info->end_address = (address + length - 1); 63 : 168 : range_info->region_node = region_node; 64 : : 65 : 168 : range_info->next = acpi_gbl_address_range_list[space_id]; 66 : 168 : acpi_gbl_address_range_list[space_id] = range_info; 67 : : 68 : : ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 69 : : "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", 70 : : acpi_ut_get_node_name(range_info->region_node), 71 : : ACPI_FORMAT_UINT64(address), 72 : 168 : ACPI_FORMAT_UINT64(range_info->end_address))); 73 : : 74 : 168 : return_ACPI_STATUS(AE_OK); 75 : : } 76 : : 77 : : /******************************************************************************* 78 : : * 79 : : * FUNCTION: acpi_ut_remove_address_range 80 : : * 81 : : * PARAMETERS: space_id - Address space ID 82 : : * region_node - op_region namespace node 83 : : * 84 : : * RETURN: None 85 : : * 86 : : * DESCRIPTION: Remove the Operation Region from the global list. The only 87 : : * supported Space IDs are Memory and I/O. Called when an 88 : : * op_region is deleted. 89 : : * 90 : : * MUTEX: Assumes the namespace is locked 91 : : * 92 : : ******************************************************************************/ 93 : : 94 : : void 95 : 0 : acpi_ut_remove_address_range(acpi_adr_space_type space_id, 96 : : struct acpi_namespace_node *region_node) 97 : : { 98 : 0 : struct acpi_address_range *range_info; 99 : 0 : struct acpi_address_range *prev; 100 : : 101 : 0 : ACPI_FUNCTION_TRACE(ut_remove_address_range); 102 : : 103 [ # # ]: 0 : if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 104 : : (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 105 : : return_VOID; 106 : : } 107 : : 108 : : /* Get the appropriate list head and check the list */ 109 : : 110 : 0 : range_info = prev = acpi_gbl_address_range_list[space_id]; 111 [ # # ]: 0 : while (range_info) { 112 [ # # ]: 0 : if (range_info->region_node == region_node) { 113 [ # # ]: 0 : if (range_info == prev) { /* Found at list head */ 114 : 0 : acpi_gbl_address_range_list[space_id] = 115 : 0 : range_info->next; 116 : : } else { 117 : 0 : prev->next = range_info->next; 118 : : } 119 : : 120 : : ACPI_DEBUG_PRINT((ACPI_DB_NAMES, 121 : : "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n", 122 : : acpi_ut_get_node_name(range_info-> 123 : : region_node), 124 : : ACPI_FORMAT_UINT64(range_info-> 125 : : start_address), 126 : : ACPI_FORMAT_UINT64(range_info-> 127 : 0 : end_address))); 128 : : 129 : 0 : ACPI_FREE(range_info); 130 : 0 : return_VOID; 131 : : } 132 : : 133 : 0 : prev = range_info; 134 : 0 : range_info = range_info->next; 135 : : } 136 : : 137 : : return_VOID; 138 : : } 139 : : 140 : : /******************************************************************************* 141 : : * 142 : : * FUNCTION: acpi_ut_check_address_range 143 : : * 144 : : * PARAMETERS: space_id - Address space ID 145 : : * address - Start address 146 : : * length - Length of address range 147 : : * warn - TRUE if warning on overlap desired 148 : : * 149 : : * RETURN: Count of the number of conflicts detected. Zero is always 150 : : * returned for Space IDs other than Memory or I/O. 151 : : * 152 : : * DESCRIPTION: Check if the input address range overlaps any of the 153 : : * ASL operation region address ranges. The only supported 154 : : * Space IDs are Memory and I/O. 155 : : * 156 : : * MUTEX: Assumes the namespace is locked. 157 : : * 158 : : ******************************************************************************/ 159 : : 160 : : u32 161 : 0 : acpi_ut_check_address_range(acpi_adr_space_type space_id, 162 : : acpi_physical_address address, u32 length, u8 warn) 163 : : { 164 : 0 : struct acpi_address_range *range_info; 165 : 0 : acpi_physical_address end_address; 166 : 0 : char *pathname; 167 : 0 : u32 overlap_count = 0; 168 : : 169 : 0 : ACPI_FUNCTION_TRACE(ut_check_address_range); 170 : : 171 [ # # ]: 0 : if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) && 172 : : (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) { 173 : : return_UINT32(0); 174 : : } 175 : : 176 : 0 : range_info = acpi_gbl_address_range_list[space_id]; 177 : 0 : end_address = address + length - 1; 178 : : 179 : : /* Check entire list for all possible conflicts */ 180 : : 181 [ # # ]: 0 : while (range_info) { 182 : : /* 183 : : * Check if the requested address/length overlaps this 184 : : * address range. There are four cases to consider: 185 : : * 186 : : * 1) Input address/length is contained completely in the 187 : : * address range 188 : : * 2) Input address/length overlaps range at the range start 189 : : * 3) Input address/length overlaps range at the range end 190 : : * 4) Input address/length completely encompasses the range 191 : : */ 192 [ # # ]: 0 : if ((address <= range_info->end_address) && 193 [ # # ]: 0 : (end_address >= range_info->start_address)) { 194 : : 195 : : /* Found an address range overlap */ 196 : : 197 : 0 : overlap_count++; 198 [ # # ]: 0 : if (warn) { /* Optional warning message */ 199 : 0 : pathname = 200 : 0 : acpi_ns_get_normalized_pathname(range_info-> 201 : : region_node, 202 : : TRUE); 203 : : 204 : 0 : ACPI_WARNING((AE_INFO, 205 : : "%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)", 206 : : acpi_ut_get_region_name(space_id), 207 : : ACPI_FORMAT_UINT64(address), 208 : : ACPI_FORMAT_UINT64(end_address), 209 : : ACPI_FORMAT_UINT64(range_info-> 210 : : start_address), 211 : : ACPI_FORMAT_UINT64(range_info-> 212 : : end_address), 213 : : pathname)); 214 : 0 : ACPI_FREE(pathname); 215 : : } 216 : : } 217 : : 218 : 0 : range_info = range_info->next; 219 : : } 220 : : 221 : : return_UINT32(overlap_count); 222 : : } 223 : : 224 : : /******************************************************************************* 225 : : * 226 : : * FUNCTION: acpi_ut_delete_address_lists 227 : : * 228 : : * PARAMETERS: None 229 : : * 230 : : * RETURN: None 231 : : * 232 : : * DESCRIPTION: Delete all global address range lists (called during 233 : : * subsystem shutdown). 234 : : * 235 : : ******************************************************************************/ 236 : : 237 : 0 : void acpi_ut_delete_address_lists(void) 238 : : { 239 : 0 : struct acpi_address_range *next; 240 : 0 : struct acpi_address_range *range_info; 241 : 0 : int i; 242 : : 243 : : /* Delete all elements in all address range lists */ 244 : : 245 [ # # ]: 0 : for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) { 246 : 0 : next = acpi_gbl_address_range_list[i]; 247 : : 248 [ # # ]: 0 : while (next) { 249 : 0 : range_info = next; 250 : 0 : next = range_info->next; 251 : 0 : ACPI_FREE(range_info); 252 : : } 253 : : 254 : 0 : acpi_gbl_address_range_list[i] = NULL; 255 : : } 256 : 0 : }