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

nsparse.c (7705B)


      1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
      2/******************************************************************************
      3 *
      4 * Module Name: nsparse - namespace interface to AML parser
      5 *
      6 * Copyright (C) 2000 - 2022, Intel Corp.
      7 *
      8 *****************************************************************************/
      9
     10#include <acpi/acpi.h>
     11#include "accommon.h"
     12#include "acnamesp.h"
     13#include "acparser.h"
     14#include "acdispat.h"
     15#include "actables.h"
     16#include "acinterp.h"
     17
     18#define _COMPONENT          ACPI_NAMESPACE
     19ACPI_MODULE_NAME("nsparse")
     20
     21/*******************************************************************************
     22 *
     23 * FUNCTION:    ns_execute_table
     24 *
     25 * PARAMETERS:  table_desc      - An ACPI table descriptor for table to parse
     26 *              start_node      - Where to enter the table into the namespace
     27 *
     28 * RETURN:      Status
     29 *
     30 * DESCRIPTION: Load ACPI/AML table by executing the entire table as a single
     31 *              large control method.
     32 *
     33 * NOTE: The point of this is to execute any module-level code in-place
     34 * as the table is parsed. Some AML code depends on this behavior.
     35 *
     36 * It is a run-time option at this time, but will eventually become
     37 * the default.
     38 *
     39 * Note: This causes the table to only have a single-pass parse.
     40 * However, this is compatible with other ACPI implementations.
     41 *
     42 ******************************************************************************/
     43acpi_status
     44acpi_ns_execute_table(u32 table_index, struct acpi_namespace_node *start_node)
     45{
     46	acpi_status status;
     47	struct acpi_table_header *table;
     48	acpi_owner_id owner_id;
     49	struct acpi_evaluate_info *info = NULL;
     50	u32 aml_length;
     51	u8 *aml_start;
     52	union acpi_operand_object *method_obj = NULL;
     53
     54	ACPI_FUNCTION_TRACE(ns_execute_table);
     55
     56	status = acpi_get_table_by_index(table_index, &table);
     57	if (ACPI_FAILURE(status)) {
     58		return_ACPI_STATUS(status);
     59	}
     60
     61	/* Table must consist of at least a complete header */
     62
     63	if (table->length < sizeof(struct acpi_table_header)) {
     64		return_ACPI_STATUS(AE_BAD_HEADER);
     65	}
     66
     67	aml_start = (u8 *)table + sizeof(struct acpi_table_header);
     68	aml_length = table->length - sizeof(struct acpi_table_header);
     69
     70	status = acpi_tb_get_owner_id(table_index, &owner_id);
     71	if (ACPI_FAILURE(status)) {
     72		return_ACPI_STATUS(status);
     73	}
     74
     75	/* Create, initialize, and link a new temporary method object */
     76
     77	method_obj = acpi_ut_create_internal_object(ACPI_TYPE_METHOD);
     78	if (!method_obj) {
     79		return_ACPI_STATUS(AE_NO_MEMORY);
     80	}
     81
     82	/* Allocate the evaluation information block */
     83
     84	info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_evaluate_info));
     85	if (!info) {
     86		status = AE_NO_MEMORY;
     87		goto cleanup;
     88	}
     89
     90	ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
     91			      "%s: Create table pseudo-method for [%4.4s] @%p, method %p\n",
     92			      ACPI_GET_FUNCTION_NAME, table->signature, table,
     93			      method_obj));
     94
     95	method_obj->method.aml_start = aml_start;
     96	method_obj->method.aml_length = aml_length;
     97	method_obj->method.owner_id = owner_id;
     98	method_obj->method.info_flags |= ACPI_METHOD_MODULE_LEVEL;
     99
    100	info->pass_number = ACPI_IMODE_EXECUTE;
    101	info->node = start_node;
    102	info->obj_desc = method_obj;
    103	info->node_flags = info->node->flags;
    104	info->full_pathname = acpi_ns_get_normalized_pathname(info->node, TRUE);
    105	if (!info->full_pathname) {
    106		status = AE_NO_MEMORY;
    107		goto cleanup;
    108	}
    109
    110	/* Optional object evaluation log */
    111
    112	ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
    113			      "%-26s:  (Definition Block level)\n",
    114			      "Module-level evaluation"));
    115
    116	status = acpi_ps_execute_table(info);
    117
    118	/* Optional object evaluation log */
    119
    120	ACPI_DEBUG_PRINT_RAW((ACPI_DB_EVALUATION,
    121			      "%-26s:  (Definition Block level)\n",
    122			      "Module-level complete"));
    123
    124cleanup:
    125	if (info) {
    126		ACPI_FREE(info->full_pathname);
    127		info->full_pathname = NULL;
    128	}
    129	ACPI_FREE(info);
    130	acpi_ut_remove_reference(method_obj);
    131	return_ACPI_STATUS(status);
    132}
    133
    134/*******************************************************************************
    135 *
    136 * FUNCTION:    ns_one_complete_parse
    137 *
    138 * PARAMETERS:  pass_number             - 1 or 2
    139 *              table_desc              - The table to be parsed.
    140 *
    141 * RETURN:      Status
    142 *
    143 * DESCRIPTION: Perform one complete parse of an ACPI/AML table.
    144 *
    145 ******************************************************************************/
    146
    147acpi_status
    148acpi_ns_one_complete_parse(u32 pass_number,
    149			   u32 table_index,
    150			   struct acpi_namespace_node *start_node)
    151{
    152	union acpi_parse_object *parse_root;
    153	acpi_status status;
    154	u32 aml_length;
    155	u8 *aml_start;
    156	struct acpi_walk_state *walk_state;
    157	struct acpi_table_header *table;
    158	acpi_owner_id owner_id;
    159
    160	ACPI_FUNCTION_TRACE(ns_one_complete_parse);
    161
    162	status = acpi_get_table_by_index(table_index, &table);
    163	if (ACPI_FAILURE(status)) {
    164		return_ACPI_STATUS(status);
    165	}
    166
    167	/* Table must consist of at least a complete header */
    168
    169	if (table->length < sizeof(struct acpi_table_header)) {
    170		return_ACPI_STATUS(AE_BAD_HEADER);
    171	}
    172
    173	aml_start = (u8 *)table + sizeof(struct acpi_table_header);
    174	aml_length = table->length - sizeof(struct acpi_table_header);
    175
    176	status = acpi_tb_get_owner_id(table_index, &owner_id);
    177	if (ACPI_FAILURE(status)) {
    178		return_ACPI_STATUS(status);
    179	}
    180
    181	/* Create and init a Root Node */
    182
    183	parse_root = acpi_ps_create_scope_op(aml_start);
    184	if (!parse_root) {
    185		return_ACPI_STATUS(AE_NO_MEMORY);
    186	}
    187
    188	/* Create and initialize a new walk state */
    189
    190	walk_state = acpi_ds_create_walk_state(owner_id, NULL, NULL, NULL);
    191	if (!walk_state) {
    192		acpi_ps_free_op(parse_root);
    193		return_ACPI_STATUS(AE_NO_MEMORY);
    194	}
    195
    196	status = acpi_ds_init_aml_walk(walk_state, parse_root, NULL,
    197				       aml_start, aml_length, NULL,
    198				       (u8)pass_number);
    199	if (ACPI_FAILURE(status)) {
    200		acpi_ds_delete_walk_state(walk_state);
    201		goto cleanup;
    202	}
    203
    204	/* Found OSDT table, enable the namespace override feature */
    205
    206	if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) &&
    207	    pass_number == ACPI_IMODE_LOAD_PASS1) {
    208		walk_state->namespace_override = TRUE;
    209	}
    210
    211	/* start_node is the default location to load the table */
    212
    213	if (start_node && start_node != acpi_gbl_root_node) {
    214		status =
    215		    acpi_ds_scope_stack_push(start_node, ACPI_TYPE_METHOD,
    216					     walk_state);
    217		if (ACPI_FAILURE(status)) {
    218			acpi_ds_delete_walk_state(walk_state);
    219			goto cleanup;
    220		}
    221	}
    222
    223	/* Parse the AML */
    224
    225	ACPI_DEBUG_PRINT((ACPI_DB_PARSE,
    226			  "*PARSE* pass %u parse\n", pass_number));
    227	acpi_ex_enter_interpreter();
    228	status = acpi_ps_parse_aml(walk_state);
    229	acpi_ex_exit_interpreter();
    230
    231cleanup:
    232	acpi_ps_delete_parse_tree(parse_root);
    233	return_ACPI_STATUS(status);
    234}
    235
    236/*******************************************************************************
    237 *
    238 * FUNCTION:    acpi_ns_parse_table
    239 *
    240 * PARAMETERS:  table_desc      - An ACPI table descriptor for table to parse
    241 *              start_node      - Where to enter the table into the namespace
    242 *
    243 * RETURN:      Status
    244 *
    245 * DESCRIPTION: Parse AML within an ACPI table and return a tree of ops
    246 *
    247 ******************************************************************************/
    248
    249acpi_status
    250acpi_ns_parse_table(u32 table_index, struct acpi_namespace_node *start_node)
    251{
    252	acpi_status status;
    253
    254	ACPI_FUNCTION_TRACE(ns_parse_table);
    255
    256	/*
    257	 * Executes the AML table as one large control method.
    258	 * The point of this is to execute any module-level code in-place
    259	 * as the table is parsed. Some AML code depends on this behavior.
    260	 *
    261	 * Note: This causes the table to only have a single-pass parse.
    262	 * However, this is compatible with other ACPI implementations.
    263	 */
    264	ACPI_DEBUG_PRINT_RAW((ACPI_DB_PARSE,
    265			      "%s: **** Start table execution pass\n",
    266			      ACPI_GET_FUNCTION_NAME));
    267
    268	status = acpi_ns_execute_table(table_index, start_node);
    269
    270	return_ACPI_STATUS(status);
    271}