@@ -867,18 +867,6 @@ static uacpi_status handle_package(struct execution_context *ctx)
867
867
return UACPI_STATUS_OK ;
868
868
}
869
869
870
- static uacpi_size field_byte_size (uacpi_object * obj )
871
- {
872
- uacpi_size bit_length ;
873
-
874
- if (obj -> type == UACPI_OBJECT_BUFFER_FIELD )
875
- bit_length = obj -> buffer_field .bit_length ;
876
- else
877
- bit_length = obj -> field_unit -> bit_length ;
878
-
879
- return uacpi_round_up_bits_to_bytes (bit_length );
880
- }
881
-
882
870
static uacpi_size sizeof_int (void )
883
871
{
884
872
return g_uacpi_rt_ctx .is_rev1 ? 4 : 8 ;
@@ -941,8 +929,9 @@ static void write_buffer_index(uacpi_buffer_index *buf_idx,
941
929
* the specification. In reality, we just copy one buffer to another
942
930
* because that's what NT does.
943
931
*/
944
- static uacpi_status object_assign_with_implicit_cast (uacpi_object * dst ,
945
- uacpi_object * src )
932
+ static uacpi_status object_assign_with_implicit_cast (
933
+ uacpi_object * dst , uacpi_object * src , uacpi_data_view * wtr_response
934
+ )
946
935
{
947
936
uacpi_status ret ;
948
937
uacpi_data_view src_buf ;
@@ -975,7 +964,8 @@ static uacpi_status object_assign_with_implicit_cast(uacpi_object *dst,
975
964
976
965
case UACPI_OBJECT_FIELD_UNIT :
977
966
return uacpi_write_field_unit (
978
- dst -> field_unit , src_buf .bytes , src_buf .length
967
+ dst -> field_unit , src_buf .bytes , src_buf .length ,
968
+ wtr_response
979
969
);
980
970
981
971
case UACPI_OBJECT_BUFFER_INDEX :
@@ -2279,8 +2269,9 @@ static void object_replace_child(uacpi_object *parent, uacpi_object *new_child)
2279
2269
* 3. NAME -> Store with implicit cast.
2280
2270
* 4. RefOf -> Not allowed here.
2281
2271
*/
2282
- static uacpi_status store_to_reference (uacpi_object * dst ,
2283
- uacpi_object * src )
2272
+ static uacpi_status store_to_reference (
2273
+ uacpi_object * dst , uacpi_object * src , uacpi_data_view * wtr_response
2274
+ )
2284
2275
{
2285
2276
uacpi_object * src_obj ;
2286
2277
uacpi_bool overwrite = UACPI_FALSE ;
@@ -2335,7 +2326,9 @@ static uacpi_status store_to_reference(uacpi_object *dst,
2335
2326
return UACPI_STATUS_OK ;
2336
2327
}
2337
2328
2338
- return object_assign_with_implicit_cast (dst -> inner_object , src_obj );
2329
+ return object_assign_with_implicit_cast (
2330
+ dst -> inner_object , src_obj , wtr_response
2331
+ );
2339
2332
}
2340
2333
2341
2334
static uacpi_status handle_ref_or_deref_of (struct execution_context * ctx )
@@ -3769,48 +3762,69 @@ static uacpi_object_type buffer_field_get_read_type(
3769
3762
return UACPI_OBJECT_INTEGER ;
3770
3763
}
3771
3764
3772
- static uacpi_object_type field_unit_get_read_type (
3773
- struct uacpi_field_unit * field
3765
+ static uacpi_status field_get_read_type (
3766
+ uacpi_object * obj , uacpi_object_type * out_type
3774
3767
)
3775
3768
{
3776
- if (field -> bit_length > (g_uacpi_rt_ctx .is_rev1 ? 32u : 64u ))
3777
- return UACPI_OBJECT_BUFFER ;
3769
+ if (obj -> type == UACPI_OBJECT_BUFFER_FIELD ) {
3770
+ * out_type = buffer_field_get_read_type (& obj -> buffer_field );
3771
+ return UACPI_STATUS_OK ;
3772
+ }
3778
3773
3779
- return UACPI_OBJECT_INTEGER ;
3774
+ return uacpi_field_unit_get_read_type ( obj -> field_unit , out_type ) ;
3780
3775
}
3781
3776
3782
- static uacpi_object_type field_get_read_type (uacpi_object * obj )
3777
+ static uacpi_status field_byte_size (
3778
+ uacpi_object * obj , uacpi_size * out_size
3779
+ )
3783
3780
{
3784
- if (obj -> type == UACPI_OBJECT_BUFFER_FIELD )
3785
- return buffer_field_get_read_type (& obj -> buffer_field );
3781
+ uacpi_size bit_length ;
3786
3782
3787
- return field_unit_get_read_type (obj -> field_unit );
3783
+ if (obj -> type == UACPI_OBJECT_BUFFER_FIELD ) {
3784
+ bit_length = obj -> buffer_field .bit_length ;
3785
+ } else {
3786
+ uacpi_status ret ;
3787
+
3788
+ ret = uacpi_field_unit_get_bit_length (obj -> field_unit , & bit_length );
3789
+ if (uacpi_unlikely_error (ret ))
3790
+ return ret ;
3791
+ }
3792
+
3793
+ * out_size = uacpi_round_up_bits_to_bytes (bit_length );
3794
+ return UACPI_STATUS_OK ;
3788
3795
}
3789
3796
3790
3797
static uacpi_status handle_field_read (struct execution_context * ctx )
3791
3798
{
3799
+ uacpi_status ret ;
3792
3800
struct op_context * op_ctx = ctx -> cur_op_ctx ;
3793
3801
struct uacpi_namespace_node * node ;
3794
3802
uacpi_object * src_obj , * dst_obj ;
3795
3803
uacpi_size dst_size ;
3796
- void * dst ;
3804
+ void * dst = UACPI_NULL ;
3805
+ uacpi_data_view wtr_response = { 0 };
3797
3806
3798
3807
node = item_array_at (& op_ctx -> items , 0 )-> node ;
3799
3808
src_obj = uacpi_namespace_node_get_object (node );
3800
3809
dst_obj = item_array_at (& op_ctx -> items , 1 )-> obj ;
3801
3810
3802
- if (field_get_read_type ( src_obj ) == UACPI_OBJECT_BUFFER ) {
3811
+ if (op_ctx -> op -> code == UACPI_AML_OP_InternalOpReadFieldAsBuffer ) {
3803
3812
uacpi_buffer * buf ;
3804
3813
3805
- buf = dst_obj -> buffer ;
3806
- dst_size = field_byte_size (src_obj );
3814
+ ret = field_byte_size (src_obj , & dst_size );
3815
+ if (uacpi_unlikely_error (ret ))
3816
+ return ret ;
3807
3817
3808
- dst = uacpi_kernel_alloc_zeroed (dst_size );
3809
- if (dst == UACPI_NULL )
3810
- return UACPI_STATUS_OUT_OF_MEMORY ;
3818
+ if (dst_size != 0 ) {
3819
+ buf = dst_obj -> buffer ;
3820
+
3821
+ dst = uacpi_kernel_alloc_zeroed (dst_size );
3822
+ if (dst == UACPI_NULL )
3823
+ return UACPI_STATUS_OUT_OF_MEMORY ;
3811
3824
3812
- buf -> data = dst ;
3813
- buf -> size = dst_size ;
3825
+ buf -> data = dst ;
3826
+ buf -> size = dst_size ;
3827
+ }
3814
3828
} else {
3815
3829
dst = & dst_obj -> integer ;
3816
3830
dst_size = sizeof (uacpi_u64 );
@@ -3821,7 +3835,21 @@ static uacpi_status handle_field_read(struct execution_context *ctx)
3821
3835
return UACPI_STATUS_OK ;
3822
3836
}
3823
3837
3824
- return uacpi_read_field_unit (src_obj -> field_unit , dst , dst_size );
3838
+ ret = uacpi_read_field_unit (
3839
+ src_obj -> field_unit , dst , dst_size , & wtr_response
3840
+ );
3841
+ if (uacpi_unlikely_error (ret ))
3842
+ return ret ;
3843
+
3844
+ if (wtr_response .data != UACPI_NULL ) {
3845
+ uacpi_buffer * buf ;
3846
+
3847
+ buf = dst_obj -> buffer ;
3848
+ buf -> data = wtr_response .data ;
3849
+ buf -> size = wtr_response .length ;
3850
+ }
3851
+
3852
+ return ret ;
3825
3853
}
3826
3854
3827
3855
static uacpi_status handle_create_buffer_field (struct execution_context * ctx )
@@ -4192,7 +4220,9 @@ static uacpi_bool maybe_end_block(struct execution_context *ctx)
4192
4220
return UACPI_TRUE ;
4193
4221
}
4194
4222
4195
- static uacpi_status store_to_target (uacpi_object * dst , uacpi_object * src )
4223
+ static uacpi_status store_to_target (
4224
+ uacpi_object * dst , uacpi_object * src , uacpi_data_view * wtr_response
4225
+ )
4196
4226
{
4197
4227
uacpi_status ret ;
4198
4228
@@ -4201,12 +4231,12 @@ static uacpi_status store_to_target(uacpi_object *dst, uacpi_object *src)
4201
4231
ret = debug_store (src );
4202
4232
break ;
4203
4233
case UACPI_OBJECT_REFERENCE :
4204
- ret = store_to_reference (dst , src );
4234
+ ret = store_to_reference (dst , src , wtr_response );
4205
4235
break ;
4206
4236
4207
4237
case UACPI_OBJECT_BUFFER_INDEX :
4208
4238
src = uacpi_unwrap_internal_reference (src );
4209
- ret = object_assign_with_implicit_cast (dst , src );
4239
+ ret = object_assign_with_implicit_cast (dst , src , wtr_response );
4210
4240
break ;
4211
4241
4212
4242
case UACPI_OBJECT_INTEGER :
@@ -4233,8 +4263,35 @@ static uacpi_status handle_copy_object_or_store(struct execution_context *ctx)
4233
4263
src = item_array_at (& op_ctx -> items , 0 )-> obj ;
4234
4264
dst = item_array_at (& op_ctx -> items , 1 )-> obj ;
4235
4265
4236
- if (op_ctx -> op -> code == UACPI_AML_OP_StoreOp )
4237
- return store_to_target (dst , src );
4266
+ if (op_ctx -> op -> code == UACPI_AML_OP_StoreOp ) {
4267
+ uacpi_status ret ;
4268
+ uacpi_data_view wtr_response = { 0 };
4269
+
4270
+ ret = store_to_target (dst , src , & wtr_response );
4271
+ if (uacpi_unlikely_error (ret ))
4272
+ return ret ;
4273
+
4274
+ /*
4275
+ * This was a write-then-read field access since we got a response
4276
+ * buffer back from this store. Now we have to return this buffer
4277
+ * as a prvalue from the StoreOp so that it can be used by AML to
4278
+ * retrieve the response.
4279
+ */
4280
+ if (wtr_response .data != UACPI_NULL ) {
4281
+ uacpi_object * wtr_response_obj ;
4282
+
4283
+ wtr_response_obj = uacpi_object_create_buffer (wtr_response );
4284
+ if (wtr_response_obj == UACPI_NULL ) {
4285
+ uacpi_free (wtr_response .data , wtr_response .length );
4286
+ return UACPI_STATUS_OUT_OF_MEMORY ;
4287
+ }
4288
+
4289
+ uacpi_object_unref (src );
4290
+ item_array_at (& op_ctx -> items , 0 )-> obj = wtr_response_obj ;
4291
+ }
4292
+
4293
+ return ret ;
4294
+ }
4238
4295
4239
4296
if (dst -> type != UACPI_OBJECT_REFERENCE )
4240
4297
return UACPI_STATUS_AML_INCOMPATIBLE_OBJECT_TYPE ;
@@ -4279,13 +4336,16 @@ static uacpi_status handle_inc_dec(struct execution_context *ctx)
4279
4336
if (uacpi_unlikely (!field_allowed ))
4280
4337
goto out_bad_type ;
4281
4338
4282
- true_src_type = field_get_read_type (src );
4339
+ ret = field_get_read_type (src , & true_src_type );
4340
+ if (uacpi_unlikely_error (ret ))
4341
+ goto out_bad_type ;
4283
4342
if (true_src_type != UACPI_OBJECT_INTEGER )
4284
4343
goto out_bad_type ;
4285
4344
4286
4345
if (src -> type == UACPI_OBJECT_FIELD_UNIT ) {
4287
4346
ret = uacpi_read_field_unit (
4288
- src -> field_unit , & dst -> integer , sizeof_int ()
4347
+ src -> field_unit , & dst -> integer , sizeof_int (),
4348
+ UACPI_NULL
4289
4349
);
4290
4350
if (uacpi_unlikely_error (ret ))
4291
4351
return ret ;
@@ -5497,7 +5557,7 @@ static uacpi_status exec_op(struct execution_context *ctx)
5497
5557
src = item -> obj ;
5498
5558
}
5499
5559
5500
- ret = store_to_target (dst , src );
5560
+ ret = store_to_target (dst , src , UACPI_NULL );
5501
5561
break ;
5502
5562
}
5503
5563
@@ -5589,11 +5649,28 @@ static uacpi_status exec_op(struct execution_context *ctx)
5589
5649
}
5590
5650
5591
5651
case UACPI_OBJECT_BUFFER_FIELD :
5592
- case UACPI_OBJECT_FIELD_UNIT :
5652
+ case UACPI_OBJECT_FIELD_UNIT : {
5653
+ uacpi_object_type type ;
5654
+
5593
5655
if (!op_wants_term_arg_or_operand (prev_op ))
5594
5656
break ;
5595
5657
5596
- switch (field_get_read_type (obj )) {
5658
+ ret = field_get_read_type (obj , & type );
5659
+ if (uacpi_unlikely_error (ret )) {
5660
+ const uacpi_char * field_path ;
5661
+
5662
+ field_path = uacpi_namespace_node_generate_absolute_path (
5663
+ item -> node
5664
+ );
5665
+
5666
+ uacpi_error (
5667
+ "unable to perform a read from field %s: "
5668
+ "parent opregion gone\n" , field_path
5669
+ );
5670
+ uacpi_free_absolute_path (field_path );
5671
+ }
5672
+
5673
+ switch (type ) {
5597
5674
case UACPI_OBJECT_BUFFER :
5598
5675
new_op = UACPI_AML_OP_InternalOpReadFieldAsBuffer ;
5599
5676
break ;
@@ -5605,6 +5682,7 @@ static uacpi_status exec_op(struct execution_context *ctx)
5605
5682
continue ;
5606
5683
}
5607
5684
break ;
5685
+ }
5608
5686
default :
5609
5687
break ;
5610
5688
}
0 commit comments