1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44#include <acpi/acpi.h>
45#include "accommon.h"
46#include "acresrc.h"
47#include "acnamesp.h"
48
49#define _COMPONENT ACPI_RESOURCES
50ACPI_MODULE_NAME("rscalc")
51
52
53static u8 acpi_rs_count_set_bits(u16 bit_field);
54
55static acpi_rs_length
56acpi_rs_struct_option_length(struct acpi_resource_source *resource_source);
57
58static u32
59acpi_rs_stream_option_length(u32 resource_length, u32 minimum_total_length);
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74static u8 acpi_rs_count_set_bits(u16 bit_field)
75{
76 u8 bits_set;
77
78 ACPI_FUNCTION_ENTRY();
79
80 for (bits_set = 0; bit_field; bits_set++) {
81
82
83
84 bit_field &= (u16) (bit_field - 1);
85 }
86
87 return (bits_set);
88}
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104static acpi_rs_length
105acpi_rs_struct_option_length(struct acpi_resource_source *resource_source)
106{
107 ACPI_FUNCTION_ENTRY();
108
109
110
111
112
113
114 if (resource_source->string_ptr) {
115 return ((acpi_rs_length) (resource_source->string_length + 1));
116 }
117
118 return (0);
119}
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137static u32
138acpi_rs_stream_option_length(u32 resource_length,
139 u32 minimum_aml_resource_length)
140{
141 u32 string_length = 0;
142
143 ACPI_FUNCTION_ENTRY();
144
145
146
147
148
149
150
151
152
153
154
155
156
157 if (resource_length > minimum_aml_resource_length) {
158
159
160
161 string_length =
162 resource_length - minimum_aml_resource_length - 1;
163 }
164
165
166
167
168
169 return ((u32) ACPI_ROUND_UP_TO_NATIVE_WORD(string_length));
170}
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187acpi_status
188acpi_rs_get_aml_length(struct acpi_resource * resource, acpi_size * size_needed)
189{
190 acpi_size aml_size_needed = 0;
191 acpi_rs_length total_size;
192
193 ACPI_FUNCTION_TRACE(rs_get_aml_length);
194
195
196
197 while (resource) {
198
199
200
201 if (resource->type > ACPI_RESOURCE_TYPE_MAX) {
202 return_ACPI_STATUS(AE_AML_INVALID_RESOURCE_TYPE);
203 }
204
205
206
207 if (!resource->length) {
208 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
209 }
210
211
212
213 total_size = acpi_gbl_aml_resource_sizes[resource->type];
214
215
216
217
218
219 switch (resource->type) {
220 case ACPI_RESOURCE_TYPE_IRQ:
221
222
223
224 if (resource->data.irq.descriptor_length == 2) {
225 total_size--;
226 }
227 break;
228
229 case ACPI_RESOURCE_TYPE_START_DEPENDENT:
230
231
232
233 if (resource->data.irq.descriptor_length == 0) {
234 total_size--;
235 }
236 break;
237
238 case ACPI_RESOURCE_TYPE_VENDOR:
239
240
241
242
243
244
245 if (resource->data.vendor.byte_length > 7) {
246
247
248
249 total_size =
250 sizeof(struct aml_resource_large_header);
251 }
252
253
254
255 total_size = (acpi_rs_length)
256 (total_size + resource->data.vendor.byte_length);
257 break;
258
259 case ACPI_RESOURCE_TYPE_END_TAG:
260
261
262
263
264 *size_needed = aml_size_needed + total_size;
265
266
267
268 return_ACPI_STATUS(AE_OK);
269
270 case ACPI_RESOURCE_TYPE_ADDRESS16:
271
272
273
274
275 total_size = (acpi_rs_length)
276 (total_size +
277 acpi_rs_struct_option_length(&resource->data.
278 address16.
279 resource_source));
280 break;
281
282 case ACPI_RESOURCE_TYPE_ADDRESS32:
283
284
285
286
287 total_size = (acpi_rs_length)
288 (total_size +
289 acpi_rs_struct_option_length(&resource->data.
290 address32.
291 resource_source));
292 break;
293
294 case ACPI_RESOURCE_TYPE_ADDRESS64:
295
296
297
298
299 total_size = (acpi_rs_length)
300 (total_size +
301 acpi_rs_struct_option_length(&resource->data.
302 address64.
303 resource_source));
304 break;
305
306 case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
307
308
309
310
311
312 total_size = (acpi_rs_length)
313 (total_size +
314 ((resource->data.extended_irq.interrupt_count -
315 1) * 4) +
316
317 acpi_rs_struct_option_length(&resource->data.
318 extended_irq.
319 resource_source));
320 break;
321
322 case ACPI_RESOURCE_TYPE_GPIO:
323
324 total_size =
325 (acpi_rs_length) (total_size +
326 (resource->data.gpio.
327 pin_table_length * 2) +
328 resource->data.gpio.
329 resource_source.string_length +
330 resource->data.gpio.
331 vendor_length);
332
333 break;
334
335 case ACPI_RESOURCE_TYPE_SERIAL_BUS:
336
337 total_size =
338 acpi_gbl_aml_resource_serial_bus_sizes[resource->
339 data.
340 common_serial_bus.
341 type];
342
343 total_size = (acpi_rs_length) (total_size +
344 resource->data.
345 i2c_serial_bus.
346 resource_source.
347 string_length +
348 resource->data.
349 i2c_serial_bus.
350 vendor_length);
351
352 break;
353
354 default:
355
356 break;
357 }
358
359
360
361 aml_size_needed += total_size;
362
363
364
365 resource =
366 ACPI_ADD_PTR(struct acpi_resource, resource,
367 resource->length);
368 }
369
370
371
372 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
373}
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391acpi_status
392acpi_rs_get_list_length(u8 * aml_buffer,
393 u32 aml_buffer_length, acpi_size * size_needed)
394{
395 acpi_status status;
396 u8 *end_aml;
397 u8 *buffer;
398 u32 buffer_size;
399 u16 temp16;
400 u16 resource_length;
401 u32 extra_struct_bytes;
402 u8 resource_index;
403 u8 minimum_aml_resource_length;
404 union aml_resource *aml_resource;
405
406 ACPI_FUNCTION_TRACE(rs_get_list_length);
407
408 *size_needed = ACPI_RS_SIZE_MIN;
409 end_aml = aml_buffer + aml_buffer_length;
410
411
412
413 while (aml_buffer < end_aml) {
414
415
416
417 status =
418 acpi_ut_validate_resource(NULL, aml_buffer,
419 &resource_index);
420 if (ACPI_FAILURE(status)) {
421
422
423
424
425 return_ACPI_STATUS(status);
426 }
427
428 aml_resource = (void *)aml_buffer;
429
430
431
432 resource_length = acpi_ut_get_resource_length(aml_buffer);
433 minimum_aml_resource_length =
434 acpi_gbl_resource_aml_sizes[resource_index];
435
436
437
438
439
440 extra_struct_bytes = 0;
441 buffer =
442 aml_buffer + acpi_ut_get_resource_header_length(aml_buffer);
443
444 switch (acpi_ut_get_resource_type(aml_buffer)) {
445 case ACPI_RESOURCE_NAME_IRQ:
446
447
448
449
450 ACPI_MOVE_16_TO_16(&temp16, buffer);
451 extra_struct_bytes = acpi_rs_count_set_bits(temp16);
452 break;
453
454 case ACPI_RESOURCE_NAME_DMA:
455
456
457
458
459 extra_struct_bytes = acpi_rs_count_set_bits(*buffer);
460 break;
461
462 case ACPI_RESOURCE_NAME_VENDOR_SMALL:
463 case ACPI_RESOURCE_NAME_VENDOR_LARGE:
464
465
466
467
468 extra_struct_bytes = resource_length;
469
470
471
472
473
474
475 if (extra_struct_bytes) {
476 extra_struct_bytes--;
477 }
478 break;
479
480 case ACPI_RESOURCE_NAME_END_TAG:
481
482
483
484 return_ACPI_STATUS(AE_OK);
485
486 case ACPI_RESOURCE_NAME_ADDRESS32:
487 case ACPI_RESOURCE_NAME_ADDRESS16:
488 case ACPI_RESOURCE_NAME_ADDRESS64:
489
490
491
492
493 extra_struct_bytes =
494 acpi_rs_stream_option_length(resource_length,
495 minimum_aml_resource_length);
496 break;
497
498 case ACPI_RESOURCE_NAME_EXTENDED_IRQ:
499
500
501
502
503
504
505 extra_struct_bytes = (buffer[1] - 1) * sizeof(u32);
506
507
508
509 extra_struct_bytes +=
510 acpi_rs_stream_option_length(resource_length -
511 extra_struct_bytes,
512 minimum_aml_resource_length);
513 break;
514
515 case ACPI_RESOURCE_NAME_GPIO:
516
517
518
519 if (aml_resource->gpio.vendor_length) {
520 extra_struct_bytes +=
521 aml_resource->gpio.vendor_offset -
522 aml_resource->gpio.pin_table_offset +
523 aml_resource->gpio.vendor_length;
524 } else {
525 extra_struct_bytes +=
526 aml_resource->large_header.resource_length +
527 sizeof(struct aml_resource_large_header) -
528 aml_resource->gpio.pin_table_offset;
529 }
530 break;
531
532 case ACPI_RESOURCE_NAME_SERIAL_BUS:
533
534 minimum_aml_resource_length =
535 acpi_gbl_resource_aml_serial_bus_sizes
536 [aml_resource->common_serial_bus.type];
537 extra_struct_bytes +=
538 aml_resource->common_serial_bus.resource_length -
539 minimum_aml_resource_length;
540 break;
541
542 default:
543
544 break;
545 }
546
547
548
549
550
551
552
553 if (acpi_ut_get_resource_type(aml_buffer) ==
554 ACPI_RESOURCE_NAME_SERIAL_BUS) {
555 buffer_size =
556 acpi_gbl_resource_struct_serial_bus_sizes
557 [aml_resource->common_serial_bus.type] +
558 extra_struct_bytes;
559 } else {
560 buffer_size =
561 acpi_gbl_resource_struct_sizes[resource_index] +
562 extra_struct_bytes;
563 }
564 buffer_size = (u32)ACPI_ROUND_UP_TO_NATIVE_WORD(buffer_size);
565
566 *size_needed += buffer_size;
567
568 ACPI_DEBUG_PRINT((ACPI_DB_RESOURCES,
569 "Type %.2X, AmlLength %.2X InternalLength %.2X\n",
570 acpi_ut_get_resource_type(aml_buffer),
571 acpi_ut_get_descriptor_length(aml_buffer),
572 buffer_size));
573
574
575
576
577
578 aml_buffer += acpi_ut_get_descriptor_length(aml_buffer);
579 }
580
581
582
583 return_ACPI_STATUS(AE_AML_NO_RESOURCE_END_TAG);
584}
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603acpi_status
604acpi_rs_get_pci_routing_table_length(union acpi_operand_object *package_object,
605 acpi_size * buffer_size_needed)
606{
607 u32 number_of_elements;
608 acpi_size temp_size_needed = 0;
609 union acpi_operand_object **top_object_list;
610 u32 index;
611 union acpi_operand_object *package_element;
612 union acpi_operand_object **sub_object_list;
613 u8 name_found;
614 u32 table_index;
615
616 ACPI_FUNCTION_TRACE(rs_get_pci_routing_table_length);
617
618 number_of_elements = package_object->package.count;
619
620
621
622
623
624
625
626
627
628
629
630 top_object_list = package_object->package.elements;
631
632 for (index = 0; index < number_of_elements; index++) {
633
634
635
636 package_element = *top_object_list;
637
638
639
640 if (!package_element ||
641 (package_element->common.type != ACPI_TYPE_PACKAGE)) {
642 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
643 }
644
645
646
647
648
649 sub_object_list = package_element->package.elements;
650
651
652
653 name_found = FALSE;
654
655 for (table_index = 0;
656 table_index < package_element->package.count
657 && !name_found; table_index++) {
658 if (*sub_object_list &&
659 ((ACPI_TYPE_STRING ==
660 (*sub_object_list)->common.type) ||
661 ((ACPI_TYPE_LOCAL_REFERENCE ==
662 (*sub_object_list)->common.type) &&
663 ((*sub_object_list)->reference.class ==
664 ACPI_REFCLASS_NAME)))) {
665 name_found = TRUE;
666 } else {
667
668
669 sub_object_list++;
670 }
671 }
672
673 temp_size_needed += (sizeof(struct acpi_pci_routing_table) - 4);
674
675
676
677 if (name_found) {
678 if ((*sub_object_list)->common.type == ACPI_TYPE_STRING) {
679
680
681
682
683 temp_size_needed += ((acpi_size)
684 (*sub_object_list)->string.
685 length + 1);
686 } else {
687 temp_size_needed += acpi_ns_get_pathname_length((*sub_object_list)->reference.node);
688 }
689 } else {
690
691
692
693
694 temp_size_needed += sizeof(u32);
695 }
696
697
698
699 temp_size_needed = ACPI_ROUND_UP_TO_64BIT(temp_size_needed);
700
701
702
703 top_object_list++;
704 }
705
706
707
708
709
710 *buffer_size_needed =
711 temp_size_needed + sizeof(struct acpi_pci_routing_table);
712 return_ACPI_STATUS(AE_OK);
713}
714