0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012 #include "acnamesp.h"
0013
0014
0015 #define _COMPONENT ACPI_UTILITIES
0016 ACPI_MODULE_NAME("utcopy")
0017
0018
0019 static acpi_status
0020 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
0021 union acpi_object *external_object,
0022 u8 *data_space, acpi_size *buffer_space_used);
0023
0024 static acpi_status
0025 acpi_ut_copy_ielement_to_ielement(u8 object_type,
0026 union acpi_operand_object *source_object,
0027 union acpi_generic_state *state,
0028 void *context);
0029
0030 static acpi_status
0031 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
0032 u8 *buffer, acpi_size *space_used);
0033
0034 static acpi_status
0035 acpi_ut_copy_esimple_to_isimple(union acpi_object *user_obj,
0036 union acpi_operand_object **return_obj);
0037
0038 static acpi_status
0039 acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
0040 union acpi_operand_object **internal_object);
0041
0042 static acpi_status
0043 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
0044 union acpi_operand_object *dest_desc);
0045
0046 static acpi_status
0047 acpi_ut_copy_ielement_to_eelement(u8 object_type,
0048 union acpi_operand_object *source_object,
0049 union acpi_generic_state *state,
0050 void *context);
0051
0052 static acpi_status
0053 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
0054 union acpi_operand_object *dest_obj,
0055 struct acpi_walk_state *walk_state);
0056
0057
0058
0059
0060
0061
0062
0063
0064
0065
0066
0067
0068
0069
0070
0071
0072
0073
0074
0075
0076
0077 static acpi_status
0078 acpi_ut_copy_isimple_to_esimple(union acpi_operand_object *internal_object,
0079 union acpi_object *external_object,
0080 u8 *data_space, acpi_size *buffer_space_used)
0081 {
0082 acpi_status status = AE_OK;
0083
0084 ACPI_FUNCTION_TRACE(ut_copy_isimple_to_esimple);
0085
0086 *buffer_space_used = 0;
0087
0088
0089
0090
0091
0092 if (!internal_object) {
0093 return_ACPI_STATUS(AE_OK);
0094 }
0095
0096
0097
0098 memset(external_object, 0, sizeof(union acpi_object));
0099
0100
0101
0102
0103
0104 external_object->type = internal_object->common.type;
0105
0106
0107
0108 switch (internal_object->common.type) {
0109 case ACPI_TYPE_STRING:
0110
0111 external_object->string.pointer = (char *)data_space;
0112 external_object->string.length = internal_object->string.length;
0113 *buffer_space_used = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
0114 internal_object->
0115 string.
0116 length + 1);
0117
0118 memcpy((void *)data_space,
0119 (void *)internal_object->string.pointer,
0120 (acpi_size)internal_object->string.length + 1);
0121 break;
0122
0123 case ACPI_TYPE_BUFFER:
0124
0125 external_object->buffer.pointer = data_space;
0126 external_object->buffer.length = internal_object->buffer.length;
0127 *buffer_space_used =
0128 ACPI_ROUND_UP_TO_NATIVE_WORD(internal_object->string.
0129 length);
0130
0131 memcpy((void *)data_space,
0132 (void *)internal_object->buffer.pointer,
0133 internal_object->buffer.length);
0134 break;
0135
0136 case ACPI_TYPE_INTEGER:
0137
0138 external_object->integer.value = internal_object->integer.value;
0139 break;
0140
0141 case ACPI_TYPE_LOCAL_REFERENCE:
0142
0143
0144
0145 switch (internal_object->reference.class) {
0146 case ACPI_REFCLASS_NAME:
0147
0148
0149
0150
0151 external_object->reference.handle =
0152 internal_object->reference.node;
0153 external_object->reference.actual_type =
0154 acpi_ns_get_type(internal_object->reference.node);
0155 break;
0156
0157 default:
0158
0159
0160
0161 return_ACPI_STATUS(AE_TYPE);
0162 }
0163 break;
0164
0165 case ACPI_TYPE_PROCESSOR:
0166
0167 external_object->processor.proc_id =
0168 internal_object->processor.proc_id;
0169 external_object->processor.pblk_address =
0170 internal_object->processor.address;
0171 external_object->processor.pblk_length =
0172 internal_object->processor.length;
0173 break;
0174
0175 case ACPI_TYPE_POWER:
0176
0177 external_object->power_resource.system_level =
0178 internal_object->power_resource.system_level;
0179
0180 external_object->power_resource.resource_order =
0181 internal_object->power_resource.resource_order;
0182 break;
0183
0184 default:
0185
0186
0187
0188 ACPI_ERROR((AE_INFO,
0189 "Unsupported object type, cannot convert to external object: %s",
0190 acpi_ut_get_type_name(internal_object->common.
0191 type)));
0192
0193 return_ACPI_STATUS(AE_SUPPORT);
0194 }
0195
0196 return_ACPI_STATUS(status);
0197 }
0198
0199
0200
0201
0202
0203
0204
0205
0206
0207
0208
0209
0210
0211 static acpi_status
0212 acpi_ut_copy_ielement_to_eelement(u8 object_type,
0213 union acpi_operand_object *source_object,
0214 union acpi_generic_state *state,
0215 void *context)
0216 {
0217 acpi_status status = AE_OK;
0218 struct acpi_pkg_info *info = (struct acpi_pkg_info *)context;
0219 acpi_size object_space;
0220 u32 this_index;
0221 union acpi_object *target_object;
0222
0223 ACPI_FUNCTION_ENTRY();
0224
0225 this_index = state->pkg.index;
0226 target_object = (union acpi_object *)&((union acpi_object *)
0227 (state->pkg.dest_object))->
0228 package.elements[this_index];
0229
0230 switch (object_type) {
0231 case ACPI_COPY_TYPE_SIMPLE:
0232
0233
0234
0235 status = acpi_ut_copy_isimple_to_esimple(source_object,
0236 target_object,
0237 info->free_space,
0238 &object_space);
0239 if (ACPI_FAILURE(status)) {
0240 return (status);
0241 }
0242 break;
0243
0244 case ACPI_COPY_TYPE_PACKAGE:
0245
0246
0247
0248 target_object->type = ACPI_TYPE_PACKAGE;
0249 target_object->package.count = source_object->package.count;
0250 target_object->package.elements =
0251 ACPI_CAST_PTR(union acpi_object, info->free_space);
0252
0253
0254
0255
0256 state->pkg.this_target_obj = target_object;
0257
0258
0259
0260
0261
0262 object_space = ACPI_ROUND_UP_TO_NATIVE_WORD((acpi_size)
0263 target_object->
0264 package.count *
0265 sizeof(union
0266 acpi_object));
0267 break;
0268
0269 default:
0270
0271 return (AE_BAD_PARAMETER);
0272 }
0273
0274 info->free_space += object_space;
0275 info->length += object_space;
0276 return (status);
0277 }
0278
0279
0280
0281
0282
0283
0284
0285
0286
0287
0288
0289
0290
0291
0292
0293
0294
0295
0296
0297
0298 static acpi_status
0299 acpi_ut_copy_ipackage_to_epackage(union acpi_operand_object *internal_object,
0300 u8 *buffer, acpi_size *space_used)
0301 {
0302 union acpi_object *external_object;
0303 acpi_status status;
0304 struct acpi_pkg_info info;
0305
0306 ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_epackage);
0307
0308
0309
0310
0311 external_object = ACPI_CAST_PTR(union acpi_object, buffer);
0312
0313
0314
0315
0316 info.length = ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
0317 info.free_space = buffer +
0318 ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
0319 info.object_space = 0;
0320 info.num_packages = 1;
0321
0322 external_object->type = internal_object->common.type;
0323 external_object->package.count = internal_object->package.count;
0324 external_object->package.elements =
0325 ACPI_CAST_PTR(union acpi_object, info.free_space);
0326
0327
0328
0329
0330
0331 info.length += (acpi_size)external_object->package.count *
0332 ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
0333 info.free_space += external_object->package.count *
0334 ACPI_ROUND_UP_TO_NATIVE_WORD(sizeof(union acpi_object));
0335
0336 status = acpi_ut_walk_package_tree(internal_object, external_object,
0337 acpi_ut_copy_ielement_to_eelement,
0338 &info);
0339
0340 *space_used = info.length;
0341 return_ACPI_STATUS(status);
0342 }
0343
0344
0345
0346
0347
0348
0349
0350
0351
0352
0353
0354
0355
0356
0357
0358 acpi_status
0359 acpi_ut_copy_iobject_to_eobject(union acpi_operand_object *internal_object,
0360 struct acpi_buffer *ret_buffer)
0361 {
0362 acpi_status status;
0363
0364 ACPI_FUNCTION_TRACE(ut_copy_iobject_to_eobject);
0365
0366 if (internal_object->common.type == ACPI_TYPE_PACKAGE) {
0367
0368
0369
0370
0371 status = acpi_ut_copy_ipackage_to_epackage(internal_object,
0372 ret_buffer->pointer,
0373 &ret_buffer->length);
0374 } else {
0375
0376
0377
0378 status = acpi_ut_copy_isimple_to_esimple(internal_object,
0379 ACPI_CAST_PTR(union
0380 acpi_object,
0381 ret_buffer->
0382 pointer),
0383 ACPI_ADD_PTR(u8,
0384 ret_buffer->
0385 pointer,
0386 ACPI_ROUND_UP_TO_NATIVE_WORD
0387 (sizeof
0388 (union
0389 acpi_object))),
0390 &ret_buffer->length);
0391
0392
0393
0394
0395 ret_buffer->length += sizeof(union acpi_object);
0396 }
0397
0398 return_ACPI_STATUS(status);
0399 }
0400
0401
0402
0403
0404
0405
0406
0407
0408
0409
0410
0411
0412
0413
0414
0415
0416
0417 static acpi_status
0418 acpi_ut_copy_esimple_to_isimple(union acpi_object *external_object,
0419 union acpi_operand_object **ret_internal_object)
0420 {
0421 union acpi_operand_object *internal_object;
0422
0423 ACPI_FUNCTION_TRACE(ut_copy_esimple_to_isimple);
0424
0425
0426
0427
0428 switch (external_object->type) {
0429 case ACPI_TYPE_STRING:
0430 case ACPI_TYPE_BUFFER:
0431 case ACPI_TYPE_INTEGER:
0432 case ACPI_TYPE_LOCAL_REFERENCE:
0433
0434 internal_object = acpi_ut_create_internal_object((u8)
0435 external_object->
0436 type);
0437 if (!internal_object) {
0438 return_ACPI_STATUS(AE_NO_MEMORY);
0439 }
0440 break;
0441
0442 case ACPI_TYPE_ANY:
0443
0444 *ret_internal_object = NULL;
0445 return_ACPI_STATUS(AE_OK);
0446
0447 default:
0448
0449
0450
0451 ACPI_ERROR((AE_INFO,
0452 "Unsupported object type, cannot convert to internal object: %s",
0453 acpi_ut_get_type_name(external_object->type)));
0454
0455 return_ACPI_STATUS(AE_SUPPORT);
0456 }
0457
0458
0459
0460 switch (external_object->type) {
0461 case ACPI_TYPE_STRING:
0462
0463 internal_object->string.pointer =
0464 ACPI_ALLOCATE_ZEROED((acpi_size)
0465 external_object->string.length + 1);
0466
0467 if (!internal_object->string.pointer) {
0468 goto error_exit;
0469 }
0470
0471 memcpy(internal_object->string.pointer,
0472 external_object->string.pointer,
0473 external_object->string.length);
0474
0475 internal_object->string.length = external_object->string.length;
0476 break;
0477
0478 case ACPI_TYPE_BUFFER:
0479
0480 internal_object->buffer.pointer =
0481 ACPI_ALLOCATE_ZEROED(external_object->buffer.length);
0482 if (!internal_object->buffer.pointer) {
0483 goto error_exit;
0484 }
0485
0486 memcpy(internal_object->buffer.pointer,
0487 external_object->buffer.pointer,
0488 external_object->buffer.length);
0489
0490 internal_object->buffer.length = external_object->buffer.length;
0491
0492
0493
0494 internal_object->buffer.flags |= AOPOBJ_DATA_VALID;
0495 break;
0496
0497 case ACPI_TYPE_INTEGER:
0498
0499 internal_object->integer.value = external_object->integer.value;
0500 break;
0501
0502 case ACPI_TYPE_LOCAL_REFERENCE:
0503
0504
0505
0506 internal_object->reference.class = ACPI_REFCLASS_REFOF;
0507 internal_object->reference.object =
0508 external_object->reference.handle;
0509 break;
0510
0511 default:
0512
0513
0514
0515 break;
0516 }
0517
0518 *ret_internal_object = internal_object;
0519 return_ACPI_STATUS(AE_OK);
0520
0521 error_exit:
0522 acpi_ut_remove_reference(internal_object);
0523 return_ACPI_STATUS(AE_NO_MEMORY);
0524 }
0525
0526
0527
0528
0529
0530
0531
0532
0533
0534
0535
0536
0537
0538
0539
0540 static acpi_status
0541 acpi_ut_copy_epackage_to_ipackage(union acpi_object *external_object,
0542 union acpi_operand_object **internal_object)
0543 {
0544 acpi_status status = AE_OK;
0545 union acpi_operand_object *package_object;
0546 union acpi_operand_object **package_elements;
0547 u32 i;
0548
0549 ACPI_FUNCTION_TRACE(ut_copy_epackage_to_ipackage);
0550
0551
0552
0553 package_object =
0554 acpi_ut_create_package_object(external_object->package.count);
0555 if (!package_object) {
0556 return_ACPI_STATUS(AE_NO_MEMORY);
0557 }
0558
0559 package_elements = package_object->package.elements;
0560
0561
0562
0563
0564
0565 for (i = 0; i < external_object->package.count; i++) {
0566 status =
0567 acpi_ut_copy_eobject_to_iobject(&external_object->package.
0568 elements[i],
0569 &package_elements[i]);
0570 if (ACPI_FAILURE(status)) {
0571
0572
0573
0574 package_object->package.count = i;
0575 package_elements[i] = NULL;
0576 acpi_ut_remove_reference(package_object);
0577 return_ACPI_STATUS(status);
0578 }
0579 }
0580
0581
0582
0583 package_object->package.flags |= AOPOBJ_DATA_VALID;
0584
0585 *internal_object = package_object;
0586 return_ACPI_STATUS(status);
0587 }
0588
0589
0590
0591
0592
0593
0594
0595
0596
0597
0598
0599
0600
0601
0602 acpi_status
0603 acpi_ut_copy_eobject_to_iobject(union acpi_object *external_object,
0604 union acpi_operand_object **internal_object)
0605 {
0606 acpi_status status;
0607
0608 ACPI_FUNCTION_TRACE(ut_copy_eobject_to_iobject);
0609
0610 if (external_object->type == ACPI_TYPE_PACKAGE) {
0611 status =
0612 acpi_ut_copy_epackage_to_ipackage(external_object,
0613 internal_object);
0614 } else {
0615
0616
0617
0618 status = acpi_ut_copy_esimple_to_isimple(external_object,
0619 internal_object);
0620 }
0621
0622 return_ACPI_STATUS(status);
0623 }
0624
0625
0626
0627
0628
0629
0630
0631
0632
0633
0634
0635
0636
0637
0638
0639 static acpi_status
0640 acpi_ut_copy_simple_object(union acpi_operand_object *source_desc,
0641 union acpi_operand_object *dest_desc)
0642 {
0643 u16 reference_count;
0644 union acpi_operand_object *next_object;
0645 acpi_status status;
0646 acpi_size copy_size;
0647
0648
0649
0650 reference_count = dest_desc->common.reference_count;
0651 next_object = dest_desc->common.next_object;
0652
0653
0654
0655
0656
0657 copy_size = sizeof(union acpi_operand_object);
0658 if (ACPI_GET_DESCRIPTOR_TYPE(source_desc) == ACPI_DESC_TYPE_NAMED) {
0659 copy_size = sizeof(struct acpi_namespace_node);
0660 }
0661
0662 memcpy(ACPI_CAST_PTR(char, dest_desc),
0663 ACPI_CAST_PTR(char, source_desc), copy_size);
0664
0665
0666
0667 dest_desc->common.reference_count = reference_count;
0668 dest_desc->common.next_object = next_object;
0669
0670
0671
0672 dest_desc->common.flags &= ~AOPOBJ_STATIC_POINTER;
0673
0674
0675
0676 switch (dest_desc->common.type) {
0677 case ACPI_TYPE_BUFFER:
0678
0679
0680
0681
0682
0683 if ((source_desc->buffer.pointer) &&
0684 (source_desc->buffer.length)) {
0685 dest_desc->buffer.pointer =
0686 ACPI_ALLOCATE(source_desc->buffer.length);
0687 if (!dest_desc->buffer.pointer) {
0688 return (AE_NO_MEMORY);
0689 }
0690
0691
0692
0693 memcpy(dest_desc->buffer.pointer,
0694 source_desc->buffer.pointer,
0695 source_desc->buffer.length);
0696 }
0697 break;
0698
0699 case ACPI_TYPE_STRING:
0700
0701
0702
0703
0704
0705 if (source_desc->string.pointer) {
0706 dest_desc->string.pointer =
0707 ACPI_ALLOCATE((acpi_size)source_desc->string.
0708 length + 1);
0709 if (!dest_desc->string.pointer) {
0710 return (AE_NO_MEMORY);
0711 }
0712
0713
0714
0715 memcpy(dest_desc->string.pointer,
0716 source_desc->string.pointer,
0717 (acpi_size)source_desc->string.length + 1);
0718 }
0719 break;
0720
0721 case ACPI_TYPE_LOCAL_REFERENCE:
0722
0723
0724
0725
0726
0727
0728
0729
0730 if (source_desc->reference.class == ACPI_REFCLASS_TABLE) {
0731 break;
0732 }
0733
0734 acpi_ut_add_reference(source_desc->reference.object);
0735 break;
0736
0737 case ACPI_TYPE_REGION:
0738
0739
0740
0741 if (dest_desc->region.handler) {
0742 acpi_ut_add_reference(dest_desc->region.handler);
0743 }
0744 break;
0745
0746
0747
0748
0749
0750 case ACPI_TYPE_MUTEX:
0751
0752 status = acpi_os_create_mutex(&dest_desc->mutex.os_mutex);
0753 if (ACPI_FAILURE(status)) {
0754 return (status);
0755 }
0756 break;
0757
0758 case ACPI_TYPE_EVENT:
0759
0760 status = acpi_os_create_semaphore(ACPI_NO_UNIT_LIMIT, 0,
0761 &dest_desc->event.
0762 os_semaphore);
0763 if (ACPI_FAILURE(status)) {
0764 return (status);
0765 }
0766 break;
0767
0768 default:
0769
0770
0771
0772 break;
0773 }
0774
0775 return (AE_OK);
0776 }
0777
0778
0779
0780
0781
0782
0783
0784
0785
0786
0787
0788
0789
0790 static acpi_status
0791 acpi_ut_copy_ielement_to_ielement(u8 object_type,
0792 union acpi_operand_object *source_object,
0793 union acpi_generic_state *state,
0794 void *context)
0795 {
0796 acpi_status status = AE_OK;
0797 u32 this_index;
0798 union acpi_operand_object **this_target_ptr;
0799 union acpi_operand_object *target_object;
0800
0801 ACPI_FUNCTION_ENTRY();
0802
0803 this_index = state->pkg.index;
0804 this_target_ptr = (union acpi_operand_object **)
0805 &state->pkg.dest_object->package.elements[this_index];
0806
0807 switch (object_type) {
0808 case ACPI_COPY_TYPE_SIMPLE:
0809
0810
0811
0812 if (source_object) {
0813
0814
0815
0816 target_object =
0817 acpi_ut_create_internal_object(source_object->
0818 common.type);
0819 if (!target_object) {
0820 return (AE_NO_MEMORY);
0821 }
0822
0823 status =
0824 acpi_ut_copy_simple_object(source_object,
0825 target_object);
0826 if (ACPI_FAILURE(status)) {
0827 goto error_exit;
0828 }
0829
0830 *this_target_ptr = target_object;
0831 } else {
0832
0833
0834 *this_target_ptr = NULL;
0835 }
0836 break;
0837
0838 case ACPI_COPY_TYPE_PACKAGE:
0839
0840
0841
0842
0843 target_object =
0844 acpi_ut_create_package_object(source_object->package.count);
0845 if (!target_object) {
0846 return (AE_NO_MEMORY);
0847 }
0848
0849 target_object->common.flags = source_object->common.flags;
0850
0851
0852
0853 state->pkg.this_target_obj = target_object;
0854
0855
0856
0857 *this_target_ptr = target_object;
0858 break;
0859
0860 default:
0861
0862 return (AE_BAD_PARAMETER);
0863 }
0864
0865 return (status);
0866
0867 error_exit:
0868 acpi_ut_remove_reference(target_object);
0869 return (status);
0870 }
0871
0872
0873
0874
0875
0876
0877
0878
0879
0880
0881
0882
0883
0884
0885
0886
0887 static acpi_status
0888 acpi_ut_copy_ipackage_to_ipackage(union acpi_operand_object *source_obj,
0889 union acpi_operand_object *dest_obj,
0890 struct acpi_walk_state *walk_state)
0891 {
0892 acpi_status status = AE_OK;
0893
0894 ACPI_FUNCTION_TRACE(ut_copy_ipackage_to_ipackage);
0895
0896 dest_obj->common.type = source_obj->common.type;
0897 dest_obj->common.flags = source_obj->common.flags;
0898 dest_obj->package.count = source_obj->package.count;
0899
0900
0901
0902
0903 dest_obj->package.elements = ACPI_ALLOCATE_ZEROED(((acpi_size)
0904 source_obj->package.
0905 count +
0906 1) * sizeof(void *));
0907 if (!dest_obj->package.elements) {
0908 ACPI_ERROR((AE_INFO, "Package allocation failure"));
0909 return_ACPI_STATUS(AE_NO_MEMORY);
0910 }
0911
0912
0913
0914
0915
0916 status = acpi_ut_walk_package_tree(source_obj, dest_obj,
0917 acpi_ut_copy_ielement_to_ielement,
0918 walk_state);
0919 if (ACPI_FAILURE(status)) {
0920
0921
0922
0923 acpi_ut_remove_reference(dest_obj);
0924 }
0925
0926 return_ACPI_STATUS(status);
0927 }
0928
0929
0930
0931
0932
0933
0934
0935
0936
0937
0938
0939
0940
0941
0942
0943 acpi_status
0944 acpi_ut_copy_iobject_to_iobject(union acpi_operand_object *source_desc,
0945 union acpi_operand_object **dest_desc,
0946 struct acpi_walk_state *walk_state)
0947 {
0948 acpi_status status = AE_OK;
0949
0950 ACPI_FUNCTION_TRACE(ut_copy_iobject_to_iobject);
0951
0952
0953
0954 *dest_desc = acpi_ut_create_internal_object(source_desc->common.type);
0955 if (!*dest_desc) {
0956 return_ACPI_STATUS(AE_NO_MEMORY);
0957 }
0958
0959
0960
0961 if (source_desc->common.type == ACPI_TYPE_PACKAGE) {
0962 status =
0963 acpi_ut_copy_ipackage_to_ipackage(source_desc, *dest_desc,
0964 walk_state);
0965 } else {
0966 status = acpi_ut_copy_simple_object(source_desc, *dest_desc);
0967 }
0968
0969
0970
0971 if (ACPI_FAILURE(status)) {
0972 acpi_ut_remove_reference(*dest_desc);
0973 }
0974
0975 return_ACPI_STATUS(status);
0976 }