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 "acdispat.h"
47#include "acinterp.h"
48#include "amlcode.h"
49#include "acnamesp.h"
50
51#define _COMPONENT ACPI_EXECUTER
52ACPI_MODULE_NAME("exstore")
53
54
55static acpi_status
56acpi_ex_store_object_to_index(union acpi_operand_object *val_desc,
57 union acpi_operand_object *dest_desc,
58 struct acpi_walk_state *walk_state);
59
60static acpi_status
61acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
62 struct acpi_namespace_node *node,
63 struct acpi_walk_state *walk_state);
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85acpi_status
86acpi_ex_store(union acpi_operand_object *source_desc,
87 union acpi_operand_object *dest_desc,
88 struct acpi_walk_state *walk_state)
89{
90 acpi_status status = AE_OK;
91 union acpi_operand_object *ref_desc = dest_desc;
92
93 ACPI_FUNCTION_TRACE_PTR(ex_store, dest_desc);
94
95
96
97 if (!source_desc || !dest_desc) {
98 ACPI_ERROR((AE_INFO, "Null parameter"));
99 return_ACPI_STATUS(AE_AML_NO_OPERAND);
100 }
101
102
103
104 if (ACPI_GET_DESCRIPTOR_TYPE(dest_desc) == ACPI_DESC_TYPE_NAMED) {
105
106
107
108
109 status = acpi_ex_store_object_to_node(source_desc,
110 (struct
111 acpi_namespace_node *)
112 dest_desc, walk_state,
113 ACPI_IMPLICIT_CONVERSION);
114
115 return_ACPI_STATUS(status);
116 }
117
118
119
120 switch (dest_desc->common.type) {
121 case ACPI_TYPE_LOCAL_REFERENCE:
122
123 break;
124
125 case ACPI_TYPE_INTEGER:
126
127
128
129 if (dest_desc->common.flags & AOPOBJ_AML_CONSTANT) {
130 return_ACPI_STATUS(AE_OK);
131 }
132
133
134
135 default:
136
137
138
139 ACPI_ERROR((AE_INFO,
140 "Target is not a Reference or Constant object - %s [%p]",
141 acpi_ut_get_object_type_name(dest_desc),
142 dest_desc));
143
144 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
145 }
146
147
148
149
150
151
152
153
154
155 switch (ref_desc->reference.class) {
156 case ACPI_REFCLASS_REFOF:
157
158
159
160 status = acpi_ex_store_object_to_node(source_desc,
161 ref_desc->reference.
162 object, walk_state,
163 ACPI_IMPLICIT_CONVERSION);
164 break;
165
166 case ACPI_REFCLASS_INDEX:
167
168
169
170 status =
171 acpi_ex_store_object_to_index(source_desc, ref_desc,
172 walk_state);
173 break;
174
175 case ACPI_REFCLASS_LOCAL:
176 case ACPI_REFCLASS_ARG:
177
178
179
180 status =
181 acpi_ds_store_object_to_local(ref_desc->reference.class,
182 ref_desc->reference.value,
183 source_desc, walk_state);
184 break;
185
186 case ACPI_REFCLASS_DEBUG:
187
188
189
190
191 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
192 "**** Write to Debug Object: Object %p %s ****:\n\n",
193 source_desc,
194 acpi_ut_get_object_type_name(source_desc)));
195
196 ACPI_DEBUG_OBJECT(source_desc, 0, 0);
197 break;
198
199 default:
200
201 ACPI_ERROR((AE_INFO, "Unknown Reference Class 0x%2.2X",
202 ref_desc->reference.class));
203 ACPI_DUMP_ENTRY(ref_desc, ACPI_LV_INFO);
204
205 status = AE_AML_INTERNAL;
206 break;
207 }
208
209 return_ACPI_STATUS(status);
210}
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226static acpi_status
227acpi_ex_store_object_to_index(union acpi_operand_object *source_desc,
228 union acpi_operand_object *index_desc,
229 struct acpi_walk_state *walk_state)
230{
231 acpi_status status = AE_OK;
232 union acpi_operand_object *obj_desc;
233 union acpi_operand_object *new_desc;
234 u8 value = 0;
235 u32 i;
236
237 ACPI_FUNCTION_TRACE(ex_store_object_to_index);
238
239
240
241
242
243 switch (index_desc->reference.target_type) {
244 case ACPI_TYPE_PACKAGE:
245
246
247
248
249
250
251
252
253
254 obj_desc = *(index_desc->reference.where);
255
256 if (source_desc->common.type == ACPI_TYPE_LOCAL_REFERENCE &&
257 source_desc->reference.class == ACPI_REFCLASS_TABLE) {
258
259
260
261 acpi_ut_add_reference(source_desc);
262 new_desc = source_desc;
263 } else {
264
265
266 status =
267 acpi_ut_copy_iobject_to_iobject(source_desc,
268 &new_desc,
269 walk_state);
270 if (ACPI_FAILURE(status)) {
271 return_ACPI_STATUS(status);
272 }
273 }
274
275 if (obj_desc) {
276
277
278
279 for (i = 0; i < ((union acpi_operand_object *)
280 index_desc->reference.object)->common.
281 reference_count; i++) {
282 acpi_ut_remove_reference(obj_desc);
283 }
284 }
285
286 *(index_desc->reference.where) = new_desc;
287
288
289
290 for (i = 1; i < ((union acpi_operand_object *)
291 index_desc->reference.object)->common.
292 reference_count; i++) {
293 acpi_ut_add_reference(new_desc);
294 }
295
296 break;
297
298 case ACPI_TYPE_BUFFER_FIELD:
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313 obj_desc = index_desc->reference.object;
314 if ((obj_desc->common.type != ACPI_TYPE_BUFFER) &&
315 (obj_desc->common.type != ACPI_TYPE_STRING)) {
316 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
317 }
318
319
320
321
322
323 switch (source_desc->common.type) {
324 case ACPI_TYPE_INTEGER:
325
326
327
328 value = (u8) (source_desc->integer.value);
329 break;
330
331 case ACPI_TYPE_BUFFER:
332 case ACPI_TYPE_STRING:
333
334
335
336 value = source_desc->buffer.pointer[0];
337 break;
338
339 default:
340
341
342
343 ACPI_ERROR((AE_INFO,
344 "Source must be Integer/Buffer/String type, not %s",
345 acpi_ut_get_object_type_name(source_desc)));
346 return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
347 }
348
349
350
351 obj_desc->buffer.pointer[index_desc->reference.value] = value;
352 break;
353
354 default:
355 ACPI_ERROR((AE_INFO, "Target is not a Package or BufferField"));
356 status = AE_AML_OPERAND_TYPE;
357 break;
358 }
359
360 return_ACPI_STATUS(status);
361}
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393acpi_status
394acpi_ex_store_object_to_node(union acpi_operand_object *source_desc,
395 struct acpi_namespace_node *node,
396 struct acpi_walk_state *walk_state,
397 u8 implicit_conversion)
398{
399 acpi_status status = AE_OK;
400 union acpi_operand_object *target_desc;
401 union acpi_operand_object *new_desc;
402 acpi_object_type target_type;
403
404 ACPI_FUNCTION_TRACE_PTR(ex_store_object_to_node, source_desc);
405
406
407
408 target_type = acpi_ns_get_type(node);
409 target_desc = acpi_ns_get_attached_object(node);
410
411 ACPI_DEBUG_PRINT((ACPI_DB_EXEC, "Storing %p (%s) to node %p (%s)\n",
412 source_desc,
413 acpi_ut_get_object_type_name(source_desc), node,
414 acpi_ut_get_type_name(target_type)));
415
416
417
418
419
420 status = acpi_ex_resolve_object(&source_desc, target_type, walk_state);
421 if (ACPI_FAILURE(status)) {
422 return_ACPI_STATUS(status);
423 }
424
425
426
427 switch (target_type) {
428 case ACPI_TYPE_INTEGER:
429 case ACPI_TYPE_STRING:
430 case ACPI_TYPE_BUFFER:
431
432
433
434
435
436 if ((walk_state->opcode == AML_COPY_OP) || !implicit_conversion) {
437
438
439
440
441
442 status = acpi_ex_store_direct_to_node(source_desc, node,
443 walk_state);
444 break;
445 }
446
447
448
449 status =
450 acpi_ex_store_object_to_object(source_desc, target_desc,
451 &new_desc, walk_state);
452 if (ACPI_FAILURE(status)) {
453 return_ACPI_STATUS(status);
454 }
455
456 if (new_desc != target_desc) {
457
458
459
460
461
462
463
464
465
466 status = acpi_ns_attach_object(node, new_desc,
467 new_desc->common.type);
468
469 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
470 "Store %s into %s via Convert/Attach\n",
471 acpi_ut_get_object_type_name
472 (source_desc),
473 acpi_ut_get_object_type_name
474 (new_desc)));
475 }
476 break;
477
478 case ACPI_TYPE_BUFFER_FIELD:
479 case ACPI_TYPE_LOCAL_REGION_FIELD:
480 case ACPI_TYPE_LOCAL_BANK_FIELD:
481 case ACPI_TYPE_LOCAL_INDEX_FIELD:
482
483
484
485
486
487
488 status = acpi_ex_write_data_to_field(source_desc, target_desc,
489 &walk_state->result_obj);
490 break;
491
492 default:
493
494
495
496
497
498
499
500
501
502
503
504 status = acpi_ex_store_direct_to_node(source_desc, node,
505 walk_state);
506 break;
507 }
508
509 return_ACPI_STATUS(status);
510}
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527static acpi_status
528acpi_ex_store_direct_to_node(union acpi_operand_object *source_desc,
529 struct acpi_namespace_node *node,
530 struct acpi_walk_state *walk_state)
531{
532 acpi_status status;
533 union acpi_operand_object *new_desc;
534
535 ACPI_FUNCTION_TRACE(ex_store_direct_to_node);
536
537 ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
538 "Storing [%s] (%p) directly into node [%s] (%p)"
539 " with no implicit conversion\n",
540 acpi_ut_get_object_type_name(source_desc),
541 source_desc, acpi_ut_get_type_name(node->type),
542 node));
543
544
545
546 status =
547 acpi_ut_copy_iobject_to_iobject(source_desc, &new_desc, walk_state);
548 if (ACPI_FAILURE(status)) {
549 return_ACPI_STATUS(status);
550 }
551
552
553
554 status = acpi_ns_attach_object(node, new_desc, new_desc->common.type);
555 acpi_ut_remove_reference(new_desc);
556 return_ACPI_STATUS(status);
557}
558