xref: /openbmc/linux/drivers/acpi/acpica/psutils.c (revision 1ac731c529cd4d6adbce134754b51ff7d822b145)
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