cachepc-linux

Fork of AMDESE/linux with modifications for CachePC side-channel attack
git clone https://git.sinitax.com/sinitax/cachepc-linux
Log | Files | Refs | README | LICENSE | sfeed.txt

psloop.c (14886B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: psloop - Main AML parse loop
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10/*
     11 * Parse the AML and build an operation tree as most interpreters, (such as
     12 * Perl) do. Parsing is done by hand rather than with a YACC generated parser
     13 * to tightly constrain stack and dynamic memory usage. Parsing is kept
     14 * flexible and the code fairly compact by parsing based on a list of AML
     15 * opcode templates in aml_op_info[].
     16 */
     17
     18#include <acpi/acpi.h>
     19#include "accommon.h"
     20#include "acinterp.h"
     21#include "acparser.h"
     22#include "acdispat.h"
     23#include "amlcode.h"
     24#include "acconvert.h"
     25#include "acnamesp.h"
     26
     27#define _COMPONENT          ACPI_PARSER
     28ACPI_MODULE_NAME("psloop")
     29
     30/* Local prototypes */
     31static acpi_status
     32acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
     33		      u8 * aml_op_start, union acpi_parse_object *op);
     34
     35/*******************************************************************************
     36 *
     37 * FUNCTION:    acpi_ps_get_arguments
     38 *
     39 * PARAMETERS:  walk_state          - Current state
     40 *              aml_op_start        - Op start in AML
     41 *              op                  - Current Op
     42 *
     43 * RETURN:      Status
     44 *
     45 * DESCRIPTION: Get arguments for passed Op.
     46 *
     47 ******************************************************************************/
     48
     49static acpi_status
     50acpi_ps_get_arguments(struct acpi_walk_state *walk_state,
     51		      u8 * aml_op_start, union acpi_parse_object *op)
     52{
     53	acpi_status status = AE_OK;
     54	union acpi_parse_object *arg = NULL;
     55
     56	ACPI_FUNCTION_TRACE_PTR(ps_get_arguments, walk_state);
     57
     58	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
     59			  "Get arguments for opcode [%s]\n",
     60			  op->common.aml_op_name));
     61
     62	switch (op->common.aml_opcode) {
     63	case AML_BYTE_OP:	/* AML_BYTEDATA_ARG */
     64	case AML_WORD_OP:	/* AML_WORDDATA_ARG */
     65	case AML_DWORD_OP:	/* AML_DWORDATA_ARG */
     66	case AML_QWORD_OP:	/* AML_QWORDATA_ARG */
     67	case AML_STRING_OP:	/* AML_ASCIICHARLIST_ARG */
     68
     69		/* Fill in constant or string argument directly */
     70
     71		acpi_ps_get_next_simple_arg(&(walk_state->parser_state),
     72					    GET_CURRENT_ARG_TYPE(walk_state->
     73								 arg_types),
     74					    op);
     75		break;
     76
     77	case AML_INT_NAMEPATH_OP:	/* AML_NAMESTRING_ARG */
     78
     79		status = acpi_ps_get_next_namepath(walk_state,
     80						   &(walk_state->parser_state),
     81						   op,
     82						   ACPI_POSSIBLE_METHOD_CALL);
     83		if (ACPI_FAILURE(status)) {
     84			return_ACPI_STATUS(status);
     85		}
     86
     87		walk_state->arg_types = 0;
     88		break;
     89
     90	default:
     91		/*
     92		 * Op is not a constant or string, append each argument to the Op
     93		 */
     94		while (GET_CURRENT_ARG_TYPE(walk_state->arg_types) &&
     95		       !walk_state->arg_count) {
     96			walk_state->aml = walk_state->parser_state.aml;
     97
     98			switch (op->common.aml_opcode) {
     99			case AML_METHOD_OP:
    100			case AML_BUFFER_OP:
    101			case AML_PACKAGE_OP:
    102			case AML_VARIABLE_PACKAGE_OP:
    103			case AML_WHILE_OP:
    104
    105				break;
    106
    107			default:
    108
    109				ASL_CV_CAPTURE_COMMENTS(walk_state);
    110				break;
    111			}
    112
    113			status =
    114			    acpi_ps_get_next_arg(walk_state,
    115						 &(walk_state->parser_state),
    116						 GET_CURRENT_ARG_TYPE
    117						 (walk_state->arg_types), &arg);
    118			if (ACPI_FAILURE(status)) {
    119				return_ACPI_STATUS(status);
    120			}
    121
    122			if (arg) {
    123				acpi_ps_append_arg(op, arg);
    124			}
    125
    126			INCREMENT_ARG_LIST(walk_state->arg_types);
    127		}
    128
    129		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    130				  "Final argument count: %8.8X pass %u\n",
    131				  walk_state->arg_count,
    132				  walk_state->pass_number));
    133
    134		/* Special processing for certain opcodes */
    135
    136		switch (op->common.aml_opcode) {
    137		case AML_METHOD_OP:
    138			/*
    139			 * Skip parsing of control method because we don't have enough
    140			 * info in the first pass to parse it correctly.
    141			 *
    142			 * Save the length and address of the body
    143			 */
    144			op->named.data = walk_state->parser_state.aml;
    145			op->named.length = (u32)
    146			    (walk_state->parser_state.pkg_end -
    147			     walk_state->parser_state.aml);
    148
    149			/* Skip body of method */
    150
    151			walk_state->parser_state.aml =
    152			    walk_state->parser_state.pkg_end;
    153			walk_state->arg_count = 0;
    154			break;
    155
    156		case AML_BUFFER_OP:
    157		case AML_PACKAGE_OP:
    158		case AML_VARIABLE_PACKAGE_OP:
    159
    160			if ((op->common.parent) &&
    161			    (op->common.parent->common.aml_opcode ==
    162			     AML_NAME_OP)
    163			    && (walk_state->pass_number <=
    164				ACPI_IMODE_LOAD_PASS2)) {
    165				ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    166						  "Setup Package/Buffer: Pass %u, AML Ptr: %p\n",
    167						  walk_state->pass_number,
    168						  aml_op_start));
    169
    170				/*
    171				 * Skip parsing of Buffers and Packages because we don't have
    172				 * enough info in the first pass to parse them correctly.
    173				 */
    174				op->named.data = aml_op_start;
    175				op->named.length = (u32)
    176				    (walk_state->parser_state.pkg_end -
    177				     aml_op_start);
    178
    179				/* Skip body */
    180
    181				walk_state->parser_state.aml =
    182				    walk_state->parser_state.pkg_end;
    183				walk_state->arg_count = 0;
    184			}
    185			break;
    186
    187		case AML_WHILE_OP:
    188
    189			if (walk_state->control_state) {
    190				walk_state->control_state->control.package_end =
    191				    walk_state->parser_state.pkg_end;
    192			}
    193			break;
    194
    195		default:
    196
    197			/* No action for all other opcodes */
    198
    199			break;
    200		}
    201
    202		break;
    203	}
    204
    205	return_ACPI_STATUS(AE_OK);
    206}
    207
    208/*******************************************************************************
    209 *
    210 * FUNCTION:    acpi_ps_parse_loop
    211 *
    212 * PARAMETERS:  walk_state          - Current state
    213 *
    214 * RETURN:      Status
    215 *
    216 * DESCRIPTION: Parse AML (pointed to by the current parser state) and return
    217 *              a tree of ops.
    218 *
    219 ******************************************************************************/
    220
    221acpi_status acpi_ps_parse_loop(struct acpi_walk_state *walk_state)
    222{
    223	acpi_status status = AE_OK;
    224	union acpi_parse_object *op = NULL;	/* current op */
    225	struct acpi_parse_state *parser_state;
    226	u8 *aml_op_start = NULL;
    227	u8 opcode_length;
    228
    229	ACPI_FUNCTION_TRACE_PTR(ps_parse_loop, walk_state);
    230
    231	if (walk_state->descending_callback == NULL) {
    232		return_ACPI_STATUS(AE_BAD_PARAMETER);
    233	}
    234
    235	parser_state = &walk_state->parser_state;
    236	walk_state->arg_types = 0;
    237
    238#ifndef ACPI_CONSTANT_EVAL_ONLY
    239
    240	if (walk_state->walk_type & ACPI_WALK_METHOD_RESTART) {
    241
    242		/* We are restarting a preempted control method */
    243
    244		if (acpi_ps_has_completed_scope(parser_state)) {
    245			/*
    246			 * We must check if a predicate to an IF or WHILE statement
    247			 * was just completed
    248			 */
    249			if ((parser_state->scope->parse_scope.op) &&
    250			    ((parser_state->scope->parse_scope.op->common.
    251			      aml_opcode == AML_IF_OP)
    252			     || (parser_state->scope->parse_scope.op->common.
    253				 aml_opcode == AML_WHILE_OP))
    254			    && (walk_state->control_state)
    255			    && (walk_state->control_state->common.state ==
    256				ACPI_CONTROL_PREDICATE_EXECUTING)) {
    257				/*
    258				 * A predicate was just completed, get the value of the
    259				 * predicate and branch based on that value
    260				 */
    261				walk_state->op = NULL;
    262				status =
    263				    acpi_ds_get_predicate_value(walk_state,
    264								ACPI_TO_POINTER
    265								(TRUE));
    266				if (ACPI_FAILURE(status)
    267				    && !ACPI_CNTL_EXCEPTION(status)) {
    268					if (status == AE_AML_NO_RETURN_VALUE) {
    269						ACPI_EXCEPTION((AE_INFO, status,
    270								"Invoked method did not return a value"));
    271					}
    272
    273					ACPI_EXCEPTION((AE_INFO, status,
    274							"GetPredicate Failed"));
    275					return_ACPI_STATUS(status);
    276				}
    277
    278				status =
    279				    acpi_ps_next_parse_state(walk_state, op,
    280							     status);
    281			}
    282
    283			acpi_ps_pop_scope(parser_state, &op,
    284					  &walk_state->arg_types,
    285					  &walk_state->arg_count);
    286			ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    287					  "Popped scope, Op=%p\n", op));
    288		} else if (walk_state->prev_op) {
    289
    290			/* We were in the middle of an op */
    291
    292			op = walk_state->prev_op;
    293			walk_state->arg_types = walk_state->prev_arg_types;
    294		}
    295	}
    296#endif
    297
    298	/* Iterative parsing loop, while there is more AML to process: */
    299
    300	while ((parser_state->aml < parser_state->aml_end) || (op)) {
    301		ASL_CV_CAPTURE_COMMENTS(walk_state);
    302
    303		aml_op_start = parser_state->aml;
    304		if (!op) {
    305			status =
    306			    acpi_ps_create_op(walk_state, aml_op_start, &op);
    307			if (ACPI_FAILURE(status)) {
    308				/*
    309				 * ACPI_PARSE_MODULE_LEVEL means that we are loading a table by
    310				 * executing it as a control method. However, if we encounter
    311				 * an error while loading the table, we need to keep trying to
    312				 * load the table rather than aborting the table load. Set the
    313				 * status to AE_OK to proceed with the table load.
    314				 */
    315				if ((walk_state->
    316				     parse_flags & ACPI_PARSE_MODULE_LEVEL)
    317				    && ((status == AE_ALREADY_EXISTS)
    318					|| (status == AE_NOT_FOUND))) {
    319					status = AE_OK;
    320				}
    321				if (status == AE_CTRL_PARSE_CONTINUE) {
    322					continue;
    323				}
    324
    325				if (status == AE_CTRL_PARSE_PENDING) {
    326					status = AE_OK;
    327				}
    328
    329				if (status == AE_CTRL_TERMINATE) {
    330					return_ACPI_STATUS(status);
    331				}
    332
    333				status =
    334				    acpi_ps_complete_op(walk_state, &op,
    335							status);
    336				if (ACPI_FAILURE(status)) {
    337					return_ACPI_STATUS(status);
    338				}
    339				if (acpi_ns_opens_scope
    340				    (acpi_ps_get_opcode_info
    341				     (walk_state->opcode)->object_type)) {
    342					/*
    343					 * If the scope/device op fails to parse, skip the body of
    344					 * the scope op because the parse failure indicates that
    345					 * the device may not exist.
    346					 */
    347					ACPI_INFO(("Skipping parse of AML opcode: %s (0x%4.4X)", acpi_ps_get_opcode_name(walk_state->opcode), walk_state->opcode));
    348
    349					/*
    350					 * Determine the opcode length before skipping the opcode.
    351					 * An opcode can be 1 byte or 2 bytes in length.
    352					 */
    353					opcode_length = 1;
    354					if ((walk_state->opcode & 0xFF00) ==
    355					    AML_EXTENDED_OPCODE) {
    356						opcode_length = 2;
    357					}
    358					walk_state->parser_state.aml =
    359					    walk_state->aml + opcode_length;
    360
    361					walk_state->parser_state.aml =
    362					    acpi_ps_get_next_package_end
    363					    (&walk_state->parser_state);
    364					walk_state->aml =
    365					    walk_state->parser_state.aml;
    366				}
    367
    368				continue;
    369			}
    370
    371			acpi_ex_start_trace_opcode(op, walk_state);
    372		}
    373
    374		/*
    375		 * Start arg_count at zero because we don't know if there are
    376		 * any args yet
    377		 */
    378		walk_state->arg_count = 0;
    379
    380		switch (op->common.aml_opcode) {
    381		case AML_BYTE_OP:
    382		case AML_WORD_OP:
    383		case AML_DWORD_OP:
    384		case AML_QWORD_OP:
    385
    386			break;
    387
    388		default:
    389
    390			ASL_CV_CAPTURE_COMMENTS(walk_state);
    391			break;
    392		}
    393
    394		/* Are there any arguments that must be processed? */
    395
    396		if (walk_state->arg_types) {
    397
    398			/* Get arguments */
    399
    400			status =
    401			    acpi_ps_get_arguments(walk_state, aml_op_start, op);
    402			if (ACPI_FAILURE(status)) {
    403				status =
    404				    acpi_ps_complete_op(walk_state, &op,
    405							status);
    406				if (ACPI_FAILURE(status)) {
    407					return_ACPI_STATUS(status);
    408				}
    409				if ((walk_state->control_state) &&
    410				    ((walk_state->control_state->control.
    411				      opcode == AML_IF_OP)
    412				     || (walk_state->control_state->control.
    413					 opcode == AML_WHILE_OP))) {
    414					/*
    415					 * If the if/while op fails to parse, we will skip parsing
    416					 * the body of the op.
    417					 */
    418					parser_state->aml =
    419					    walk_state->control_state->control.
    420					    aml_predicate_start + 1;
    421					parser_state->aml =
    422					    acpi_ps_get_next_package_end
    423					    (parser_state);
    424					walk_state->aml = parser_state->aml;
    425
    426					ACPI_ERROR((AE_INFO,
    427						    "Skipping While/If block"));
    428					if (*walk_state->aml == AML_ELSE_OP) {
    429						ACPI_ERROR((AE_INFO,
    430							    "Skipping Else block"));
    431						walk_state->parser_state.aml =
    432						    walk_state->aml + 1;
    433						walk_state->parser_state.aml =
    434						    acpi_ps_get_next_package_end
    435						    (parser_state);
    436						walk_state->aml =
    437						    parser_state->aml;
    438					}
    439					ACPI_FREE(acpi_ut_pop_generic_state
    440						  (&walk_state->control_state));
    441				}
    442				op = NULL;
    443				continue;
    444			}
    445		}
    446
    447		/* Check for arguments that need to be processed */
    448
    449		ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    450				  "Parseloop: argument count: %8.8X\n",
    451				  walk_state->arg_count));
    452
    453		if (walk_state->arg_count) {
    454			/*
    455			 * There are arguments (complex ones), push Op and
    456			 * prepare for argument
    457			 */
    458			status = acpi_ps_push_scope(parser_state, op,
    459						    walk_state->arg_types,
    460						    walk_state->arg_count);
    461			if (ACPI_FAILURE(status)) {
    462				status =
    463				    acpi_ps_complete_op(walk_state, &op,
    464							status);
    465				if (ACPI_FAILURE(status)) {
    466					return_ACPI_STATUS(status);
    467				}
    468
    469				continue;
    470			}
    471
    472			op = NULL;
    473			continue;
    474		}
    475
    476		/*
    477		 * All arguments have been processed -- Op is complete,
    478		 * prepare for next
    479		 */
    480		walk_state->op_info =
    481		    acpi_ps_get_opcode_info(op->common.aml_opcode);
    482		if (walk_state->op_info->flags & AML_NAMED) {
    483			if (op->common.aml_opcode == AML_REGION_OP ||
    484			    op->common.aml_opcode == AML_DATA_REGION_OP) {
    485				/*
    486				 * Skip parsing of control method or opregion body,
    487				 * because we don't have enough info in the first pass
    488				 * to parse them correctly.
    489				 *
    490				 * Completed parsing an op_region declaration, we now
    491				 * know the length.
    492				 */
    493				op->named.length =
    494				    (u32) (parser_state->aml - op->named.data);
    495			}
    496		}
    497
    498		if (walk_state->op_info->flags & AML_CREATE) {
    499			/*
    500			 * Backup to beginning of create_XXXfield declaration (1 for
    501			 * Opcode)
    502			 *
    503			 * body_length is unknown until we parse the body
    504			 */
    505			op->named.length =
    506			    (u32) (parser_state->aml - op->named.data);
    507		}
    508
    509		if (op->common.aml_opcode == AML_BANK_FIELD_OP) {
    510			/*
    511			 * Backup to beginning of bank_field declaration
    512			 *
    513			 * body_length is unknown until we parse the body
    514			 */
    515			op->named.length =
    516			    (u32) (parser_state->aml - op->named.data);
    517		}
    518
    519		/* This op complete, notify the dispatcher */
    520
    521		if (walk_state->ascending_callback != NULL) {
    522			walk_state->op = op;
    523			walk_state->opcode = op->common.aml_opcode;
    524
    525			status = walk_state->ascending_callback(walk_state);
    526			status =
    527			    acpi_ps_next_parse_state(walk_state, op, status);
    528			if (status == AE_CTRL_PENDING) {
    529				status = AE_OK;
    530			} else
    531			    if ((walk_state->
    532				 parse_flags & ACPI_PARSE_MODULE_LEVEL)
    533				&& (ACPI_AML_EXCEPTION(status)
    534				    || status == AE_ALREADY_EXISTS
    535				    || status == AE_NOT_FOUND)) {
    536				/*
    537				 * ACPI_PARSE_MODULE_LEVEL flag means that we
    538				 * are currently loading a table by executing
    539				 * it as a control method. However, if we
    540				 * encounter an error while loading the table,
    541				 * we need to keep trying to load the table
    542				 * rather than aborting the table load (setting
    543				 * the status to AE_OK continues the table
    544				 * load). If we get a failure at this point, it
    545				 * means that the dispatcher got an error while
    546				 * trying to execute the Op.
    547				 */
    548				status = AE_OK;
    549			}
    550		}
    551
    552		status = acpi_ps_complete_op(walk_state, &op, status);
    553		if (ACPI_FAILURE(status)) {
    554			return_ACPI_STATUS(status);
    555		}
    556
    557	}			/* while parser_state->Aml */
    558
    559	status = acpi_ps_complete_final_op(walk_state, op, status);
    560	return_ACPI_STATUS(status);
    561}