1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
2 | /******************************************************************************* |
3 | * |
4 | * Module Name: rsmisc - Miscellaneous resource descriptors |
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("rsmisc" ) |
14 | #define INIT_RESOURCE_TYPE(i) i->resource_offset |
15 | #define INIT_RESOURCE_LENGTH(i) i->aml_offset |
16 | #define INIT_TABLE_LENGTH(i) i->value |
17 | #define COMPARE_OPCODE(i) i->resource_offset |
18 | #define COMPARE_TARGET(i) i->aml_offset |
19 | #define COMPARE_VALUE(i) i->value |
20 | /******************************************************************************* |
21 | * |
22 | * FUNCTION: acpi_rs_convert_aml_to_resource |
23 | * |
24 | * PARAMETERS: resource - Pointer to the resource descriptor |
25 | * aml - Where the AML descriptor is returned |
26 | * info - Pointer to appropriate conversion table |
27 | * |
28 | * RETURN: Status |
29 | * |
30 | * DESCRIPTION: Convert an external AML resource descriptor to the corresponding |
31 | * internal resource descriptor |
32 | * |
33 | ******************************************************************************/ |
34 | acpi_status |
35 | acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, |
36 | union aml_resource *aml, |
37 | struct acpi_rsconvert_info *info) |
38 | { |
39 | acpi_rs_length aml_resource_length; |
40 | void *source; |
41 | void *destination; |
42 | char *target; |
43 | u8 count; |
44 | u8 flags_mode = FALSE; |
45 | u16 item_count = 0; |
46 | u16 temp16 = 0; |
47 | |
48 | ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); |
49 | |
50 | if (!info) { |
51 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
52 | } |
53 | |
54 | if (((acpi_size)resource) & 0x3) { |
55 | |
56 | /* Each internal resource struct is expected to be 32-bit aligned */ |
57 | |
58 | ACPI_WARNING((AE_INFO, |
59 | "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u" , |
60 | resource, resource->type, resource->length)); |
61 | } |
62 | |
63 | /* Extract the resource Length field (does not include header length) */ |
64 | |
65 | aml_resource_length = acpi_ut_get_resource_length(aml); |
66 | |
67 | /* |
68 | * First table entry must be ACPI_RSC_INITxxx and must contain the |
69 | * table length (# of table entries) |
70 | */ |
71 | count = INIT_TABLE_LENGTH(info); |
72 | while (count) { |
73 | target = NULL; |
74 | |
75 | /* |
76 | * Source is the external AML byte stream buffer, |
77 | * destination is the internal resource descriptor |
78 | */ |
79 | source = ACPI_ADD_PTR(void, aml, info->aml_offset); |
80 | destination = |
81 | ACPI_ADD_PTR(void, resource, info->resource_offset); |
82 | |
83 | switch (info->opcode) { |
84 | case ACPI_RSC_INITGET: |
85 | /* |
86 | * Get the resource type and the initial (minimum) length |
87 | */ |
88 | memset(resource, 0, INIT_RESOURCE_LENGTH(info)); |
89 | resource->type = INIT_RESOURCE_TYPE(info); |
90 | resource->length = INIT_RESOURCE_LENGTH(info); |
91 | break; |
92 | |
93 | case ACPI_RSC_INITSET: |
94 | break; |
95 | |
96 | case ACPI_RSC_FLAGINIT: |
97 | |
98 | flags_mode = TRUE; |
99 | break; |
100 | |
101 | case ACPI_RSC_1BITFLAG: |
102 | /* |
103 | * Mask and shift the flag bit |
104 | */ |
105 | ACPI_SET8(destination, |
106 | ((ACPI_GET8(source) >> info->value) & 0x01)); |
107 | break; |
108 | |
109 | case ACPI_RSC_2BITFLAG: |
110 | /* |
111 | * Mask and shift the flag bits |
112 | */ |
113 | ACPI_SET8(destination, |
114 | ((ACPI_GET8(source) >> info->value) & 0x03)); |
115 | break; |
116 | |
117 | case ACPI_RSC_3BITFLAG: |
118 | /* |
119 | * Mask and shift the flag bits |
120 | */ |
121 | ACPI_SET8(destination, |
122 | ((ACPI_GET8(source) >> info->value) & 0x07)); |
123 | break; |
124 | |
125 | case ACPI_RSC_6BITFLAG: |
126 | /* |
127 | * Mask and shift the flag bits |
128 | */ |
129 | ACPI_SET8(destination, |
130 | ((ACPI_GET8(source) >> info->value) & 0x3F)); |
131 | break; |
132 | |
133 | case ACPI_RSC_COUNT: |
134 | |
135 | item_count = ACPI_GET8(source); |
136 | ACPI_SET8(destination, item_count); |
137 | |
138 | resource->length = resource->length + |
139 | (info->value * (item_count - 1)); |
140 | break; |
141 | |
142 | case ACPI_RSC_COUNT16: |
143 | |
144 | item_count = aml_resource_length; |
145 | ACPI_SET16(destination, item_count); |
146 | |
147 | resource->length = resource->length + |
148 | (info->value * (item_count - 1)); |
149 | break; |
150 | |
151 | case ACPI_RSC_COUNT_GPIO_PIN: |
152 | |
153 | target = ACPI_ADD_PTR(void, aml, info->value); |
154 | item_count = ACPI_GET16(target) - ACPI_GET16(source); |
155 | |
156 | resource->length = resource->length + item_count; |
157 | item_count = item_count / 2; |
158 | ACPI_SET16(destination, item_count); |
159 | break; |
160 | |
161 | case ACPI_RSC_COUNT_GPIO_VEN: |
162 | |
163 | item_count = ACPI_GET8(source); |
164 | ACPI_SET8(destination, item_count); |
165 | |
166 | resource->length = |
167 | resource->length + (info->value * item_count); |
168 | break; |
169 | |
170 | case ACPI_RSC_COUNT_GPIO_RES: |
171 | /* |
172 | * Vendor data is optional (length/offset may both be zero) |
173 | * Examine vendor data length field first |
174 | */ |
175 | target = ACPI_ADD_PTR(void, aml, (info->value + 2)); |
176 | if (ACPI_GET16(target)) { |
177 | |
178 | /* Use vendor offset to get resource source length */ |
179 | |
180 | target = ACPI_ADD_PTR(void, aml, info->value); |
181 | item_count = |
182 | ACPI_GET16(target) - ACPI_GET16(source); |
183 | } else { |
184 | /* No vendor data to worry about */ |
185 | |
186 | item_count = aml->large_header.resource_length + |
187 | sizeof(struct aml_resource_large_header) - |
188 | ACPI_GET16(source); |
189 | } |
190 | |
191 | resource->length = resource->length + item_count; |
192 | ACPI_SET16(destination, item_count); |
193 | break; |
194 | |
195 | case ACPI_RSC_COUNT_SERIAL_VEN: |
196 | |
197 | ACPI_MOVE_16_TO_16(&temp16, source); |
198 | item_count = temp16 - info->value; |
199 | |
200 | resource->length = resource->length + item_count; |
201 | ACPI_SET16(destination, item_count); |
202 | break; |
203 | |
204 | case ACPI_RSC_COUNT_SERIAL_RES: |
205 | |
206 | ACPI_MOVE_16_TO_16(&temp16, source); |
207 | item_count = (aml_resource_length + |
208 | sizeof(struct aml_resource_large_header)) |
209 | - temp16 - info->value; |
210 | |
211 | resource->length = resource->length + item_count; |
212 | ACPI_SET16(destination, item_count); |
213 | break; |
214 | |
215 | case ACPI_RSC_LENGTH: |
216 | |
217 | resource->length = resource->length + info->value; |
218 | break; |
219 | |
220 | case ACPI_RSC_MOVE8: |
221 | case ACPI_RSC_MOVE16: |
222 | case ACPI_RSC_MOVE32: |
223 | case ACPI_RSC_MOVE64: |
224 | /* |
225 | * Raw data move. Use the Info value field unless item_count has |
226 | * been previously initialized via a COUNT opcode |
227 | */ |
228 | if (info->value) { |
229 | item_count = info->value; |
230 | } |
231 | acpi_rs_move_data(destination, source, item_count, |
232 | move_type: info->opcode); |
233 | break; |
234 | |
235 | case ACPI_RSC_MOVE_GPIO_PIN: |
236 | |
237 | /* Generate and set the PIN data pointer */ |
238 | |
239 | target = (char *)ACPI_ADD_PTR(void, resource, |
240 | (resource->length - |
241 | item_count * 2)); |
242 | *(u16 **)destination = ACPI_CAST_PTR(u16, target); |
243 | |
244 | /* Copy the PIN data */ |
245 | |
246 | source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); |
247 | acpi_rs_move_data(destination: target, source, item_count, |
248 | move_type: info->opcode); |
249 | break; |
250 | |
251 | case ACPI_RSC_MOVE_GPIO_RES: |
252 | |
253 | /* Generate and set the resource_source string pointer */ |
254 | |
255 | target = (char *)ACPI_ADD_PTR(void, resource, |
256 | (resource->length - |
257 | item_count)); |
258 | *(u8 **)destination = ACPI_CAST_PTR(u8, target); |
259 | |
260 | /* Copy the resource_source string */ |
261 | |
262 | source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); |
263 | acpi_rs_move_data(destination: target, source, item_count, |
264 | move_type: info->opcode); |
265 | break; |
266 | |
267 | case ACPI_RSC_MOVE_SERIAL_VEN: |
268 | |
269 | /* Generate and set the Vendor Data pointer */ |
270 | |
271 | target = (char *)ACPI_ADD_PTR(void, resource, |
272 | (resource->length - |
273 | item_count)); |
274 | *(u8 **)destination = ACPI_CAST_PTR(u8, target); |
275 | |
276 | /* Copy the Vendor Data */ |
277 | |
278 | source = ACPI_ADD_PTR(void, aml, info->value); |
279 | acpi_rs_move_data(destination: target, source, item_count, |
280 | move_type: info->opcode); |
281 | break; |
282 | |
283 | case ACPI_RSC_MOVE_SERIAL_RES: |
284 | |
285 | /* Generate and set the resource_source string pointer */ |
286 | |
287 | target = (char *)ACPI_ADD_PTR(void, resource, |
288 | (resource->length - |
289 | item_count)); |
290 | *(u8 **)destination = ACPI_CAST_PTR(u8, target); |
291 | |
292 | /* Copy the resource_source string */ |
293 | |
294 | ACPI_MOVE_16_TO_16(&temp16, source); |
295 | source = |
296 | ACPI_ADD_PTR(void, aml, (temp16 + info->value)); |
297 | acpi_rs_move_data(destination: target, source, item_count, |
298 | move_type: info->opcode); |
299 | break; |
300 | |
301 | case ACPI_RSC_SET8: |
302 | |
303 | memset(destination, info->aml_offset, info->value); |
304 | break; |
305 | |
306 | case ACPI_RSC_DATA8: |
307 | |
308 | target = ACPI_ADD_PTR(char, resource, info->value); |
309 | memcpy(destination, source, ACPI_GET16(target)); |
310 | break; |
311 | |
312 | case ACPI_RSC_ADDRESS: |
313 | /* |
314 | * Common handler for address descriptor flags |
315 | */ |
316 | if (!acpi_rs_get_address_common(resource, aml)) { |
317 | return_ACPI_STATUS |
318 | (AE_AML_INVALID_RESOURCE_TYPE); |
319 | } |
320 | break; |
321 | |
322 | case ACPI_RSC_SOURCE: |
323 | /* |
324 | * Optional resource_source (Index and String) |
325 | */ |
326 | resource->length += |
327 | acpi_rs_get_resource_source(resource_length: aml_resource_length, |
328 | minimum_length: info->value, |
329 | resource_source: destination, aml, NULL); |
330 | break; |
331 | |
332 | case ACPI_RSC_SOURCEX: |
333 | /* |
334 | * Optional resource_source (Index and String). This is the more |
335 | * complicated case used by the Interrupt() macro |
336 | */ |
337 | target = ACPI_ADD_PTR(char, resource, |
338 | info->aml_offset + |
339 | (item_count * 4)); |
340 | |
341 | resource->length += |
342 | acpi_rs_get_resource_source(resource_length: aml_resource_length, |
343 | minimum_length: (acpi_rs_length) |
344 | (((item_count - |
345 | 1) * sizeof(u32)) + |
346 | info->value), |
347 | resource_source: destination, aml, |
348 | string_ptr: target); |
349 | break; |
350 | |
351 | case ACPI_RSC_BITMASK: |
352 | /* |
353 | * 8-bit encoded bitmask (DMA macro) |
354 | */ |
355 | item_count = |
356 | acpi_rs_decode_bitmask(ACPI_GET8(source), |
357 | list: destination); |
358 | if (item_count) { |
359 | resource->length += (item_count - 1); |
360 | } |
361 | |
362 | target = ACPI_ADD_PTR(char, resource, info->value); |
363 | ACPI_SET8(target, item_count); |
364 | break; |
365 | |
366 | case ACPI_RSC_BITMASK16: |
367 | /* |
368 | * 16-bit encoded bitmask (IRQ macro) |
369 | */ |
370 | ACPI_MOVE_16_TO_16(&temp16, source); |
371 | |
372 | item_count = |
373 | acpi_rs_decode_bitmask(mask: temp16, list: destination); |
374 | if (item_count) { |
375 | resource->length += (item_count - 1); |
376 | } |
377 | |
378 | target = ACPI_ADD_PTR(char, resource, info->value); |
379 | ACPI_SET8(target, item_count); |
380 | break; |
381 | |
382 | case ACPI_RSC_EXIT_NE: |
383 | /* |
384 | * control - Exit conversion if not equal |
385 | */ |
386 | switch (info->resource_offset) { |
387 | case ACPI_RSC_COMPARE_AML_LENGTH: |
388 | |
389 | if (aml_resource_length != info->value) { |
390 | goto exit; |
391 | } |
392 | break; |
393 | |
394 | case ACPI_RSC_COMPARE_VALUE: |
395 | |
396 | if (ACPI_GET8(source) != info->value) { |
397 | goto exit; |
398 | } |
399 | break; |
400 | |
401 | default: |
402 | |
403 | ACPI_ERROR((AE_INFO, |
404 | "Invalid conversion sub-opcode" )); |
405 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
406 | } |
407 | break; |
408 | |
409 | default: |
410 | |
411 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode" )); |
412 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
413 | } |
414 | |
415 | count--; |
416 | info++; |
417 | } |
418 | |
419 | exit: |
420 | if (!flags_mode) { |
421 | |
422 | /* Round the resource struct length up to the next boundary (32 or 64) */ |
423 | |
424 | resource->length = (u32) |
425 | ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); |
426 | } |
427 | return_ACPI_STATUS(AE_OK); |
428 | } |
429 | |
430 | /******************************************************************************* |
431 | * |
432 | * FUNCTION: acpi_rs_convert_resource_to_aml |
433 | * |
434 | * PARAMETERS: resource - Pointer to the resource descriptor |
435 | * aml - Where the AML descriptor is returned |
436 | * info - Pointer to appropriate conversion table |
437 | * |
438 | * RETURN: Status |
439 | * |
440 | * DESCRIPTION: Convert an internal resource descriptor to the corresponding |
441 | * external AML resource descriptor. |
442 | * |
443 | ******************************************************************************/ |
444 | |
445 | acpi_status |
446 | acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, |
447 | union aml_resource *aml, |
448 | struct acpi_rsconvert_info *info) |
449 | { |
450 | void *source = NULL; |
451 | void *destination; |
452 | char *target; |
453 | acpi_rsdesc_size aml_length = 0; |
454 | u8 count; |
455 | u16 temp16 = 0; |
456 | u16 item_count = 0; |
457 | |
458 | ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); |
459 | |
460 | if (!info) { |
461 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
462 | } |
463 | |
464 | /* |
465 | * First table entry must be ACPI_RSC_INITxxx and must contain the |
466 | * table length (# of table entries) |
467 | */ |
468 | count = INIT_TABLE_LENGTH(info); |
469 | |
470 | while (count) { |
471 | /* |
472 | * Source is the internal resource descriptor, |
473 | * destination is the external AML byte stream buffer |
474 | */ |
475 | source = ACPI_ADD_PTR(void, resource, info->resource_offset); |
476 | destination = ACPI_ADD_PTR(void, aml, info->aml_offset); |
477 | |
478 | switch (info->opcode) { |
479 | case ACPI_RSC_INITSET: |
480 | |
481 | memset(aml, 0, INIT_RESOURCE_LENGTH(info)); |
482 | aml_length = INIT_RESOURCE_LENGTH(info); |
483 | acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), |
484 | total_length: aml_length, aml); |
485 | break; |
486 | |
487 | case ACPI_RSC_INITGET: |
488 | break; |
489 | |
490 | case ACPI_RSC_FLAGINIT: |
491 | /* |
492 | * Clear the flag byte |
493 | */ |
494 | ACPI_SET8(destination, 0); |
495 | break; |
496 | |
497 | case ACPI_RSC_1BITFLAG: |
498 | /* |
499 | * Mask and shift the flag bit |
500 | */ |
501 | ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) |
502 | ((ACPI_GET8(source) & 0x01) << info-> |
503 | value)); |
504 | break; |
505 | |
506 | case ACPI_RSC_2BITFLAG: |
507 | /* |
508 | * Mask and shift the flag bits |
509 | */ |
510 | ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) |
511 | ((ACPI_GET8(source) & 0x03) << info-> |
512 | value)); |
513 | break; |
514 | |
515 | case ACPI_RSC_3BITFLAG: |
516 | /* |
517 | * Mask and shift the flag bits |
518 | */ |
519 | ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) |
520 | ((ACPI_GET8(source) & 0x07) << info-> |
521 | value)); |
522 | break; |
523 | |
524 | case ACPI_RSC_6BITFLAG: |
525 | /* |
526 | * Mask and shift the flag bits |
527 | */ |
528 | ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) |
529 | ((ACPI_GET8(source) & 0x3F) << info-> |
530 | value)); |
531 | break; |
532 | |
533 | case ACPI_RSC_COUNT: |
534 | |
535 | item_count = ACPI_GET8(source); |
536 | ACPI_SET8(destination, item_count); |
537 | |
538 | aml_length = (u16) |
539 | (aml_length + (info->value * (item_count - 1))); |
540 | break; |
541 | |
542 | case ACPI_RSC_COUNT16: |
543 | |
544 | item_count = ACPI_GET16(source); |
545 | aml_length = (u16) (aml_length + item_count); |
546 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
547 | break; |
548 | |
549 | case ACPI_RSC_COUNT_GPIO_PIN: |
550 | |
551 | item_count = ACPI_GET16(source); |
552 | ACPI_SET16(destination, aml_length); |
553 | |
554 | aml_length = (u16)(aml_length + item_count * 2); |
555 | target = ACPI_ADD_PTR(void, aml, info->value); |
556 | ACPI_SET16(target, aml_length); |
557 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
558 | break; |
559 | |
560 | case ACPI_RSC_COUNT_GPIO_VEN: |
561 | |
562 | item_count = ACPI_GET16(source); |
563 | ACPI_SET16(destination, item_count); |
564 | |
565 | aml_length = |
566 | (u16)(aml_length + (info->value * item_count)); |
567 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
568 | break; |
569 | |
570 | case ACPI_RSC_COUNT_GPIO_RES: |
571 | |
572 | /* Set resource source string length */ |
573 | |
574 | item_count = ACPI_GET16(source); |
575 | ACPI_SET16(destination, aml_length); |
576 | |
577 | /* Compute offset for the Vendor Data */ |
578 | |
579 | aml_length = (u16)(aml_length + item_count); |
580 | target = ACPI_ADD_PTR(void, aml, info->value); |
581 | |
582 | /* Set vendor offset only if there is vendor data */ |
583 | |
584 | ACPI_SET16(target, aml_length); |
585 | |
586 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
587 | break; |
588 | |
589 | case ACPI_RSC_COUNT_SERIAL_VEN: |
590 | |
591 | item_count = ACPI_GET16(source); |
592 | ACPI_SET16(destination, item_count + info->value); |
593 | aml_length = (u16)(aml_length + item_count); |
594 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
595 | break; |
596 | |
597 | case ACPI_RSC_COUNT_SERIAL_RES: |
598 | |
599 | item_count = ACPI_GET16(source); |
600 | aml_length = (u16)(aml_length + item_count); |
601 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
602 | break; |
603 | |
604 | case ACPI_RSC_LENGTH: |
605 | |
606 | acpi_rs_set_resource_length(total_length: info->value, aml); |
607 | break; |
608 | |
609 | case ACPI_RSC_MOVE8: |
610 | case ACPI_RSC_MOVE16: |
611 | case ACPI_RSC_MOVE32: |
612 | case ACPI_RSC_MOVE64: |
613 | |
614 | if (info->value) { |
615 | item_count = info->value; |
616 | } |
617 | acpi_rs_move_data(destination, source, item_count, |
618 | move_type: info->opcode); |
619 | break; |
620 | |
621 | case ACPI_RSC_MOVE_GPIO_PIN: |
622 | |
623 | destination = (char *)ACPI_ADD_PTR(void, aml, |
624 | ACPI_GET16 |
625 | (destination)); |
626 | source = *(u16 **)source; |
627 | acpi_rs_move_data(destination, source, item_count, |
628 | move_type: info->opcode); |
629 | break; |
630 | |
631 | case ACPI_RSC_MOVE_GPIO_RES: |
632 | |
633 | /* Used for both resource_source string and vendor_data */ |
634 | |
635 | destination = (char *)ACPI_ADD_PTR(void, aml, |
636 | ACPI_GET16 |
637 | (destination)); |
638 | source = *(u8 **)source; |
639 | acpi_rs_move_data(destination, source, item_count, |
640 | move_type: info->opcode); |
641 | break; |
642 | |
643 | case ACPI_RSC_MOVE_SERIAL_VEN: |
644 | |
645 | destination = (char *)ACPI_ADD_PTR(void, aml, |
646 | (aml_length - |
647 | item_count)); |
648 | source = *(u8 **)source; |
649 | acpi_rs_move_data(destination, source, item_count, |
650 | move_type: info->opcode); |
651 | break; |
652 | |
653 | case ACPI_RSC_MOVE_SERIAL_RES: |
654 | |
655 | destination = (char *)ACPI_ADD_PTR(void, aml, |
656 | (aml_length - |
657 | item_count)); |
658 | source = *(u8 **)source; |
659 | acpi_rs_move_data(destination, source, item_count, |
660 | move_type: info->opcode); |
661 | break; |
662 | |
663 | case ACPI_RSC_ADDRESS: |
664 | |
665 | /* Set the Resource Type, General Flags, and Type-Specific Flags */ |
666 | |
667 | acpi_rs_set_address_common(aml, resource); |
668 | break; |
669 | |
670 | case ACPI_RSC_SOURCEX: |
671 | /* |
672 | * Optional resource_source (Index and String) |
673 | */ |
674 | aml_length = |
675 | acpi_rs_set_resource_source(aml, |
676 | minimum_length: (acpi_rs_length) |
677 | aml_length, resource_source: source); |
678 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
679 | break; |
680 | |
681 | case ACPI_RSC_SOURCE: |
682 | /* |
683 | * Optional resource_source (Index and String). This is the more |
684 | * complicated case used by the Interrupt() macro |
685 | */ |
686 | aml_length = |
687 | acpi_rs_set_resource_source(aml, minimum_length: info->value, |
688 | resource_source: source); |
689 | acpi_rs_set_resource_length(total_length: aml_length, aml); |
690 | break; |
691 | |
692 | case ACPI_RSC_BITMASK: |
693 | /* |
694 | * 8-bit encoded bitmask (DMA macro) |
695 | */ |
696 | ACPI_SET8(destination, |
697 | acpi_rs_encode_bitmask(source, |
698 | *ACPI_ADD_PTR(u8, |
699 | resource, |
700 | info-> |
701 | value))); |
702 | break; |
703 | |
704 | case ACPI_RSC_BITMASK16: |
705 | /* |
706 | * 16-bit encoded bitmask (IRQ macro) |
707 | */ |
708 | temp16 = |
709 | acpi_rs_encode_bitmask(list: source, |
710 | count: *ACPI_ADD_PTR(u8, resource, |
711 | info->value)); |
712 | ACPI_MOVE_16_TO_16(destination, &temp16); |
713 | break; |
714 | |
715 | case ACPI_RSC_EXIT_LE: |
716 | /* |
717 | * control - Exit conversion if less than or equal |
718 | */ |
719 | if (item_count <= info->value) { |
720 | goto exit; |
721 | } |
722 | break; |
723 | |
724 | case ACPI_RSC_EXIT_NE: |
725 | /* |
726 | * control - Exit conversion if not equal |
727 | */ |
728 | switch (COMPARE_OPCODE(info)) { |
729 | case ACPI_RSC_COMPARE_VALUE: |
730 | |
731 | if (*ACPI_ADD_PTR(u8, resource, |
732 | COMPARE_TARGET(info)) != |
733 | COMPARE_VALUE(info)) { |
734 | goto exit; |
735 | } |
736 | break; |
737 | |
738 | default: |
739 | |
740 | ACPI_ERROR((AE_INFO, |
741 | "Invalid conversion sub-opcode" )); |
742 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
743 | } |
744 | break; |
745 | |
746 | case ACPI_RSC_EXIT_EQ: |
747 | /* |
748 | * control - Exit conversion if equal |
749 | */ |
750 | if (*ACPI_ADD_PTR(u8, resource, |
751 | COMPARE_TARGET(info)) == |
752 | COMPARE_VALUE(info)) { |
753 | goto exit; |
754 | } |
755 | break; |
756 | |
757 | default: |
758 | |
759 | ACPI_ERROR((AE_INFO, "Invalid conversion opcode" )); |
760 | return_ACPI_STATUS(AE_BAD_PARAMETER); |
761 | } |
762 | |
763 | count--; |
764 | info++; |
765 | } |
766 | |
767 | exit: |
768 | return_ACPI_STATUS(AE_OK); |
769 | } |
770 | |
771 | #if 0 |
772 | /* Previous resource validations */ |
773 | |
774 | if (aml->ext_address64.revision_ID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { |
775 | return_ACPI_STATUS(AE_SUPPORT); |
776 | } |
777 | |
778 | if (resource->data.start_dpf.performance_robustness >= 3) { |
779 | return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); |
780 | } |
781 | |
782 | if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { |
783 | /* |
784 | * Only [active_high, edge_sensitive] or [active_low, level_sensitive] |
785 | * polarity/trigger interrupts are allowed (ACPI spec, section |
786 | * "IRQ Format"), so 0x00 and 0x09 are illegal. |
787 | */ |
788 | ACPI_ERROR((AE_INFO, |
789 | "Invalid interrupt polarity/trigger in resource list, 0x%X" , |
790 | aml->irq.flags)); |
791 | return_ACPI_STATUS(AE_BAD_DATA); |
792 | } |
793 | |
794 | resource->data.extended_irq.interrupt_count = temp8; |
795 | if (temp8 < 1) { |
796 | |
797 | /* Must have at least one IRQ */ |
798 | |
799 | return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); |
800 | } |
801 | |
802 | if (resource->data.dma.transfer == 0x03) { |
803 | ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)" )); |
804 | return_ACPI_STATUS(AE_BAD_DATA); |
805 | } |
806 | #endif |
807 | |