| 1 | // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 | 
|---|
| 2 | /****************************************************************************** | 
|---|
| 3 | * | 
|---|
| 4 | * Module Name: psutils - Parser miscellaneous utilities (Parser only) | 
|---|
| 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 "acconvert.h" | 
|---|
| 15 |  | 
|---|
| 16 | #define _COMPONENT          ACPI_PARSER | 
|---|
| 17 | ACPI_MODULE_NAME( "psutils") | 
|---|
| 18 |  | 
|---|
| 19 | /******************************************************************************* | 
|---|
| 20 | * | 
|---|
| 21 | * FUNCTION:    acpi_ps_create_scope_op | 
|---|
| 22 | * | 
|---|
| 23 | * PARAMETERS:  None | 
|---|
| 24 | * | 
|---|
| 25 | * RETURN:      A new Scope object, null on failure | 
|---|
| 26 | * | 
|---|
| 27 | * DESCRIPTION: Create a Scope and associated namepath op with the root name | 
|---|
| 28 | * | 
|---|
| 29 | ******************************************************************************/ | 
|---|
| 30 | union acpi_parse_object *acpi_ps_create_scope_op(u8 *aml) | 
|---|
| 31 | { | 
|---|
| 32 | union acpi_parse_object *scope_op; | 
|---|
| 33 |  | 
|---|
| 34 | scope_op = acpi_ps_alloc_op(AML_SCOPE_OP, aml); | 
|---|
| 35 | if (!scope_op) { | 
|---|
| 36 | return (NULL); | 
|---|
| 37 | } | 
|---|
| 38 |  | 
|---|
| 39 | scope_op->named.name = ACPI_ROOT_NAME; | 
|---|
| 40 | return (scope_op); | 
|---|
| 41 | } | 
|---|
| 42 |  | 
|---|
| 43 | /******************************************************************************* | 
|---|
| 44 | * | 
|---|
| 45 | * FUNCTION:    acpi_ps_init_op | 
|---|
| 46 | * | 
|---|
| 47 | * PARAMETERS:  op              - A newly allocated Op object | 
|---|
| 48 | *              opcode          - Opcode to store in the Op | 
|---|
| 49 | * | 
|---|
| 50 | * RETURN:      None | 
|---|
| 51 | * | 
|---|
| 52 | * DESCRIPTION: Initialize a parse (Op) object | 
|---|
| 53 | * | 
|---|
| 54 | ******************************************************************************/ | 
|---|
| 55 |  | 
|---|
| 56 | void acpi_ps_init_op(union acpi_parse_object *op, u16 opcode) | 
|---|
| 57 | { | 
|---|
| 58 | ACPI_FUNCTION_ENTRY(); | 
|---|
| 59 |  | 
|---|
| 60 | op->common.descriptor_type = ACPI_DESC_TYPE_PARSER; | 
|---|
| 61 | op->common.aml_opcode = opcode; | 
|---|
| 62 |  | 
|---|
| 63 | ACPI_DISASM_ONLY_MEMBERS(acpi_ut_safe_strncpy(op->common.aml_op_name, | 
|---|
| 64 | (acpi_ps_get_opcode_info | 
|---|
| 65 | (opcode))->name, | 
|---|
| 66 | sizeof(op->common. | 
|---|
| 67 | aml_op_name))); | 
|---|
| 68 | } | 
|---|
| 69 |  | 
|---|
| 70 | /******************************************************************************* | 
|---|
| 71 | * | 
|---|
| 72 | * FUNCTION:    acpi_ps_alloc_op | 
|---|
| 73 | * | 
|---|
| 74 | * PARAMETERS:  opcode          - Opcode that will be stored in the new Op | 
|---|
| 75 | *              aml             - Address of the opcode | 
|---|
| 76 | * | 
|---|
| 77 | * RETURN:      Pointer to the new Op, null on failure | 
|---|
| 78 | * | 
|---|
| 79 | * DESCRIPTION: Allocate an acpi_op, choose op type (and thus size) based on | 
|---|
| 80 | *              opcode. A cache of opcodes is available for the pure | 
|---|
| 81 | *              GENERIC_OP, since this is by far the most commonly used. | 
|---|
| 82 | * | 
|---|
| 83 | ******************************************************************************/ | 
|---|
| 84 |  | 
|---|
| 85 | union acpi_parse_object *acpi_ps_alloc_op(u16 opcode, u8 *aml) | 
|---|
| 86 | { | 
|---|
| 87 | union acpi_parse_object *op; | 
|---|
| 88 | const struct acpi_opcode_info *op_info; | 
|---|
| 89 | u8 flags = ACPI_PARSEOP_GENERIC; | 
|---|
| 90 |  | 
|---|
| 91 | ACPI_FUNCTION_ENTRY(); | 
|---|
| 92 |  | 
|---|
| 93 | op_info = acpi_ps_get_opcode_info(opcode); | 
|---|
| 94 |  | 
|---|
| 95 | /* Determine type of parse_op required */ | 
|---|
| 96 |  | 
|---|
| 97 | if (op_info->flags & AML_DEFER) { | 
|---|
| 98 | flags = ACPI_PARSEOP_DEFERRED; | 
|---|
| 99 | } else if (op_info->flags & AML_NAMED) { | 
|---|
| 100 | flags = ACPI_PARSEOP_NAMED_OBJECT; | 
|---|
| 101 | } else if (opcode == AML_INT_BYTELIST_OP) { | 
|---|
| 102 | flags = ACPI_PARSEOP_BYTELIST; | 
|---|
| 103 | } | 
|---|
| 104 |  | 
|---|
| 105 | /* Allocate the minimum required size object */ | 
|---|
| 106 |  | 
|---|
| 107 | if (flags == ACPI_PARSEOP_GENERIC) { | 
|---|
| 108 |  | 
|---|
| 109 | /* The generic op (default) is by far the most common (16 to 1) */ | 
|---|
| 110 |  | 
|---|
| 111 | op = acpi_os_acquire_object(acpi_gbl_ps_node_cache); | 
|---|
| 112 | } else { | 
|---|
| 113 | /* Extended parseop */ | 
|---|
| 114 |  | 
|---|
| 115 | op = acpi_os_acquire_object(acpi_gbl_ps_node_ext_cache); | 
|---|
| 116 | } | 
|---|
| 117 |  | 
|---|
| 118 | /* Initialize the Op */ | 
|---|
| 119 |  | 
|---|
| 120 | if (op) { | 
|---|
| 121 | acpi_ps_init_op(op, opcode); | 
|---|
| 122 | op->common.aml = aml; | 
|---|
| 123 | op->common.flags = flags; | 
|---|
| 124 | ASL_CV_CLEAR_OP_COMMENTS(op); | 
|---|
| 125 |  | 
|---|
| 126 | if (opcode == AML_SCOPE_OP) { | 
|---|
| 127 | acpi_gbl_current_scope = op; | 
|---|
| 128 | } | 
|---|
| 129 |  | 
|---|
| 130 | if (acpi_gbl_capture_comments) { | 
|---|
| 131 | ASL_CV_TRANSFER_COMMENTS(op); | 
|---|
| 132 | } | 
|---|
| 133 | } | 
|---|
| 134 |  | 
|---|
| 135 | return (op); | 
|---|
| 136 | } | 
|---|
| 137 |  | 
|---|
| 138 | /******************************************************************************* | 
|---|
| 139 | * | 
|---|
| 140 | * FUNCTION:    acpi_ps_free_op | 
|---|
| 141 | * | 
|---|
| 142 | * PARAMETERS:  op              - Op to be freed | 
|---|
| 143 | * | 
|---|
| 144 | * RETURN:      None. | 
|---|
| 145 | * | 
|---|
| 146 | * DESCRIPTION: Free an Op object. Either put it on the GENERIC_OP cache list | 
|---|
| 147 | *              or actually free it. | 
|---|
| 148 | * | 
|---|
| 149 | ******************************************************************************/ | 
|---|
| 150 |  | 
|---|
| 151 | void acpi_ps_free_op(union acpi_parse_object *op) | 
|---|
| 152 | { | 
|---|
| 153 | ACPI_FUNCTION_NAME(ps_free_op); | 
|---|
| 154 |  | 
|---|
| 155 | ASL_CV_CLEAR_OP_COMMENTS(op); | 
|---|
| 156 | if (op->common.aml_opcode == AML_INT_RETURN_VALUE_OP) { | 
|---|
| 157 | ACPI_DEBUG_PRINT((ACPI_DB_ALLOCATIONS, | 
|---|
| 158 | "Free retval op: %p\n", op)); | 
|---|
| 159 | } | 
|---|
| 160 |  | 
|---|
| 161 | if (op->common.flags & ACPI_PARSEOP_GENERIC) { | 
|---|
| 162 | (void)acpi_os_release_object(cache: acpi_gbl_ps_node_cache, object: op); | 
|---|
| 163 | } else { | 
|---|
| 164 | (void)acpi_os_release_object(cache: acpi_gbl_ps_node_ext_cache, object: op); | 
|---|
| 165 | } | 
|---|
| 166 | } | 
|---|
| 167 |  | 
|---|
| 168 | /******************************************************************************* | 
|---|
| 169 | * | 
|---|
| 170 | * FUNCTION:    Utility functions | 
|---|
| 171 | * | 
|---|
| 172 | * DESCRIPTION: Low level character and object functions | 
|---|
| 173 | * | 
|---|
| 174 | ******************************************************************************/ | 
|---|
| 175 |  | 
|---|
| 176 | /* | 
|---|
| 177 | * Is "c" a namestring lead character? | 
|---|
| 178 | */ | 
|---|
| 179 | u8 acpi_ps_is_leading_char(u32 c) | 
|---|
| 180 | { | 
|---|
| 181 | return ((u8) (c == '_' || (c >= 'A' && c <= 'Z'))); | 
|---|
| 182 | } | 
|---|
| 183 |  | 
|---|
| 184 | /* | 
|---|
| 185 | * Get op's name (4-byte name segment) or 0 if unnamed | 
|---|
| 186 | */ | 
|---|
| 187 | u32 acpi_ps_get_name(union acpi_parse_object * op) | 
|---|
| 188 | { | 
|---|
| 189 |  | 
|---|
| 190 | /* The "generic" object has no name associated with it */ | 
|---|
| 191 |  | 
|---|
| 192 | if (op->common.flags & ACPI_PARSEOP_GENERIC) { | 
|---|
| 193 | return (0); | 
|---|
| 194 | } | 
|---|
| 195 |  | 
|---|
| 196 | /* Only the "Extended" parse objects have a name */ | 
|---|
| 197 |  | 
|---|
| 198 | return (op->named.name); | 
|---|
| 199 | } | 
|---|
| 200 |  | 
|---|
| 201 | /* | 
|---|
| 202 | * Set op's name | 
|---|
| 203 | */ | 
|---|
| 204 | void acpi_ps_set_name(union acpi_parse_object *op, u32 name) | 
|---|
| 205 | { | 
|---|
| 206 |  | 
|---|
| 207 | /* The "generic" object has no name associated with it */ | 
|---|
| 208 |  | 
|---|
| 209 | if (op->common.flags & ACPI_PARSEOP_GENERIC) { | 
|---|
| 210 | return; | 
|---|
| 211 | } | 
|---|
| 212 |  | 
|---|
| 213 | op->named.name = name; | 
|---|
| 214 | } | 
|---|
| 215 |  | 
|---|