Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/acpi/acpica/dsobject.c
26282 views
1
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2
/******************************************************************************
3
*
4
* Module Name: dsobject - Dispatcher object management routines
5
*
6
* Copyright (C) 2000 - 2025, Intel Corp.
7
*
8
*****************************************************************************/
9
10
#include <acpi/acpi.h>
11
#include "accommon.h"
12
#include "acparser.h"
13
#include "amlcode.h"
14
#include "acdispat.h"
15
#include "acnamesp.h"
16
#include "acinterp.h"
17
18
#define _COMPONENT ACPI_DISPATCHER
19
ACPI_MODULE_NAME("dsobject")
20
21
/*******************************************************************************
22
*
23
* FUNCTION: acpi_ds_build_internal_object
24
*
25
* PARAMETERS: walk_state - Current walk state
26
* op - Parser object to be translated
27
* obj_desc_ptr - Where the ACPI internal object is returned
28
*
29
* RETURN: Status
30
*
31
* DESCRIPTION: Translate a parser Op object to the equivalent namespace object
32
* Simple objects are any objects other than a package object!
33
*
34
******************************************************************************/
35
acpi_status
36
acpi_ds_build_internal_object(struct acpi_walk_state *walk_state,
37
union acpi_parse_object *op,
38
union acpi_operand_object **obj_desc_ptr)
39
{
40
union acpi_operand_object *obj_desc;
41
acpi_status status;
42
43
ACPI_FUNCTION_TRACE(ds_build_internal_object);
44
45
*obj_desc_ptr = NULL;
46
if (op->common.aml_opcode == AML_INT_NAMEPATH_OP) {
47
/*
48
* This is a named object reference. If this name was
49
* previously looked up in the namespace, it was stored in
50
* this op. Otherwise, go ahead and look it up now
51
*/
52
if (!op->common.node) {
53
54
/* Check if we are resolving a named reference within a package */
55
56
if ((op->common.parent->common.aml_opcode ==
57
AML_PACKAGE_OP)
58
|| (op->common.parent->common.aml_opcode ==
59
AML_VARIABLE_PACKAGE_OP)) {
60
/*
61
* We won't resolve package elements here, we will do this
62
* after all ACPI tables are loaded into the namespace. This
63
* behavior supports both forward references to named objects
64
* and external references to objects in other tables.
65
*/
66
goto create_new_object;
67
} else {
68
status = acpi_ns_lookup(walk_state->scope_info,
69
op->common.value.string,
70
ACPI_TYPE_ANY,
71
ACPI_IMODE_EXECUTE,
72
ACPI_NS_SEARCH_PARENT |
73
ACPI_NS_DONT_OPEN_SCOPE,
74
NULL,
75
ACPI_CAST_INDIRECT_PTR
76
(struct
77
acpi_namespace_node,
78
&(op->common.node)));
79
if (ACPI_FAILURE(status)) {
80
ACPI_ERROR_NAMESPACE(walk_state->
81
scope_info,
82
op->common.value.
83
string, status);
84
return_ACPI_STATUS(status);
85
}
86
}
87
}
88
}
89
90
create_new_object:
91
92
/* Create and init a new internal ACPI object */
93
94
obj_desc = acpi_ut_create_internal_object((acpi_ps_get_opcode_info
95
(op->common.aml_opcode))->
96
object_type);
97
if (!obj_desc) {
98
return_ACPI_STATUS(AE_NO_MEMORY);
99
}
100
101
status =
102
acpi_ds_init_object_from_op(walk_state, op, op->common.aml_opcode,
103
&obj_desc);
104
if (ACPI_FAILURE(status)) {
105
acpi_ut_remove_reference(obj_desc);
106
return_ACPI_STATUS(status);
107
}
108
109
/*
110
* Handling for unresolved package reference elements.
111
* These are elements that are namepaths.
112
*/
113
if ((op->common.parent->common.aml_opcode == AML_PACKAGE_OP) ||
114
(op->common.parent->common.aml_opcode == AML_VARIABLE_PACKAGE_OP)) {
115
obj_desc->reference.resolved = TRUE;
116
117
if ((op->common.aml_opcode == AML_INT_NAMEPATH_OP) &&
118
!obj_desc->reference.node) {
119
/*
120
* Name was unresolved above.
121
* Get the prefix node for later lookup
122
*/
123
obj_desc->reference.node =
124
walk_state->scope_info->scope.node;
125
obj_desc->reference.aml = op->common.aml;
126
obj_desc->reference.resolved = FALSE;
127
}
128
}
129
130
*obj_desc_ptr = obj_desc;
131
return_ACPI_STATUS(status);
132
}
133
134
/*******************************************************************************
135
*
136
* FUNCTION: acpi_ds_build_internal_buffer_obj
137
*
138
* PARAMETERS: walk_state - Current walk state
139
* op - Parser object to be translated
140
* buffer_length - Length of the buffer
141
* obj_desc_ptr - Where the ACPI internal object is returned
142
*
143
* RETURN: Status
144
*
145
* DESCRIPTION: Translate a parser Op package object to the equivalent
146
* namespace object
147
*
148
******************************************************************************/
149
150
acpi_status
151
acpi_ds_build_internal_buffer_obj(struct acpi_walk_state *walk_state,
152
union acpi_parse_object *op,
153
u32 buffer_length,
154
union acpi_operand_object **obj_desc_ptr)
155
{
156
union acpi_parse_object *arg;
157
union acpi_operand_object *obj_desc;
158
union acpi_parse_object *byte_list;
159
u32 byte_list_length = 0;
160
161
ACPI_FUNCTION_TRACE(ds_build_internal_buffer_obj);
162
163
/*
164
* If we are evaluating a Named buffer object "Name (xxxx, Buffer)".
165
* The buffer object already exists (from the NS node), otherwise it must
166
* be created.
167
*/
168
obj_desc = *obj_desc_ptr;
169
if (!obj_desc) {
170
171
/* Create a new buffer object */
172
173
obj_desc = acpi_ut_create_internal_object(ACPI_TYPE_BUFFER);
174
*obj_desc_ptr = obj_desc;
175
if (!obj_desc) {
176
return_ACPI_STATUS(AE_NO_MEMORY);
177
}
178
}
179
180
/*
181
* Second arg is the buffer data (optional) byte_list can be either
182
* individual bytes or a string initializer. In either case, a
183
* byte_list appears in the AML.
184
*/
185
arg = op->common.value.arg; /* skip first arg */
186
187
byte_list = arg->named.next;
188
if (byte_list) {
189
if (byte_list->common.aml_opcode != AML_INT_BYTELIST_OP) {
190
ACPI_ERROR((AE_INFO,
191
"Expecting bytelist, found AML opcode 0x%X in op %p",
192
byte_list->common.aml_opcode, byte_list));
193
194
acpi_ut_remove_reference(obj_desc);
195
return (AE_TYPE);
196
}
197
198
byte_list_length = (u32) byte_list->common.value.integer;
199
}
200
201
/*
202
* The buffer length (number of bytes) will be the larger of:
203
* 1) The specified buffer length and
204
* 2) The length of the initializer byte list
205
*/
206
obj_desc->buffer.length = buffer_length;
207
if (byte_list_length > buffer_length) {
208
obj_desc->buffer.length = byte_list_length;
209
}
210
211
/* Allocate the buffer */
212
213
if (obj_desc->buffer.length == 0) {
214
obj_desc->buffer.pointer = NULL;
215
ACPI_DEBUG_PRINT((ACPI_DB_EXEC,
216
"Buffer defined with zero length in AML, creating\n"));
217
} else {
218
obj_desc->buffer.pointer =
219
ACPI_ALLOCATE_ZEROED(obj_desc->buffer.length);
220
if (!obj_desc->buffer.pointer) {
221
acpi_ut_delete_object_desc(obj_desc);
222
return_ACPI_STATUS(AE_NO_MEMORY);
223
}
224
225
/* Initialize buffer from the byte_list (if present) */
226
227
if (byte_list) {
228
memcpy(obj_desc->buffer.pointer, byte_list->named.data,
229
byte_list_length);
230
}
231
}
232
233
obj_desc->buffer.flags |= AOPOBJ_DATA_VALID;
234
op->common.node = ACPI_CAST_PTR(struct acpi_namespace_node, obj_desc);
235
return_ACPI_STATUS(AE_OK);
236
}
237
238
/*******************************************************************************
239
*
240
* FUNCTION: acpi_ds_create_node
241
*
242
* PARAMETERS: walk_state - Current walk state
243
* node - NS Node to be initialized
244
* op - Parser object to be translated
245
*
246
* RETURN: Status
247
*
248
* DESCRIPTION: Create the object to be associated with a namespace node
249
*
250
******************************************************************************/
251
252
acpi_status
253
acpi_ds_create_node(struct acpi_walk_state *walk_state,
254
struct acpi_namespace_node *node,
255
union acpi_parse_object *op)
256
{
257
acpi_status status;
258
union acpi_operand_object *obj_desc;
259
260
ACPI_FUNCTION_TRACE_PTR(ds_create_node, op);
261
262
/*
263
* Because of the execution pass through the non-control-method
264
* parts of the table, we can arrive here twice. Only init
265
* the named object node the first time through
266
*/
267
if (acpi_ns_get_attached_object(node)) {
268
return_ACPI_STATUS(AE_OK);
269
}
270
271
if (!op->common.value.arg) {
272
273
/* No arguments, there is nothing to do */
274
275
return_ACPI_STATUS(AE_OK);
276
}
277
278
/* Build an internal object for the argument(s) */
279
280
status =
281
acpi_ds_build_internal_object(walk_state, op->common.value.arg,
282
&obj_desc);
283
if (ACPI_FAILURE(status)) {
284
return_ACPI_STATUS(status);
285
}
286
287
/* Re-type the object according to its argument */
288
289
node->type = obj_desc->common.type;
290
291
/* Attach obj to node */
292
293
status = acpi_ns_attach_object(node, obj_desc, node->type);
294
295
/* Remove local reference to the object */
296
297
acpi_ut_remove_reference(obj_desc);
298
return_ACPI_STATUS(status);
299
}
300
301
/*******************************************************************************
302
*
303
* FUNCTION: acpi_ds_init_object_from_op
304
*
305
* PARAMETERS: walk_state - Current walk state
306
* op - Parser op used to init the internal object
307
* opcode - AML opcode associated with the object
308
* ret_obj_desc - Namespace object to be initialized
309
*
310
* RETURN: Status
311
*
312
* DESCRIPTION: Initialize a namespace object from a parser Op and its
313
* associated arguments. The namespace object is a more compact
314
* representation of the Op and its arguments.
315
*
316
******************************************************************************/
317
318
acpi_status
319
acpi_ds_init_object_from_op(struct acpi_walk_state *walk_state,
320
union acpi_parse_object *op,
321
u16 opcode,
322
union acpi_operand_object **ret_obj_desc)
323
{
324
const struct acpi_opcode_info *op_info;
325
union acpi_operand_object *obj_desc;
326
acpi_status status = AE_OK;
327
328
ACPI_FUNCTION_TRACE(ds_init_object_from_op);
329
330
obj_desc = *ret_obj_desc;
331
op_info = acpi_ps_get_opcode_info(opcode);
332
if (op_info->class == AML_CLASS_UNKNOWN) {
333
334
/* Unknown opcode */
335
336
return_ACPI_STATUS(AE_TYPE);
337
}
338
339
/* Perform per-object initialization */
340
341
switch (obj_desc->common.type) {
342
case ACPI_TYPE_BUFFER:
343
/*
344
* Defer evaluation of Buffer term_arg operand
345
*/
346
obj_desc->buffer.node =
347
ACPI_CAST_PTR(struct acpi_namespace_node,
348
walk_state->operands[0]);
349
obj_desc->buffer.aml_start = op->named.data;
350
obj_desc->buffer.aml_length = op->named.length;
351
break;
352
353
case ACPI_TYPE_PACKAGE:
354
/*
355
* Defer evaluation of Package term_arg operand and all
356
* package elements. (01/2017): We defer the element
357
* resolution to allow forward references from the package
358
* in order to provide compatibility with other ACPI
359
* implementations.
360
*/
361
obj_desc->package.node =
362
ACPI_CAST_PTR(struct acpi_namespace_node,
363
walk_state->operands[0]);
364
365
if (!op->named.data) {
366
return_ACPI_STATUS(AE_OK);
367
}
368
369
obj_desc->package.aml_start = op->named.data;
370
obj_desc->package.aml_length = op->named.length;
371
break;
372
373
case ACPI_TYPE_INTEGER:
374
375
switch (op_info->type) {
376
case AML_TYPE_CONSTANT:
377
/*
378
* Resolve AML Constants here - AND ONLY HERE!
379
* All constants are integers.
380
* We mark the integer with a flag that indicates that it started
381
* life as a constant -- so that stores to constants will perform
382
* as expected (noop). zero_op is used as a placeholder for optional
383
* target operands.
384
*/
385
obj_desc->common.flags = AOPOBJ_AML_CONSTANT;
386
387
switch (opcode) {
388
case AML_ZERO_OP:
389
390
obj_desc->integer.value = 0;
391
break;
392
393
case AML_ONE_OP:
394
395
obj_desc->integer.value = 1;
396
break;
397
398
case AML_ONES_OP:
399
400
obj_desc->integer.value = ACPI_UINT64_MAX;
401
402
/* Truncate value if we are executing from a 32-bit ACPI table */
403
404
(void)acpi_ex_truncate_for32bit_table(obj_desc);
405
break;
406
407
case AML_REVISION_OP:
408
409
obj_desc->integer.value = ACPI_CA_VERSION;
410
break;
411
412
default:
413
414
ACPI_ERROR((AE_INFO,
415
"Unknown constant opcode 0x%X",
416
opcode));
417
status = AE_AML_OPERAND_TYPE;
418
break;
419
}
420
break;
421
422
case AML_TYPE_LITERAL:
423
424
obj_desc->integer.value = op->common.value.integer;
425
426
if (acpi_ex_truncate_for32bit_table(obj_desc)) {
427
428
/* Warn if we found a 64-bit constant in a 32-bit table */
429
430
ACPI_WARNING((AE_INFO,
431
"Truncated 64-bit constant found in 32-bit table: %8.8X%8.8X => %8.8X",
432
ACPI_FORMAT_UINT64(op->common.
433
value.integer),
434
(u32)obj_desc->integer.value));
435
}
436
break;
437
438
default:
439
440
ACPI_ERROR((AE_INFO, "Unknown Integer type 0x%X",
441
op_info->type));
442
status = AE_AML_OPERAND_TYPE;
443
break;
444
}
445
break;
446
447
case ACPI_TYPE_STRING:
448
449
obj_desc->string.pointer = op->common.value.string;
450
obj_desc->string.length = (u32)strlen(op->common.value.string);
451
452
/*
453
* The string is contained in the ACPI table, don't ever try
454
* to delete it
455
*/
456
obj_desc->common.flags |= AOPOBJ_STATIC_POINTER;
457
break;
458
459
case ACPI_TYPE_METHOD:
460
break;
461
462
case ACPI_TYPE_LOCAL_REFERENCE:
463
464
switch (op_info->type) {
465
case AML_TYPE_LOCAL_VARIABLE:
466
467
/* Local ID (0-7) is (AML opcode - base AML_FIRST_LOCAL_OP) */
468
469
obj_desc->reference.value =
470
((u32)opcode) - AML_FIRST_LOCAL_OP;
471
obj_desc->reference.class = ACPI_REFCLASS_LOCAL;
472
473
status =
474
acpi_ds_method_data_get_node(ACPI_REFCLASS_LOCAL,
475
obj_desc->reference.
476
value, walk_state,
477
ACPI_CAST_INDIRECT_PTR
478
(struct
479
acpi_namespace_node,
480
&obj_desc->reference.
481
object));
482
break;
483
484
case AML_TYPE_METHOD_ARGUMENT:
485
486
/* Arg ID (0-6) is (AML opcode - base AML_FIRST_ARG_OP) */
487
488
obj_desc->reference.value =
489
((u32)opcode) - AML_FIRST_ARG_OP;
490
obj_desc->reference.class = ACPI_REFCLASS_ARG;
491
492
status = acpi_ds_method_data_get_node(ACPI_REFCLASS_ARG,
493
obj_desc->
494
reference.value,
495
walk_state,
496
ACPI_CAST_INDIRECT_PTR
497
(struct
498
acpi_namespace_node,
499
&obj_desc->
500
reference.
501
object));
502
break;
503
504
default: /* Object name or Debug object */
505
506
switch (op->common.aml_opcode) {
507
case AML_INT_NAMEPATH_OP:
508
509
/* Node was saved in Op */
510
511
obj_desc->reference.node = op->common.node;
512
obj_desc->reference.class = ACPI_REFCLASS_NAME;
513
if (op->common.node) {
514
obj_desc->reference.object =
515
op->common.node->object;
516
}
517
break;
518
519
case AML_DEBUG_OP:
520
521
obj_desc->reference.class = ACPI_REFCLASS_DEBUG;
522
break;
523
524
default:
525
526
ACPI_ERROR((AE_INFO,
527
"Unimplemented reference type for AML opcode: 0x%4.4X",
528
opcode));
529
return_ACPI_STATUS(AE_AML_OPERAND_TYPE);
530
}
531
break;
532
}
533
break;
534
535
default:
536
537
ACPI_ERROR((AE_INFO, "Unimplemented data type: 0x%X",
538
obj_desc->common.type));
539
540
status = AE_AML_OPERAND_TYPE;
541
break;
542
}
543
544
return_ACPI_STATUS(status);
545
}
546
547