mirror of https://github.com/Qortal/Brooklyn
You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
294 lines
6.3 KiB
294 lines
6.3 KiB
// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 |
|
/****************************************************************************** |
|
* |
|
* Module Name: pstree - Parser op tree manipulation/traversal/search |
|
* |
|
* Copyright (C) 2000 - 2021, Intel Corp. |
|
* |
|
*****************************************************************************/ |
|
|
|
#include <acpi/acpi.h> |
|
#include "accommon.h" |
|
#include "acparser.h" |
|
#include "amlcode.h" |
|
#include "acconvert.h" |
|
|
|
#define _COMPONENT ACPI_PARSER |
|
ACPI_MODULE_NAME("pstree") |
|
|
|
/* Local prototypes */ |
|
#ifdef ACPI_OBSOLETE_FUNCTIONS |
|
union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op); |
|
#endif |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_ps_get_arg |
|
* |
|
* PARAMETERS: op - Get an argument for this op |
|
* argn - Nth argument to get |
|
* |
|
* RETURN: The argument (as an Op object). NULL if argument does not exist |
|
* |
|
* DESCRIPTION: Get the specified op's argument. |
|
* |
|
******************************************************************************/ |
|
|
|
union acpi_parse_object *acpi_ps_get_arg(union acpi_parse_object *op, u32 argn) |
|
{ |
|
union acpi_parse_object *arg = NULL; |
|
const struct acpi_opcode_info *op_info; |
|
|
|
ACPI_FUNCTION_ENTRY(); |
|
|
|
/* |
|
if (Op->Common.aml_opcode == AML_INT_CONNECTION_OP) |
|
{ |
|
return (Op->Common.Value.Arg); |
|
} |
|
*/ |
|
/* Get the info structure for this opcode */ |
|
|
|
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); |
|
if (op_info->class == AML_CLASS_UNKNOWN) { |
|
|
|
/* Invalid opcode or ASCII character */ |
|
|
|
return (NULL); |
|
} |
|
|
|
/* Check if this opcode requires argument sub-objects */ |
|
|
|
if (!(op_info->flags & AML_HAS_ARGS)) { |
|
|
|
/* Has no linked argument objects */ |
|
|
|
return (NULL); |
|
} |
|
|
|
/* Get the requested argument object */ |
|
|
|
arg = op->common.value.arg; |
|
while (arg && argn) { |
|
argn--; |
|
arg = arg->common.next; |
|
} |
|
|
|
return (arg); |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_ps_append_arg |
|
* |
|
* PARAMETERS: op - Append an argument to this Op. |
|
* arg - Argument Op to append |
|
* |
|
* RETURN: None. |
|
* |
|
* DESCRIPTION: Append an argument to an op's argument list (a NULL arg is OK) |
|
* |
|
******************************************************************************/ |
|
|
|
void |
|
acpi_ps_append_arg(union acpi_parse_object *op, union acpi_parse_object *arg) |
|
{ |
|
union acpi_parse_object *prev_arg; |
|
const struct acpi_opcode_info *op_info; |
|
|
|
ACPI_FUNCTION_TRACE(ps_append_arg); |
|
|
|
if (!op) { |
|
return_VOID; |
|
} |
|
|
|
/* Get the info structure for this opcode */ |
|
|
|
op_info = acpi_ps_get_opcode_info(op->common.aml_opcode); |
|
if (op_info->class == AML_CLASS_UNKNOWN) { |
|
|
|
/* Invalid opcode */ |
|
|
|
ACPI_ERROR((AE_INFO, "Invalid AML Opcode: 0x%2.2X", |
|
op->common.aml_opcode)); |
|
return_VOID; |
|
} |
|
|
|
/* Check if this opcode requires argument sub-objects */ |
|
|
|
if (!(op_info->flags & AML_HAS_ARGS)) { |
|
|
|
/* Has no linked argument objects */ |
|
|
|
return_VOID; |
|
} |
|
|
|
/* Append the argument to the linked argument list */ |
|
|
|
if (op->common.value.arg) { |
|
|
|
/* Append to existing argument list */ |
|
|
|
prev_arg = op->common.value.arg; |
|
while (prev_arg->common.next) { |
|
prev_arg = prev_arg->common.next; |
|
} |
|
prev_arg->common.next = arg; |
|
} else { |
|
/* No argument list, this will be the first argument */ |
|
|
|
op->common.value.arg = arg; |
|
} |
|
|
|
/* Set the parent in this arg and any args linked after it */ |
|
|
|
while (arg) { |
|
arg->common.parent = op; |
|
arg = arg->common.next; |
|
|
|
op->common.arg_list_length++; |
|
} |
|
|
|
return_VOID; |
|
} |
|
|
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_ps_get_depth_next |
|
* |
|
* PARAMETERS: origin - Root of subtree to search |
|
* op - Last (previous) Op that was found |
|
* |
|
* RETURN: Next Op found in the search. |
|
* |
|
* DESCRIPTION: Get next op in tree (walking the tree in depth-first order) |
|
* Return NULL when reaching "origin" or when walking up from root |
|
* |
|
******************************************************************************/ |
|
|
|
union acpi_parse_object *acpi_ps_get_depth_next(union acpi_parse_object *origin, |
|
union acpi_parse_object *op) |
|
{ |
|
union acpi_parse_object *next = NULL; |
|
union acpi_parse_object *parent; |
|
union acpi_parse_object *arg; |
|
|
|
ACPI_FUNCTION_ENTRY(); |
|
|
|
if (!op) { |
|
return (NULL); |
|
} |
|
|
|
/* Look for an argument or child */ |
|
|
|
next = acpi_ps_get_arg(op, 0); |
|
if (next) { |
|
ASL_CV_LABEL_FILENODE(next); |
|
return (next); |
|
} |
|
|
|
/* Look for a sibling */ |
|
|
|
next = op->common.next; |
|
if (next) { |
|
ASL_CV_LABEL_FILENODE(next); |
|
return (next); |
|
} |
|
|
|
/* Look for a sibling of parent */ |
|
|
|
parent = op->common.parent; |
|
|
|
while (parent) { |
|
arg = acpi_ps_get_arg(parent, 0); |
|
while (arg && (arg != origin) && (arg != op)) { |
|
|
|
ASL_CV_LABEL_FILENODE(arg); |
|
arg = arg->common.next; |
|
} |
|
|
|
if (arg == origin) { |
|
|
|
/* Reached parent of origin, end search */ |
|
|
|
return (NULL); |
|
} |
|
|
|
if (parent->common.next) { |
|
|
|
/* Found sibling of parent */ |
|
|
|
ASL_CV_LABEL_FILENODE(parent->common.next); |
|
return (parent->common.next); |
|
} |
|
|
|
op = parent; |
|
parent = parent->common.parent; |
|
} |
|
|
|
ASL_CV_LABEL_FILENODE(next); |
|
return (next); |
|
} |
|
|
|
#ifdef ACPI_OBSOLETE_FUNCTIONS |
|
/******************************************************************************* |
|
* |
|
* FUNCTION: acpi_ps_get_child |
|
* |
|
* PARAMETERS: op - Get the child of this Op |
|
* |
|
* RETURN: Child Op, Null if none is found. |
|
* |
|
* DESCRIPTION: Get op's children or NULL if none |
|
* |
|
******************************************************************************/ |
|
|
|
union acpi_parse_object *acpi_ps_get_child(union acpi_parse_object *op) |
|
{ |
|
union acpi_parse_object *child = NULL; |
|
|
|
ACPI_FUNCTION_ENTRY(); |
|
|
|
switch (op->common.aml_opcode) { |
|
case AML_SCOPE_OP: |
|
case AML_ELSE_OP: |
|
case AML_DEVICE_OP: |
|
case AML_THERMAL_ZONE_OP: |
|
case AML_INT_METHODCALL_OP: |
|
|
|
child = acpi_ps_get_arg(op, 0); |
|
break; |
|
|
|
case AML_BUFFER_OP: |
|
case AML_PACKAGE_OP: |
|
case AML_VARIABLE_PACKAGE_OP: |
|
case AML_METHOD_OP: |
|
case AML_IF_OP: |
|
case AML_WHILE_OP: |
|
case AML_FIELD_OP: |
|
|
|
child = acpi_ps_get_arg(op, 1); |
|
break; |
|
|
|
case AML_POWER_RESOURCE_OP: |
|
case AML_INDEX_FIELD_OP: |
|
|
|
child = acpi_ps_get_arg(op, 2); |
|
break; |
|
|
|
case AML_PROCESSOR_OP: |
|
case AML_BANK_FIELD_OP: |
|
|
|
child = acpi_ps_get_arg(op, 3); |
|
break; |
|
|
|
default: |
|
|
|
/* All others have no children */ |
|
|
|
break; |
|
} |
|
|
|
return (child); |
|
} |
|
#endif
|
|
|