0001
0002
0003
0004
0005
0006
0007
0008 #include <acpi/acpi.h>
0009 #include "accommon.h"
0010 #include "acresrc.h"
0011
0012 #define _COMPONENT ACPI_RESOURCES
0013 ACPI_MODULE_NAME("rsmisc")
0014 #define INIT_RESOURCE_TYPE(i) i->resource_offset
0015 #define INIT_RESOURCE_LENGTH(i) i->aml_offset
0016 #define INIT_TABLE_LENGTH(i) i->value
0017 #define COMPARE_OPCODE(i) i->resource_offset
0018 #define COMPARE_TARGET(i) i->aml_offset
0019 #define COMPARE_VALUE(i) i->value
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034 acpi_status
0035 acpi_rs_convert_aml_to_resource(struct acpi_resource *resource,
0036 union aml_resource *aml,
0037 struct acpi_rsconvert_info *info)
0038 {
0039 acpi_rs_length aml_resource_length;
0040 void *source;
0041 void *destination;
0042 char *target;
0043 u8 count;
0044 u8 flags_mode = FALSE;
0045 u16 item_count = 0;
0046 u16 temp16 = 0;
0047
0048 ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource);
0049
0050 if (!info) {
0051 return_ACPI_STATUS(AE_BAD_PARAMETER);
0052 }
0053
0054 if (((acpi_size)resource) & 0x3) {
0055
0056
0057
0058 ACPI_WARNING((AE_INFO,
0059 "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u",
0060 resource, resource->type, resource->length));
0061 }
0062
0063
0064
0065 aml_resource_length = acpi_ut_get_resource_length(aml);
0066
0067
0068
0069
0070
0071 count = INIT_TABLE_LENGTH(info);
0072 while (count) {
0073 target = NULL;
0074
0075
0076
0077
0078
0079 source = ACPI_ADD_PTR(void, aml, info->aml_offset);
0080 destination =
0081 ACPI_ADD_PTR(void, resource, info->resource_offset);
0082
0083 switch (info->opcode) {
0084 case ACPI_RSC_INITGET:
0085
0086
0087
0088 memset(resource, 0, INIT_RESOURCE_LENGTH(info));
0089 resource->type = INIT_RESOURCE_TYPE(info);
0090 resource->length = INIT_RESOURCE_LENGTH(info);
0091 break;
0092
0093 case ACPI_RSC_INITSET:
0094 break;
0095
0096 case ACPI_RSC_FLAGINIT:
0097
0098 flags_mode = TRUE;
0099 break;
0100
0101 case ACPI_RSC_1BITFLAG:
0102
0103
0104
0105 ACPI_SET8(destination,
0106 ((ACPI_GET8(source) >> info->value) & 0x01));
0107 break;
0108
0109 case ACPI_RSC_2BITFLAG:
0110
0111
0112
0113 ACPI_SET8(destination,
0114 ((ACPI_GET8(source) >> info->value) & 0x03));
0115 break;
0116
0117 case ACPI_RSC_3BITFLAG:
0118
0119
0120
0121 ACPI_SET8(destination,
0122 ((ACPI_GET8(source) >> info->value) & 0x07));
0123 break;
0124
0125 case ACPI_RSC_6BITFLAG:
0126
0127
0128
0129 ACPI_SET8(destination,
0130 ((ACPI_GET8(source) >> info->value) & 0x3F));
0131 break;
0132
0133 case ACPI_RSC_COUNT:
0134
0135 item_count = ACPI_GET8(source);
0136 ACPI_SET8(destination, item_count);
0137
0138 resource->length = resource->length +
0139 (info->value * (item_count - 1));
0140 break;
0141
0142 case ACPI_RSC_COUNT16:
0143
0144 item_count = aml_resource_length;
0145 ACPI_SET16(destination, item_count);
0146
0147 resource->length = resource->length +
0148 (info->value * (item_count - 1));
0149 break;
0150
0151 case ACPI_RSC_COUNT_GPIO_PIN:
0152
0153 target = ACPI_ADD_PTR(void, aml, info->value);
0154 item_count = ACPI_GET16(target) - ACPI_GET16(source);
0155
0156 resource->length = resource->length + item_count;
0157 item_count = item_count / 2;
0158 ACPI_SET16(destination, item_count);
0159 break;
0160
0161 case ACPI_RSC_COUNT_GPIO_VEN:
0162
0163 item_count = ACPI_GET8(source);
0164 ACPI_SET8(destination, item_count);
0165
0166 resource->length =
0167 resource->length + (info->value * item_count);
0168 break;
0169
0170 case ACPI_RSC_COUNT_GPIO_RES:
0171
0172
0173
0174
0175 target = ACPI_ADD_PTR(void, aml, (info->value + 2));
0176 if (ACPI_GET16(target)) {
0177
0178
0179
0180 target = ACPI_ADD_PTR(void, aml, info->value);
0181 item_count =
0182 ACPI_GET16(target) - ACPI_GET16(source);
0183 } else {
0184
0185
0186 item_count = aml->large_header.resource_length +
0187 sizeof(struct aml_resource_large_header) -
0188 ACPI_GET16(source);
0189 }
0190
0191 resource->length = resource->length + item_count;
0192 ACPI_SET16(destination, item_count);
0193 break;
0194
0195 case ACPI_RSC_COUNT_SERIAL_VEN:
0196
0197 item_count = ACPI_GET16(source) - info->value;
0198
0199 resource->length = resource->length + item_count;
0200 ACPI_SET16(destination, item_count);
0201 break;
0202
0203 case ACPI_RSC_COUNT_SERIAL_RES:
0204
0205 item_count = (aml_resource_length +
0206 sizeof(struct aml_resource_large_header))
0207 - ACPI_GET16(source) - info->value;
0208
0209 resource->length = resource->length + item_count;
0210 ACPI_SET16(destination, item_count);
0211 break;
0212
0213 case ACPI_RSC_LENGTH:
0214
0215 resource->length = resource->length + info->value;
0216 break;
0217
0218 case ACPI_RSC_MOVE8:
0219 case ACPI_RSC_MOVE16:
0220 case ACPI_RSC_MOVE32:
0221 case ACPI_RSC_MOVE64:
0222
0223
0224
0225
0226 if (info->value) {
0227 item_count = info->value;
0228 }
0229 acpi_rs_move_data(destination, source, item_count,
0230 info->opcode);
0231 break;
0232
0233 case ACPI_RSC_MOVE_GPIO_PIN:
0234
0235
0236
0237 target = (char *)ACPI_ADD_PTR(void, resource,
0238 (resource->length -
0239 item_count * 2));
0240 *(u16 **)destination = ACPI_CAST_PTR(u16, target);
0241
0242
0243
0244 source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
0245 acpi_rs_move_data(target, source, item_count,
0246 info->opcode);
0247 break;
0248
0249 case ACPI_RSC_MOVE_GPIO_RES:
0250
0251
0252
0253 target = (char *)ACPI_ADD_PTR(void, resource,
0254 (resource->length -
0255 item_count));
0256 *(u8 **)destination = ACPI_CAST_PTR(u8, target);
0257
0258
0259
0260 source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source));
0261 acpi_rs_move_data(target, source, item_count,
0262 info->opcode);
0263 break;
0264
0265 case ACPI_RSC_MOVE_SERIAL_VEN:
0266
0267
0268
0269 target = (char *)ACPI_ADD_PTR(void, resource,
0270 (resource->length -
0271 item_count));
0272 *(u8 **)destination = ACPI_CAST_PTR(u8, target);
0273
0274
0275
0276 source = ACPI_ADD_PTR(void, aml, info->value);
0277 acpi_rs_move_data(target, source, item_count,
0278 info->opcode);
0279 break;
0280
0281 case ACPI_RSC_MOVE_SERIAL_RES:
0282
0283
0284
0285 target = (char *)ACPI_ADD_PTR(void, resource,
0286 (resource->length -
0287 item_count));
0288 *(u8 **)destination = ACPI_CAST_PTR(u8, target);
0289
0290
0291
0292 source =
0293 ACPI_ADD_PTR(void, aml,
0294 (ACPI_GET16(source) + info->value));
0295 acpi_rs_move_data(target, source, item_count,
0296 info->opcode);
0297 break;
0298
0299 case ACPI_RSC_SET8:
0300
0301 memset(destination, info->aml_offset, info->value);
0302 break;
0303
0304 case ACPI_RSC_DATA8:
0305
0306 target = ACPI_ADD_PTR(char, resource, info->value);
0307 memcpy(destination, source, ACPI_GET16(target));
0308 break;
0309
0310 case ACPI_RSC_ADDRESS:
0311
0312
0313
0314 if (!acpi_rs_get_address_common(resource, aml)) {
0315 return_ACPI_STATUS
0316 (AE_AML_INVALID_RESOURCE_TYPE);
0317 }
0318 break;
0319
0320 case ACPI_RSC_SOURCE:
0321
0322
0323
0324 resource->length +=
0325 acpi_rs_get_resource_source(aml_resource_length,
0326 info->value,
0327 destination, aml, NULL);
0328 break;
0329
0330 case ACPI_RSC_SOURCEX:
0331
0332
0333
0334
0335 target = ACPI_ADD_PTR(char, resource,
0336 info->aml_offset +
0337 (item_count * 4));
0338
0339 resource->length +=
0340 acpi_rs_get_resource_source(aml_resource_length,
0341 (acpi_rs_length)
0342 (((item_count -
0343 1) * sizeof(u32)) +
0344 info->value),
0345 destination, aml,
0346 target);
0347 break;
0348
0349 case ACPI_RSC_BITMASK:
0350
0351
0352
0353 item_count =
0354 acpi_rs_decode_bitmask(ACPI_GET8(source),
0355 destination);
0356 if (item_count) {
0357 resource->length += (item_count - 1);
0358 }
0359
0360 target = ACPI_ADD_PTR(char, resource, info->value);
0361 ACPI_SET8(target, item_count);
0362 break;
0363
0364 case ACPI_RSC_BITMASK16:
0365
0366
0367
0368 ACPI_MOVE_16_TO_16(&temp16, source);
0369
0370 item_count =
0371 acpi_rs_decode_bitmask(temp16, destination);
0372 if (item_count) {
0373 resource->length += (item_count - 1);
0374 }
0375
0376 target = ACPI_ADD_PTR(char, resource, info->value);
0377 ACPI_SET8(target, item_count);
0378 break;
0379
0380 case ACPI_RSC_EXIT_NE:
0381
0382
0383
0384 switch (info->resource_offset) {
0385 case ACPI_RSC_COMPARE_AML_LENGTH:
0386
0387 if (aml_resource_length != info->value) {
0388 goto exit;
0389 }
0390 break;
0391
0392 case ACPI_RSC_COMPARE_VALUE:
0393
0394 if (ACPI_GET8(source) != info->value) {
0395 goto exit;
0396 }
0397 break;
0398
0399 default:
0400
0401 ACPI_ERROR((AE_INFO,
0402 "Invalid conversion sub-opcode"));
0403 return_ACPI_STATUS(AE_BAD_PARAMETER);
0404 }
0405 break;
0406
0407 default:
0408
0409 ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
0410 return_ACPI_STATUS(AE_BAD_PARAMETER);
0411 }
0412
0413 count--;
0414 info++;
0415 }
0416
0417 exit:
0418 if (!flags_mode) {
0419
0420
0421
0422 resource->length = (u32)
0423 ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length);
0424 }
0425 return_ACPI_STATUS(AE_OK);
0426 }
0427
0428
0429
0430
0431
0432
0433
0434
0435
0436
0437
0438
0439
0440
0441
0442
0443 acpi_status
0444 acpi_rs_convert_resource_to_aml(struct acpi_resource *resource,
0445 union aml_resource *aml,
0446 struct acpi_rsconvert_info *info)
0447 {
0448 void *source = NULL;
0449 void *destination;
0450 char *target;
0451 acpi_rsdesc_size aml_length = 0;
0452 u8 count;
0453 u16 temp16 = 0;
0454 u16 item_count = 0;
0455
0456 ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml);
0457
0458 if (!info) {
0459 return_ACPI_STATUS(AE_BAD_PARAMETER);
0460 }
0461
0462
0463
0464
0465
0466 count = INIT_TABLE_LENGTH(info);
0467
0468 while (count) {
0469
0470
0471
0472
0473 source = ACPI_ADD_PTR(void, resource, info->resource_offset);
0474 destination = ACPI_ADD_PTR(void, aml, info->aml_offset);
0475
0476 switch (info->opcode) {
0477 case ACPI_RSC_INITSET:
0478
0479 memset(aml, 0, INIT_RESOURCE_LENGTH(info));
0480 aml_length = INIT_RESOURCE_LENGTH(info);
0481 acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info),
0482 aml_length, aml);
0483 break;
0484
0485 case ACPI_RSC_INITGET:
0486 break;
0487
0488 case ACPI_RSC_FLAGINIT:
0489
0490
0491
0492 ACPI_SET8(destination, 0);
0493 break;
0494
0495 case ACPI_RSC_1BITFLAG:
0496
0497
0498
0499 ACPI_SET_BIT(*ACPI_CAST8(destination), (u8)
0500 ((ACPI_GET8(source) & 0x01) << info->
0501 value));
0502 break;
0503
0504 case ACPI_RSC_2BITFLAG:
0505
0506
0507
0508 ACPI_SET_BIT(*ACPI_CAST8(destination), (u8)
0509 ((ACPI_GET8(source) & 0x03) << info->
0510 value));
0511 break;
0512
0513 case ACPI_RSC_3BITFLAG:
0514
0515
0516
0517 ACPI_SET_BIT(*ACPI_CAST8(destination), (u8)
0518 ((ACPI_GET8(source) & 0x07) << info->
0519 value));
0520 break;
0521
0522 case ACPI_RSC_6BITFLAG:
0523
0524
0525
0526 ACPI_SET_BIT(*ACPI_CAST8(destination), (u8)
0527 ((ACPI_GET8(source) & 0x3F) << info->
0528 value));
0529 break;
0530
0531 case ACPI_RSC_COUNT:
0532
0533 item_count = ACPI_GET8(source);
0534 ACPI_SET8(destination, item_count);
0535
0536 aml_length = (u16)
0537 (aml_length + (info->value * (item_count - 1)));
0538 break;
0539
0540 case ACPI_RSC_COUNT16:
0541
0542 item_count = ACPI_GET16(source);
0543 aml_length = (u16) (aml_length + item_count);
0544 acpi_rs_set_resource_length(aml_length, aml);
0545 break;
0546
0547 case ACPI_RSC_COUNT_GPIO_PIN:
0548
0549 item_count = ACPI_GET16(source);
0550 ACPI_SET16(destination, aml_length);
0551
0552 aml_length = (u16)(aml_length + item_count * 2);
0553 target = ACPI_ADD_PTR(void, aml, info->value);
0554 ACPI_SET16(target, aml_length);
0555 acpi_rs_set_resource_length(aml_length, aml);
0556 break;
0557
0558 case ACPI_RSC_COUNT_GPIO_VEN:
0559
0560 item_count = ACPI_GET16(source);
0561 ACPI_SET16(destination, item_count);
0562
0563 aml_length =
0564 (u16)(aml_length + (info->value * item_count));
0565 acpi_rs_set_resource_length(aml_length, aml);
0566 break;
0567
0568 case ACPI_RSC_COUNT_GPIO_RES:
0569
0570
0571
0572 item_count = ACPI_GET16(source);
0573 ACPI_SET16(destination, aml_length);
0574
0575
0576
0577 aml_length = (u16)(aml_length + item_count);
0578 target = ACPI_ADD_PTR(void, aml, info->value);
0579
0580
0581
0582 ACPI_SET16(target, aml_length);
0583
0584 acpi_rs_set_resource_length(aml_length, aml);
0585 break;
0586
0587 case ACPI_RSC_COUNT_SERIAL_VEN:
0588
0589 item_count = ACPI_GET16(source);
0590 ACPI_SET16(destination, item_count + info->value);
0591 aml_length = (u16)(aml_length + item_count);
0592 acpi_rs_set_resource_length(aml_length, aml);
0593 break;
0594
0595 case ACPI_RSC_COUNT_SERIAL_RES:
0596
0597 item_count = ACPI_GET16(source);
0598 aml_length = (u16)(aml_length + item_count);
0599 acpi_rs_set_resource_length(aml_length, aml);
0600 break;
0601
0602 case ACPI_RSC_LENGTH:
0603
0604 acpi_rs_set_resource_length(info->value, aml);
0605 break;
0606
0607 case ACPI_RSC_MOVE8:
0608 case ACPI_RSC_MOVE16:
0609 case ACPI_RSC_MOVE32:
0610 case ACPI_RSC_MOVE64:
0611
0612 if (info->value) {
0613 item_count = info->value;
0614 }
0615 acpi_rs_move_data(destination, source, item_count,
0616 info->opcode);
0617 break;
0618
0619 case ACPI_RSC_MOVE_GPIO_PIN:
0620
0621 destination = (char *)ACPI_ADD_PTR(void, aml,
0622 ACPI_GET16
0623 (destination));
0624 source = *(u16 **)source;
0625 acpi_rs_move_data(destination, source, item_count,
0626 info->opcode);
0627 break;
0628
0629 case ACPI_RSC_MOVE_GPIO_RES:
0630
0631
0632
0633 destination = (char *)ACPI_ADD_PTR(void, aml,
0634 ACPI_GET16
0635 (destination));
0636 source = *(u8 **)source;
0637 acpi_rs_move_data(destination, source, item_count,
0638 info->opcode);
0639 break;
0640
0641 case ACPI_RSC_MOVE_SERIAL_VEN:
0642
0643 destination = (char *)ACPI_ADD_PTR(void, aml,
0644 (aml_length -
0645 item_count));
0646 source = *(u8 **)source;
0647 acpi_rs_move_data(destination, source, item_count,
0648 info->opcode);
0649 break;
0650
0651 case ACPI_RSC_MOVE_SERIAL_RES:
0652
0653 destination = (char *)ACPI_ADD_PTR(void, aml,
0654 (aml_length -
0655 item_count));
0656 source = *(u8 **)source;
0657 acpi_rs_move_data(destination, source, item_count,
0658 info->opcode);
0659 break;
0660
0661 case ACPI_RSC_ADDRESS:
0662
0663
0664
0665 acpi_rs_set_address_common(aml, resource);
0666 break;
0667
0668 case ACPI_RSC_SOURCEX:
0669
0670
0671
0672 aml_length =
0673 acpi_rs_set_resource_source(aml,
0674 (acpi_rs_length)
0675 aml_length, source);
0676 acpi_rs_set_resource_length(aml_length, aml);
0677 break;
0678
0679 case ACPI_RSC_SOURCE:
0680
0681
0682
0683
0684 aml_length =
0685 acpi_rs_set_resource_source(aml, info->value,
0686 source);
0687 acpi_rs_set_resource_length(aml_length, aml);
0688 break;
0689
0690 case ACPI_RSC_BITMASK:
0691
0692
0693
0694 ACPI_SET8(destination,
0695 acpi_rs_encode_bitmask(source,
0696 *ACPI_ADD_PTR(u8,
0697 resource,
0698 info->
0699 value)));
0700 break;
0701
0702 case ACPI_RSC_BITMASK16:
0703
0704
0705
0706 temp16 =
0707 acpi_rs_encode_bitmask(source,
0708 *ACPI_ADD_PTR(u8, resource,
0709 info->value));
0710 ACPI_MOVE_16_TO_16(destination, &temp16);
0711 break;
0712
0713 case ACPI_RSC_EXIT_LE:
0714
0715
0716
0717 if (item_count <= info->value) {
0718 goto exit;
0719 }
0720 break;
0721
0722 case ACPI_RSC_EXIT_NE:
0723
0724
0725
0726 switch (COMPARE_OPCODE(info)) {
0727 case ACPI_RSC_COMPARE_VALUE:
0728
0729 if (*ACPI_ADD_PTR(u8, resource,
0730 COMPARE_TARGET(info)) !=
0731 COMPARE_VALUE(info)) {
0732 goto exit;
0733 }
0734 break;
0735
0736 default:
0737
0738 ACPI_ERROR((AE_INFO,
0739 "Invalid conversion sub-opcode"));
0740 return_ACPI_STATUS(AE_BAD_PARAMETER);
0741 }
0742 break;
0743
0744 case ACPI_RSC_EXIT_EQ:
0745
0746
0747
0748 if (*ACPI_ADD_PTR(u8, resource,
0749 COMPARE_TARGET(info)) ==
0750 COMPARE_VALUE(info)) {
0751 goto exit;
0752 }
0753 break;
0754
0755 default:
0756
0757 ACPI_ERROR((AE_INFO, "Invalid conversion opcode"));
0758 return_ACPI_STATUS(AE_BAD_PARAMETER);
0759 }
0760
0761 count--;
0762 info++;
0763 }
0764
0765 exit:
0766 return_ACPI_STATUS(AE_OK);
0767 }
0768
0769 #if 0
0770
0771
0772 if (aml->ext_address64.revision_ID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) {
0773 return_ACPI_STATUS(AE_SUPPORT);
0774 }
0775
0776 if (resource->data.start_dpf.performance_robustness >= 3) {
0777 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE);
0778 }
0779
0780 if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) {
0781
0782
0783
0784
0785
0786 ACPI_ERROR((AE_INFO,
0787 "Invalid interrupt polarity/trigger in resource list, 0x%X",
0788 aml->irq.flags));
0789 return_ACPI_STATUS(AE_BAD_DATA);
0790 }
0791
0792 resource->data.extended_irq.interrupt_count = temp8;
0793 if (temp8 < 1) {
0794
0795
0796
0797 return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH);
0798 }
0799
0800 if (resource->data.dma.transfer == 0x03) {
0801 ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)"));
0802 return_ACPI_STATUS(AE_BAD_DATA);
0803 }
0804 #endif