xref: /openbmc/linux/drivers/acpi/acpica/rsaddr.c (revision 7f1005dd)
1 // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2 /*******************************************************************************
3  *
4  * Module Name: rsaddr - Address resource descriptors (16/32/64)
5  *
6  ******************************************************************************/
7 
8 #include <acpi/acpi.h>
9 #include "accommon.h"
10 #include "acresrc.h"
11 
12 #define _COMPONENT          ACPI_RESOURCES
13 ACPI_MODULE_NAME("rsaddr")
14 
15 /*******************************************************************************
16  *
17  * acpi_rs_convert_address16 - All WORD (16-bit) address resources
18  *
19  ******************************************************************************/
20 struct acpi_rsconvert_info acpi_rs_convert_address16[5] = {
21 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS16,
22 	 ACPI_RS_SIZE(struct acpi_resource_address16),
23 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address16)},
24 
25 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS16,
26 	 sizeof(struct aml_resource_address16),
27 	 0},
28 
29 	/* Resource Type, General Flags, and Type-Specific Flags */
30 
31 	{ACPI_RSC_ADDRESS, 0, 0, 0},
32 
33 	/*
34 	 * These fields are contiguous in both the source and destination:
35 	 * Address Granularity
36 	 * Address Range Minimum
37 	 * Address Range Maximum
38 	 * Address Translation Offset
39 	 * Address Length
40 	 */
41 	{ACPI_RSC_MOVE16, ACPI_RS_OFFSET(data.address16.address.granularity),
42 	 AML_OFFSET(address16.granularity),
43 	 5},
44 
45 	/* Optional resource_source (Index and String) */
46 
47 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address16.resource_source),
48 	 0,
49 	 sizeof(struct aml_resource_address16)}
50 };
51 
52 /*******************************************************************************
53  *
54  * acpi_rs_convert_address32 - All DWORD (32-bit) address resources
55  *
56  ******************************************************************************/
57 
58 struct acpi_rsconvert_info acpi_rs_convert_address32[5] = {
59 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS32,
60 	 ACPI_RS_SIZE(struct acpi_resource_address32),
61 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address32)},
62 
63 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS32,
64 	 sizeof(struct aml_resource_address32),
65 	 0},
66 
67 	/* Resource Type, General Flags, and Type-Specific Flags */
68 
69 	{ACPI_RSC_ADDRESS, 0, 0, 0},
70 
71 	/*
72 	 * These fields are contiguous in both the source and destination:
73 	 * Address Granularity
74 	 * Address Range Minimum
75 	 * Address Range Maximum
76 	 * Address Translation Offset
77 	 * Address Length
78 	 */
79 	{ACPI_RSC_MOVE32, ACPI_RS_OFFSET(data.address32.address.granularity),
80 	 AML_OFFSET(address32.granularity),
81 	 5},
82 
83 	/* Optional resource_source (Index and String) */
84 
85 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address32.resource_source),
86 	 0,
87 	 sizeof(struct aml_resource_address32)}
88 };
89 
90 /*******************************************************************************
91  *
92  * acpi_rs_convert_address64 - All QWORD (64-bit) address resources
93  *
94  ******************************************************************************/
95 
96 struct acpi_rsconvert_info acpi_rs_convert_address64[5] = {
97 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_ADDRESS64,
98 	 ACPI_RS_SIZE(struct acpi_resource_address64),
99 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_address64)},
100 
101 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_ADDRESS64,
102 	 sizeof(struct aml_resource_address64),
103 	 0},
104 
105 	/* Resource Type, General Flags, and Type-Specific Flags */
106 
107 	{ACPI_RSC_ADDRESS, 0, 0, 0},
108 
109 	/*
110 	 * These fields are contiguous in both the source and destination:
111 	 * Address Granularity
112 	 * Address Range Minimum
113 	 * Address Range Maximum
114 	 * Address Translation Offset
115 	 * Address Length
116 	 */
117 	{ACPI_RSC_MOVE64, ACPI_RS_OFFSET(data.address64.address.granularity),
118 	 AML_OFFSET(address64.granularity),
119 	 5},
120 
121 	/* Optional resource_source (Index and String) */
122 
123 	{ACPI_RSC_SOURCE, ACPI_RS_OFFSET(data.address64.resource_source),
124 	 0,
125 	 sizeof(struct aml_resource_address64)}
126 };
127 
128 /*******************************************************************************
129  *
130  * acpi_rs_convert_ext_address64 - All Extended (64-bit) address resources
131  *
132  ******************************************************************************/
133 
134 struct acpi_rsconvert_info acpi_rs_convert_ext_address64[5] = {
135 	{ACPI_RSC_INITGET, ACPI_RESOURCE_TYPE_EXTENDED_ADDRESS64,
136 	 ACPI_RS_SIZE(struct acpi_resource_extended_address64),
137 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_ext_address64)},
138 
139 	{ACPI_RSC_INITSET, ACPI_RESOURCE_NAME_EXTENDED_ADDRESS64,
140 	 sizeof(struct aml_resource_extended_address64),
141 	 0},
142 
143 	/* Resource Type, General Flags, and Type-Specific Flags */
144 
145 	{ACPI_RSC_ADDRESS, 0, 0, 0},
146 
147 	/* Revision ID */
148 
149 	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.ext_address64.revision_ID),
150 	 AML_OFFSET(ext_address64.revision_ID),
151 	 1},
152 	/*
153 	 * These fields are contiguous in both the source and destination:
154 	 * Address Granularity
155 	 * Address Range Minimum
156 	 * Address Range Maximum
157 	 * Address Translation Offset
158 	 * Address Length
159 	 * Type-Specific Attribute
160 	 */
161 	{ACPI_RSC_MOVE64,
162 	 ACPI_RS_OFFSET(data.ext_address64.address.granularity),
163 	 AML_OFFSET(ext_address64.granularity),
164 	 6}
165 };
166 
167 /*******************************************************************************
168  *
169  * acpi_rs_convert_general_flags - Flags common to all address descriptors
170  *
171  ******************************************************************************/
172 
173 static struct acpi_rsconvert_info acpi_rs_convert_general_flags[6] = {
174 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.flags),
175 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_general_flags)},
176 
177 	/* Resource Type (Memory, Io, bus_number, etc.) */
178 
179 	{ACPI_RSC_MOVE8, ACPI_RS_OFFSET(data.address.resource_type),
180 	 AML_OFFSET(address.resource_type),
181 	 1},
182 
183 	/* General flags - Consume, Decode, min_fixed, max_fixed */
184 
185 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.producer_consumer),
186 	 AML_OFFSET(address.flags),
187 	 0},
188 
189 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.decode),
190 	 AML_OFFSET(address.flags),
191 	 1},
192 
193 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.min_address_fixed),
194 	 AML_OFFSET(address.flags),
195 	 2},
196 
197 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.max_address_fixed),
198 	 AML_OFFSET(address.flags),
199 	 3}
200 };
201 
202 /*******************************************************************************
203  *
204  * acpi_rs_convert_mem_flags - Flags common to Memory address descriptors
205  *
206  ******************************************************************************/
207 
208 static struct acpi_rsconvert_info acpi_rs_convert_mem_flags[5] = {
209 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
210 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_mem_flags)},
211 
212 	/* Memory-specific flags */
213 
214 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.write_protect),
215 	 AML_OFFSET(address.specific_flags),
216 	 0},
217 
218 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.caching),
219 	 AML_OFFSET(address.specific_flags),
220 	 1},
221 
222 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.range_type),
223 	 AML_OFFSET(address.specific_flags),
224 	 3},
225 
226 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.mem.translation),
227 	 AML_OFFSET(address.specific_flags),
228 	 5}
229 };
230 
231 /*******************************************************************************
232  *
233  * acpi_rs_convert_io_flags - Flags common to I/O address descriptors
234  *
235  ******************************************************************************/
236 
237 static struct acpi_rsconvert_info acpi_rs_convert_io_flags[4] = {
238 	{ACPI_RSC_FLAGINIT, 0, AML_OFFSET(address.specific_flags),
239 	 ACPI_RSC_TABLE_SIZE(acpi_rs_convert_io_flags)},
240 
241 	/* I/O-specific flags */
242 
243 	{ACPI_RSC_2BITFLAG, ACPI_RS_OFFSET(data.address.info.io.range_type),
244 	 AML_OFFSET(address.specific_flags),
245 	 0},
246 
247 	{ACPI_RSC_1BITFLAG, ACPI_RS_OFFSET(data.address.info.io.translation),
248 	 AML_OFFSET(address.specific_flags),
249 	 4},
250 
251 	{ACPI_RSC_1BITFLAG,
252 	 ACPI_RS_OFFSET(data.address.info.io.translation_type),
253 	 AML_OFFSET(address.specific_flags),
254 	 5}
255 };
256 
257 /*******************************************************************************
258  *
259  * FUNCTION:    acpi_rs_get_address_common
260  *
261  * PARAMETERS:  resource            - Pointer to the internal resource struct
262  *              aml                 - Pointer to the AML resource descriptor
263  *
264  * RETURN:      TRUE if the resource_type field is OK, FALSE otherwise
265  *
266  * DESCRIPTION: Convert common flag fields from a raw AML resource descriptor
267  *              to an internal resource descriptor
268  *
269  ******************************************************************************/
270 
271 u8
272 acpi_rs_get_address_common(struct acpi_resource *resource,
273 			   union aml_resource *aml)
274 {
275 	struct aml_resource_address address;
276 
277 	ACPI_FUNCTION_ENTRY();
278 
279 	/* Avoid undefined behavior: member access within misaligned address */
280 
281 	memcpy(&address, aml, sizeof(address));
282 
283 	/* Validate the Resource Type */
284 
285 	if ((address.resource_type > 2) && (address.resource_type < 0xC0)) {
286 		return (FALSE);
287 	}
288 
289 	/* Get the Resource Type and General Flags */
290 
291 	(void)acpi_rs_convert_aml_to_resource(resource, aml,
292 					      acpi_rs_convert_general_flags);
293 
294 	/* Get the Type-Specific Flags (Memory and I/O descriptors only) */
295 
296 	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
297 		(void)acpi_rs_convert_aml_to_resource(resource, aml,
298 						      acpi_rs_convert_mem_flags);
299 	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
300 		(void)acpi_rs_convert_aml_to_resource(resource, aml,
301 						      acpi_rs_convert_io_flags);
302 	} else {
303 		/* Generic resource type, just grab the type_specific byte */
304 
305 		resource->data.address.info.type_specific =
306 		    address.specific_flags;
307 	}
308 
309 	return (TRUE);
310 }
311 
312 /*******************************************************************************
313  *
314  * FUNCTION:    acpi_rs_set_address_common
315  *
316  * PARAMETERS:  aml                 - Pointer to the AML resource descriptor
317  *              resource            - Pointer to the internal resource struct
318  *
319  * RETURN:      None
320  *
321  * DESCRIPTION: Convert common flag fields from a resource descriptor to an
322  *              AML descriptor
323  *
324  ******************************************************************************/
325 
326 void
327 acpi_rs_set_address_common(union aml_resource *aml,
328 			   struct acpi_resource *resource)
329 {
330 	ACPI_FUNCTION_ENTRY();
331 
332 	/* Set the Resource Type and General Flags */
333 
334 	(void)acpi_rs_convert_resource_to_aml(resource, aml,
335 					      acpi_rs_convert_general_flags);
336 
337 	/* Set the Type-Specific Flags (Memory and I/O descriptors only) */
338 
339 	if (resource->data.address.resource_type == ACPI_MEMORY_RANGE) {
340 		(void)acpi_rs_convert_resource_to_aml(resource, aml,
341 						      acpi_rs_convert_mem_flags);
342 	} else if (resource->data.address.resource_type == ACPI_IO_RANGE) {
343 		(void)acpi_rs_convert_resource_to_aml(resource, aml,
344 						      acpi_rs_convert_io_flags);
345 	} else {
346 		/* Generic resource type, just copy the type_specific byte */
347 
348 		aml->address.specific_flags =
349 		    resource->data.address.info.type_specific;
350 	}
351 }
352