195857638SErik Schmauss // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
295b482a8SLen Brown /******************************************************************************
395b482a8SLen Brown *
495b482a8SLen Brown * Module Name: psutils - Parser miscellaneous utilities (Parser only)
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("psutils")
1895b482a8SLen Brown
1995b482a8SLen Brown /*******************************************************************************
2095b482a8SLen Brown *
2195b482a8SLen Brown * FUNCTION: acpi_ps_create_scope_op
2295b482a8SLen Brown *
2395b482a8SLen Brown * PARAMETERS: None
2495b482a8SLen Brown *
2595b482a8SLen Brown * RETURN: A new Scope object, null on failure
2695b482a8SLen Brown *
2795b482a8SLen Brown * DESCRIPTION: Create a Scope and associated namepath op with the root name
2895b482a8SLen Brown *
2995b482a8SLen Brown ******************************************************************************/
acpi_ps_create_scope_op(u8 * aml)3062eb935bSLv Zheng union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml)
3195b482a8SLen Brown {
3295b482a8SLen Brown union acpi_parse_object *scope_op;
3395b482a8SLen Brown
3462eb935bSLv Zheng scope_op = acpi_ps_alloc_op(AML_SCOPE_OP, aml);
3595b482a8SLen Brown if (!scope_op) {
3695b482a8SLen Brown return (NULL);
3795b482a8SLen Brown }
3895b482a8SLen Brown
3995b482a8SLen Brown scope_op->named.name = ACPI_ROOT_NAME;
4095b482a8SLen Brown return (scope_op);
4195b482a8SLen Brown }
4295b482a8SLen Brown
4395b482a8SLen Brown /*******************************************************************************
4495b482a8SLen Brown *
4595b482a8SLen Brown * FUNCTION: acpi_ps_init_op
4695b482a8SLen Brown *
47ba494beeSBob Moore * PARAMETERS: op - A newly allocated Op object
48ba494beeSBob Moore * opcode - Opcode to store in the Op
4995b482a8SLen Brown *
5095b482a8SLen Brown * RETURN: None
5195b482a8SLen Brown *
5295b482a8SLen Brown * DESCRIPTION: Initialize a parse (Op) object
5395b482a8SLen Brown *
5495b482a8SLen Brown ******************************************************************************/
5595b482a8SLen Brown
acpi_ps_init_op(union acpi_parse_object * op,u16 opcode)5695b482a8SLen Brown void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode)
5795b482a8SLen Brown {
5895b482a8SLen Brown ACPI_FUNCTION_ENTRY();
5995b482a8SLen Brown
6095b482a8SLen Brown op->common.descriptor_type = ACPI_DESC_TYPE_PARSER;
6195b482a8SLen Brown op->common.aml_opcode = opcode;
6295b482a8SLen Brown
63ee68d477SBob Moore ACPI_DISASM_ONLY_MEMBERS(acpi_ut_safe_strncpy(op->common.aml_op_name,
64ee68d477SBob Moore (acpi_ps_get_opcode_info
65ee68d477SBob Moore (opcode))->name,
66ee68d477SBob Moore sizeof(op->common.
67ee68d477SBob Moore aml_op_name)));
6895b482a8SLen Brown }
6995b482a8SLen Brown
7095b482a8SLen Brown /*******************************************************************************
7195b482a8SLen Brown *
7295b482a8SLen Brown * FUNCTION: acpi_ps_alloc_op
7395b482a8SLen Brown *
74ba494beeSBob Moore * PARAMETERS: opcode - Opcode that will be stored in the new Op
7562eb935bSLv Zheng * aml - Address of the opcode
7695b482a8SLen Brown *
7795b482a8SLen Brown * RETURN: Pointer to the new Op, null on failure
7895b482a8SLen Brown *
7995b482a8SLen Brown * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on
8095b482a8SLen Brown * opcode. A cache of opcodes is available for the pure
8195b482a8SLen Brown * GENERIC_OP, since this is by far the most commonly used.
8295b482a8SLen Brown *
8395b482a8SLen Brown ******************************************************************************/
8495b482a8SLen Brown
acpi_ps_alloc_op(u16 opcode,u8 * aml)8562eb935bSLv Zheng union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml)
8695b482a8SLen Brown {
8795b482a8SLen Brown union acpi_parse_object *op;
8895b482a8SLen Brown const struct acpi_opcode_info *op_info;
8995b482a8SLen Brown u8 flags = ACPI_PARSEOP_GENERIC;
9095b482a8SLen Brown
9195b482a8SLen Brown ACPI_FUNCTION_ENTRY();
9295b482a8SLen Brown
9395b482a8SLen Brown op_info = acpi_ps_get_opcode_info(opcode);
9495b482a8SLen Brown
9595b482a8SLen Brown /* Determine type of parse_op required */
9695b482a8SLen Brown
9795b482a8SLen Brown if (op_info->flags & AML_DEFER) {
9895b482a8SLen Brown flags = ACPI_PARSEOP_DEFERRED;
9995b482a8SLen Brown } else if (op_info->flags & AML_NAMED) {
1005391abfdSBob Moore flags = ACPI_PARSEOP_NAMED_OBJECT;
10195b482a8SLen Brown } else if (opcode == AML_INT_BYTELIST_OP) {
10295b482a8SLen Brown flags = ACPI_PARSEOP_BYTELIST;
10395b482a8SLen Brown }
10495b482a8SLen Brown
10595b482a8SLen Brown /* Allocate the minimum required size object */
10695b482a8SLen Brown
10795b482a8SLen Brown if (flags == ACPI_PARSEOP_GENERIC) {
10895b482a8SLen Brown
10995b482a8SLen Brown /* The generic op (default) is by far the most common (16 to 1) */
11095b482a8SLen Brown
11195b482a8SLen Brown op = acpi_os_acquire_object(acpi_gbl_ps_node_cache);
11295b482a8SLen Brown } else {
11395b482a8SLen Brown /* Extended parseop */
11495b482a8SLen Brown
11595b482a8SLen Brown op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache);
11695b482a8SLen Brown }
11795b482a8SLen Brown
11895b482a8SLen Brown /* Initialize the Op */
11995b482a8SLen Brown
12095b482a8SLen Brown if (op) {
12195b482a8SLen Brown acpi_ps_init_op(op, opcode);
12262eb935bSLv Zheng op->common.aml = aml;
12395b482a8SLen Brown op->common.flags = flags;
1249cf7adecSBob Moore ASL_CV_CLEAR_OP_COMMENTS(op);
1259cf7adecSBob Moore
1269cf7adecSBob Moore if (opcode == AML_SCOPE_OP) {
1279cf7adecSBob Moore acpi_gbl_current_scope = op;
1289cf7adecSBob Moore }
1299cf7adecSBob Moore
130ee174d35SBob Moore if (acpi_gbl_capture_comments) {
1319cf7adecSBob Moore ASL_CV_TRANSFER_COMMENTS(op);
13295b482a8SLen Brown }
13329ad1f88SColin Ian King }
13495b482a8SLen Brown
13595b482a8SLen Brown return (op);
13695b482a8SLen Brown }
13795b482a8SLen Brown
13895b482a8SLen Brown /*******************************************************************************
13995b482a8SLen Brown *
14095b482a8SLen Brown * FUNCTION: acpi_ps_free_op
14195b482a8SLen Brown *
142ba494beeSBob Moore * PARAMETERS: op - Op to be freed
14395b482a8SLen Brown *
14495b482a8SLen Brown * RETURN: None.
14595b482a8SLen Brown *
14695b482a8SLen Brown * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list
14795b482a8SLen Brown * or actually free it.
14895b482a8SLen Brown *
14995b482a8SLen Brown ******************************************************************************/
15095b482a8SLen Brown
acpi_ps_free_op(union acpi_parse_object * op)15195b482a8SLen Brown void acpi_ps_free_op(union acpi_parse_object *op)
15295b482a8SLen Brown {
15395b482a8SLen Brown ACPI_FUNCTION_NAME(ps_free_op);
15495b482a8SLen Brown
1559cf7adecSBob Moore ASL_CV_CLEAR_OP_COMMENTS(op);
15695b482a8SLen Brown if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) {
1571fad8738SBob Moore ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS,
1581fad8738SBob Moore "Free retval op: %p\n", op));
15995b482a8SLen Brown }
16095b482a8SLen Brown
16195b482a8SLen Brown if (op->common.flags & ACPI_PARSEOP_GENERIC) {
16295b482a8SLen Brown (void)acpi_os_release_object(acpi_gbl_ps_node_cache, op);
16395b482a8SLen Brown } else {
16495b482a8SLen Brown (void)acpi_os_release_object(acpi_gbl_ps_node_ext_cache, op);
16595b482a8SLen Brown }
16695b482a8SLen Brown }
16795b482a8SLen Brown
16895b482a8SLen Brown /*******************************************************************************
16995b482a8SLen Brown *
17095b482a8SLen Brown * FUNCTION: Utility functions
17195b482a8SLen Brown *
17295b482a8SLen Brown * DESCRIPTION: Low level character and object functions
17395b482a8SLen Brown *
17495b482a8SLen Brown ******************************************************************************/
17595b482a8SLen Brown
17695b482a8SLen Brown /*
17795b482a8SLen Brown * Is "c" a namestring lead character?
17895b482a8SLen Brown */
acpi_ps_is_leading_char(u32 c)17995b482a8SLen Brown u8 acpi_ps_is_leading_char(u32 c)
18095b482a8SLen Brown {
18195b482a8SLen Brown return ((u8) (c == '_' || (c >= 'A' && c <= 'Z')));
18295b482a8SLen Brown }
18395b482a8SLen Brown
18495b482a8SLen Brown /*
18595b482a8SLen Brown * Get op's name (4-byte name segment) or 0 if unnamed
18695b482a8SLen Brown */
acpi_ps_get_name(union acpi_parse_object * op)18795b482a8SLen Brown u32 acpi_ps_get_name(union acpi_parse_object * op)
18895b482a8SLen Brown {
18995b482a8SLen Brown
19095b482a8SLen Brown /* The "generic" object has no name associated with it */
19195b482a8SLen Brown
19295b482a8SLen Brown if (op->common.flags & ACPI_PARSEOP_GENERIC) {
19395b482a8SLen Brown return (0);
19495b482a8SLen Brown }
19595b482a8SLen Brown
19695b482a8SLen Brown /* Only the "Extended" parse objects have a name */
19795b482a8SLen Brown
19895b482a8SLen Brown return (op->named.name);
19995b482a8SLen Brown }
20095b482a8SLen Brown
20195b482a8SLen Brown /*
20295b482a8SLen Brown * Set op's name
20395b482a8SLen Brown */
acpi_ps_set_name(union acpi_parse_object * op,u32 name)20495b482a8SLen Brown void acpi_ps_set_name(union acpi_parse_object *op, u32 name)
20595b482a8SLen Brown {
20695b482a8SLen Brown
20795b482a8SLen Brown /* The "generic" object has no name associated with it */
20895b482a8SLen Brown
20995b482a8SLen Brown if (op->common.flags & ACPI_PARSEOP_GENERIC) {
21095b482a8SLen Brown return;
21195b482a8SLen Brown }
21295b482a8SLen Brown
21395b482a8SLen Brown op->named.name = name;
21495b482a8SLen Brown }
215