1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /******************************************************************************
4 * Module Name: utaddress - op_region address range check
6 * Copyright (C) 2000 - 2020, Intel Corp.
8 *****************************************************************************/
10 #include <acpi/acpi.h>
14 #define _COMPONENT ACPI_UTILITIES
15 ACPI_MODULE_NAME("utaddress")
17 /*******************************************************************************
19 * FUNCTION: acpi_ut_add_address_range
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
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.
32 * MUTEX: Locks the namespace
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.
39 ******************************************************************************/
41 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
)
45 struct acpi_address_range
*range_info
;
47 ACPI_FUNCTION_TRACE(ut_add_address_range
);
49 if ((space_id
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) &&
50 (space_id
!= ACPI_ADR_SPACE_SYSTEM_IO
)) {
51 return_ACPI_STATUS(AE_OK
);
54 /* Allocate/init a new info block, add it to the appropriate list */
56 range_info
= ACPI_ALLOCATE(sizeof(struct acpi_address_range
));
58 return_ACPI_STATUS(AE_NO_MEMORY
);
61 range_info
->start_address
= address
;
62 range_info
->end_address
= (address
+ length
- 1);
63 range_info
->region_node
= region_node
;
65 range_info
->next
= acpi_gbl_address_range_list
[space_id
];
66 acpi_gbl_address_range_list
[space_id
] = range_info
;
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 ACPI_FORMAT_UINT64(range_info
->end_address
)));
74 return_ACPI_STATUS(AE_OK
);
77 /*******************************************************************************
79 * FUNCTION: acpi_ut_remove_address_range
81 * PARAMETERS: space_id - Address space ID
82 * region_node - op_region namespace node
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.
90 * MUTEX: Assumes the namespace is locked
92 ******************************************************************************/
95 acpi_ut_remove_address_range(acpi_adr_space_type space_id
,
96 struct acpi_namespace_node
*region_node
)
98 struct acpi_address_range
*range_info
;
99 struct acpi_address_range
*prev
;
101 ACPI_FUNCTION_TRACE(ut_remove_address_range
);
103 if ((space_id
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) &&
104 (space_id
!= ACPI_ADR_SPACE_SYSTEM_IO
)) {
108 /* Get the appropriate list head and check the list */
110 range_info
= prev
= acpi_gbl_address_range_list
[space_id
];
112 if (range_info
->region_node
== region_node
) {
113 if (range_info
== prev
) { /* Found at list head */
114 acpi_gbl_address_range_list
[space_id
] =
117 prev
->next
= range_info
->next
;
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
->
124 ACPI_FORMAT_UINT64(range_info
->
126 ACPI_FORMAT_UINT64(range_info
->
129 ACPI_FREE(range_info
);
134 range_info
= range_info
->next
;
140 /*******************************************************************************
142 * FUNCTION: acpi_ut_check_address_range
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
149 * RETURN: Count of the number of conflicts detected. Zero is always
150 * returned for Space IDs other than Memory or I/O.
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.
156 * MUTEX: Assumes the namespace is locked.
158 ******************************************************************************/
161 acpi_ut_check_address_range(acpi_adr_space_type space_id
,
162 acpi_physical_address address
, u32 length
, u8 warn
)
164 struct acpi_address_range
*range_info
;
165 acpi_physical_address end_address
;
167 u32 overlap_count
= 0;
169 ACPI_FUNCTION_TRACE(ut_check_address_range
);
171 if ((space_id
!= ACPI_ADR_SPACE_SYSTEM_MEMORY
) &&
172 (space_id
!= ACPI_ADR_SPACE_SYSTEM_IO
)) {
176 range_info
= acpi_gbl_address_range_list
[space_id
];
177 end_address
= address
+ length
- 1;
179 /* Check entire list for all possible conflicts */
183 * Check if the requested address/length overlaps this
184 * address range. There are four cases to consider:
186 * 1) Input address/length is contained completely in the
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
192 if ((address
<= range_info
->end_address
) &&
193 (end_address
>= range_info
->start_address
)) {
195 /* Found an address range overlap */
198 if (warn
) { /* Optional warning message */
200 acpi_ns_get_normalized_pathname(range_info
->
204 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
->
211 ACPI_FORMAT_UINT64(range_info
->
218 range_info
= range_info
->next
;
221 return_UINT32(overlap_count
);
224 /*******************************************************************************
226 * FUNCTION: acpi_ut_delete_address_lists
232 * DESCRIPTION: Delete all global address range lists (called during
233 * subsystem shutdown).
235 ******************************************************************************/
237 void acpi_ut_delete_address_lists(void)
239 struct acpi_address_range
*next
;
240 struct acpi_address_range
*range_info
;
243 /* Delete all elements in all address range lists */
245 for (i
= 0; i
< ACPI_ADDRESS_RANGE_MAX
; i
++) {
246 next
= acpi_gbl_address_range_list
[i
];
250 next
= range_info
->next
;
251 ACPI_FREE(range_info
);
254 acpi_gbl_address_range_list
[i
] = NULL
;