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 | info: 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 | info: 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 | info: 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 | info: 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 | info: 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 | info: 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 | |