195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: pstree - Parser op tree manipulation/traversal/search
595b482a8SLen Brown *
6*612c2932SBob Moore * Copyright (C) 2000 - 2023, Intel Corp.
795b482a8SLen Brown *
895857638SErik Schmauss *****************************************************************************/
995b482a8SLen Brown
1095b482a8SLen Brown #include <acpi/acpi.h>
11e2f7a777SLen Brown #include "accommon.h"
12e2f7a777SLen Brown #include "acparser.h"
13e2f7a777SLen Brown #include "amlcode.h"
149cf7adecSBob Moore #include "acconvert.h"
1595b482a8SLen Brown
1695b482a8SLen Brown #define _COMPONENT ACPI_PARSER
1795b482a8SLen Brown ACPI_MODULE_NAME("pstree")
1895b482a8SLen Brown
1995b482a8SLen Brown /* Local prototypes */
2095b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS
2195b482a8SLen Brown union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op);
2295b482a8SLen Brown #endif
2395b482a8SLen Brown
2495b482a8SLen Brown /*******************************************************************************
2595b482a8SLen Brown *
2695b482a8SLen Brown * FUNCTION: acpi_ps_get_arg
2795b482a8SLen Brown *
28ba494beeSBob Moore * PARAMETERS: op - Get an argument for this op
29ba494beeSBob Moore * argn - Nth argument to get
3095b482a8SLen Brown *
3195b482a8SLen Brown * RETURN: The argument (as an Op object). NULL if argument does not exist
3295b482a8SLen Brown *
3395b482a8SLen Brown * DESCRIPTION: Get the specified op's argument.
3495b482a8SLen Brown *
3595b482a8SLen Brown ******************************************************************************/
3695b482a8SLen Brown
acpi_ps_get_arg(union acpi_parse_object * op,u32 argn)3795b482a8SLen Brown union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn)
3895b482a8SLen Brown {
3995b482a8SLen Brown union acpi_parse_object *arg = NULL;
4095b482a8SLen Brown const struct acpi_opcode_info *op_info;
4195b482a8SLen Brown
4295b482a8SLen Brown ACPI_FUNCTION_ENTRY();
4395b482a8SLen Brown
449ce81784SBob Moore /*
459ce81784SBob Moore if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP)
469ce81784SBob Moore {
479ce81784SBob Moore return (Op->Common.Value.Arg);
489ce81784SBob Moore }
499ce81784SBob Moore */
5095b482a8SLen Brown /* Get the info structure for this opcode */
5195b482a8SLen Brown
5295b482a8SLen Brown op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
5395b482a8SLen Brown if (op_info->class == AML_CLASS_UNKNOWN) {
5495b482a8SLen Brown
5595b482a8SLen Brown /* Invalid opcode or ASCII character */
5695b482a8SLen Brown
5795b482a8SLen Brown return (NULL);
5895b482a8SLen Brown }
5995b482a8SLen Brown
6095b482a8SLen Brown /* Check if this opcode requires argument sub-objects */
6195b482a8SLen Brown
6295b482a8SLen Brown if (!(op_info->flags & AML_HAS_ARGS)) {
6395b482a8SLen Brown
6495b482a8SLen Brown /* Has no linked argument objects */
6595b482a8SLen Brown
6695b482a8SLen Brown return (NULL);
6795b482a8SLen Brown }
6895b482a8SLen Brown
6995b482a8SLen Brown /* Get the requested argument object */
7095b482a8SLen Brown
7195b482a8SLen Brown arg = op->common.value.arg;
7295b482a8SLen Brown while (arg && argn) {
7395b482a8SLen Brown argn--;
7495b482a8SLen Brown arg = arg->common.next;
7595b482a8SLen Brown }
7695b482a8SLen Brown
7795b482a8SLen Brown return (arg);
7895b482a8SLen Brown }
7995b482a8SLen Brown
8095b482a8SLen Brown /*******************************************************************************
8195b482a8SLen Brown *
8295b482a8SLen Brown * FUNCTION: acpi_ps_append_arg
8395b482a8SLen Brown *
84ba494beeSBob Moore * PARAMETERS: op - Append an argument to this Op.
85ba494beeSBob Moore * arg - Argument Op to append
8695b482a8SLen Brown *
8795b482a8SLen Brown * RETURN: None.
8895b482a8SLen Brown *
8995b482a8SLen Brown * DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK)
9095b482a8SLen Brown *
9195b482a8SLen Brown ******************************************************************************/
9295b482a8SLen Brown
9395b482a8SLen Brown void
acpi_ps_append_arg(union acpi_parse_object * op,union acpi_parse_object * arg)9495b482a8SLen Brown acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg)
9595b482a8SLen Brown {
9695b482a8SLen Brown union acpi_parse_object *prev_arg;
9795b482a8SLen Brown const struct acpi_opcode_info *op_info;
9895b482a8SLen Brown
99ce87e09dSBob Moore ACPI_FUNCTION_TRACE(ps_append_arg);
10095b482a8SLen Brown
10195b482a8SLen Brown if (!op) {
102ce87e09dSBob Moore return_VOID;
10395b482a8SLen Brown }
10495b482a8SLen Brown
10595b482a8SLen Brown /* Get the info structure for this opcode */
10695b482a8SLen Brown
10795b482a8SLen Brown op_info = acpi_ps_get_opcode_info(op->common.aml_opcode);
10895b482a8SLen Brown if (op_info->class == AML_CLASS_UNKNOWN) {
10995b482a8SLen Brown
11095b482a8SLen Brown /* Invalid opcode */
11195b482a8SLen Brown
11295b482a8SLen Brown ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X",
11395b482a8SLen Brown op->common.aml_opcode));
114ce87e09dSBob Moore return_VOID;
11595b482a8SLen Brown }
11695b482a8SLen Brown
11795b482a8SLen Brown /* Check if this opcode requires argument sub-objects */
11895b482a8SLen Brown
11995b482a8SLen Brown if (!(op_info->flags & AML_HAS_ARGS)) {
12095b482a8SLen Brown
12195b482a8SLen Brown /* Has no linked argument objects */
12295b482a8SLen Brown
123ce87e09dSBob Moore return_VOID;
12495b482a8SLen Brown }
12595b482a8SLen Brown
12695b482a8SLen Brown /* Append the argument to the linked argument list */
12795b482a8SLen Brown
12895b482a8SLen Brown if (op->common.value.arg) {
12995b482a8SLen Brown
13095b482a8SLen Brown /* Append to existing argument list */
13195b482a8SLen Brown
13295b482a8SLen Brown prev_arg = op->common.value.arg;
13395b482a8SLen Brown while (prev_arg->common.next) {
13495b482a8SLen Brown prev_arg = prev_arg->common.next;
13595b482a8SLen Brown }
13695b482a8SLen Brown prev_arg->common.next = arg;
13795b482a8SLen Brown } else {
13895b482a8SLen Brown /* No argument list, this will be the first argument */
13995b482a8SLen Brown
14095b482a8SLen Brown op->common.value.arg = arg;
14195b482a8SLen Brown }
14295b482a8SLen Brown
14395b482a8SLen Brown /* Set the parent in this arg and any args linked after it */
14495b482a8SLen Brown
14595b482a8SLen Brown while (arg) {
14695b482a8SLen Brown arg->common.parent = op;
14795b482a8SLen Brown arg = arg->common.next;
14895b482a8SLen Brown
14995b482a8SLen Brown op->common.arg_list_length++;
15095b482a8SLen Brown }
151ce87e09dSBob Moore
152ce87e09dSBob Moore return_VOID;
15395b482a8SLen Brown }
15495b482a8SLen Brown
15595b482a8SLen Brown /*******************************************************************************
15695b482a8SLen Brown *
15795b482a8SLen Brown * FUNCTION: acpi_ps_get_depth_next
15895b482a8SLen Brown *
159ba494beeSBob Moore * PARAMETERS: origin - Root of subtree to search
160ba494beeSBob Moore * op - Last (previous) Op that was found
16195b482a8SLen Brown *
16295b482a8SLen Brown * RETURN: Next Op found in the search.
16395b482a8SLen Brown *
16495b482a8SLen Brown * DESCRIPTION: Get next op in tree (walking the tree in depth-first order)
16595b482a8SLen Brown * Return NULL when reaching "origin" or when walking up from root
16695b482a8SLen Brown *
16795b482a8SLen Brown ******************************************************************************/
16895b482a8SLen Brown
acpi_ps_get_depth_next(union acpi_parse_object * origin,union acpi_parse_object * op)16995b482a8SLen Brown union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin,
17095b482a8SLen Brown union acpi_parse_object *op)
17195b482a8SLen Brown {
17295b482a8SLen Brown union acpi_parse_object *next = NULL;
17395b482a8SLen Brown union acpi_parse_object *parent;
17495b482a8SLen Brown union acpi_parse_object *arg;
17595b482a8SLen Brown
17695b482a8SLen Brown ACPI_FUNCTION_ENTRY();
17795b482a8SLen Brown
17895b482a8SLen Brown if (!op) {
17995b482a8SLen Brown return (NULL);
18095b482a8SLen Brown }
18195b482a8SLen Brown
18295b482a8SLen Brown /* Look for an argument or child */
18395b482a8SLen Brown
18495b482a8SLen Brown next = acpi_ps_get_arg(op, 0);
18595b482a8SLen Brown if (next) {
1869cf7adecSBob Moore ASL_CV_LABEL_FILENODE(next);
18795b482a8SLen Brown return (next);
18895b482a8SLen Brown }
18995b482a8SLen Brown
19095b482a8SLen Brown /* Look for a sibling */
19195b482a8SLen Brown
19295b482a8SLen Brown next = op->common.next;
19395b482a8SLen Brown if (next) {
1949cf7adecSBob Moore ASL_CV_LABEL_FILENODE(next);
19595b482a8SLen Brown return (next);
19695b482a8SLen Brown }
19795b482a8SLen Brown
19895b482a8SLen Brown /* Look for a sibling of parent */
19995b482a8SLen Brown
20095b482a8SLen Brown parent = op->common.parent;
20195b482a8SLen Brown
20295b482a8SLen Brown while (parent) {
20395b482a8SLen Brown arg = acpi_ps_get_arg(parent, 0);
20495b482a8SLen Brown while (arg && (arg != origin) && (arg != op)) {
2059cf7adecSBob Moore
2069cf7adecSBob Moore ASL_CV_LABEL_FILENODE(arg);
20795b482a8SLen Brown arg = arg->common.next;
20895b482a8SLen Brown }
20995b482a8SLen Brown
21095b482a8SLen Brown if (arg == origin) {
21195b482a8SLen Brown
21295b482a8SLen Brown /* Reached parent of origin, end search */
21395b482a8SLen Brown
21495b482a8SLen Brown return (NULL);
21595b482a8SLen Brown }
21695b482a8SLen Brown
21795b482a8SLen Brown if (parent->common.next) {
21895b482a8SLen Brown
21995b482a8SLen Brown /* Found sibling of parent */
22095b482a8SLen Brown
2219cf7adecSBob Moore ASL_CV_LABEL_FILENODE(parent->common.next);
22295b482a8SLen Brown return (parent->common.next);
22395b482a8SLen Brown }
22495b482a8SLen Brown
22595b482a8SLen Brown op = parent;
22695b482a8SLen Brown parent = parent->common.parent;
22795b482a8SLen Brown }
22895b482a8SLen Brown
2299cf7adecSBob Moore ASL_CV_LABEL_FILENODE(next);
23095b482a8SLen Brown return (next);
23195b482a8SLen Brown }
23295b482a8SLen Brown
23395b482a8SLen Brown #ifdef ACPI_OBSOLETE_FUNCTIONS
23495b482a8SLen Brown /*******************************************************************************
23595b482a8SLen Brown *
23695b482a8SLen Brown * FUNCTION: acpi_ps_get_child
23795b482a8SLen Brown *
238ba494beeSBob Moore * PARAMETERS: op - Get the child of this Op
23995b482a8SLen Brown *
24095b482a8SLen Brown * RETURN: Child Op, Null if none is found.
24195b482a8SLen Brown *
24295b482a8SLen Brown * DESCRIPTION: Get op's children or NULL if none
24395b482a8SLen Brown *
24495b482a8SLen Brown ******************************************************************************/
24595b482a8SLen Brown
acpi_ps_get_child(union acpi_parse_object * op)24695b482a8SLen Brown union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op)
24795b482a8SLen Brown {
24895b482a8SLen Brown union acpi_parse_object *child = NULL;
24995b482a8SLen Brown
25095b482a8SLen Brown ACPI_FUNCTION_ENTRY();
25195b482a8SLen Brown
25295b482a8SLen Brown switch (op->common.aml_opcode) {
25395b482a8SLen Brown case AML_SCOPE_OP:
25495b482a8SLen Brown case AML_ELSE_OP:
25595b482a8SLen Brown case AML_DEVICE_OP:
25695b482a8SLen Brown case AML_THERMAL_ZONE_OP:
25795b482a8SLen Brown case AML_INT_METHODCALL_OP:
25895b482a8SLen Brown
25995b482a8SLen Brown child = acpi_ps_get_arg(op, 0);
26095b482a8SLen Brown break;
26195b482a8SLen Brown
26295b482a8SLen Brown case AML_BUFFER_OP:
26395b482a8SLen Brown case AML_PACKAGE_OP:
2645a8361f7SSchmauss, Erik case AML_VARIABLE_PACKAGE_OP:
26595b482a8SLen Brown case AML_METHOD_OP:
26695b482a8SLen Brown case AML_IF_OP:
26795b482a8SLen Brown case AML_WHILE_OP:
26895b482a8SLen Brown case AML_FIELD_OP:
26995b482a8SLen Brown
27095b482a8SLen Brown child = acpi_ps_get_arg(op, 1);
27195b482a8SLen Brown break;
27295b482a8SLen Brown
2739ff5a21aSBob Moore case AML_POWER_RESOURCE_OP:
27495b482a8SLen Brown case AML_INDEX_FIELD_OP:
27595b482a8SLen Brown
27695b482a8SLen Brown child = acpi_ps_get_arg(op, 2);
27795b482a8SLen Brown break;
27895b482a8SLen Brown
27995b482a8SLen Brown case AML_PROCESSOR_OP:
28095b482a8SLen Brown case AML_BANK_FIELD_OP:
28195b482a8SLen Brown
28295b482a8SLen Brown child = acpi_ps_get_arg(op, 3);
28395b482a8SLen Brown break;
28495b482a8SLen Brown
28595b482a8SLen Brown default:
2861d1ea1b7SChao Guan
28795b482a8SLen Brown /* All others have no children */
2881d1ea1b7SChao Guan
28995b482a8SLen Brown break;
29095b482a8SLen Brown }
29195b482a8SLen Brown
29295b482a8SLen Brown return (child);
29395b482a8SLen Brown }
29495b482a8SLen Brown #endif
295