162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
262306a36Sopenharmony_ci/******************************************************************************
362306a36Sopenharmony_ci *
462306a36Sopenharmony_ci * Module Name: utpredef - support functions for predefined names
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright (C) 2000 - 2023, Intel Corp.
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci *****************************************************************************/
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <acpi/acpi.h>
1162306a36Sopenharmony_ci#include "accommon.h"
1262306a36Sopenharmony_ci#include "acpredef.h"
1362306a36Sopenharmony_ci
1462306a36Sopenharmony_ci#define _COMPONENT          ACPI_UTILITIES
1562306a36Sopenharmony_ciACPI_MODULE_NAME("utpredef")
1662306a36Sopenharmony_ci
1762306a36Sopenharmony_ci/*
1862306a36Sopenharmony_ci * Names for the types that can be returned by the predefined objects.
1962306a36Sopenharmony_ci * Used for warning messages. Must be in the same order as the ACPI_RTYPEs
2062306a36Sopenharmony_ci */
2162306a36Sopenharmony_cistatic const char *ut_rtype_names[] = {
2262306a36Sopenharmony_ci	"/Integer",
2362306a36Sopenharmony_ci	"/String",
2462306a36Sopenharmony_ci	"/Buffer",
2562306a36Sopenharmony_ci	"/Package",
2662306a36Sopenharmony_ci	"/Reference",
2762306a36Sopenharmony_ci};
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci/*******************************************************************************
3062306a36Sopenharmony_ci *
3162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_next_predefined_method
3262306a36Sopenharmony_ci *
3362306a36Sopenharmony_ci * PARAMETERS:  this_name           - Entry in the predefined method/name table
3462306a36Sopenharmony_ci *
3562306a36Sopenharmony_ci * RETURN:      Pointer to next entry in predefined table.
3662306a36Sopenharmony_ci *
3762306a36Sopenharmony_ci * DESCRIPTION: Get the next entry in the predefine method table. Handles the
3862306a36Sopenharmony_ci *              cases where a package info entry follows a method name that
3962306a36Sopenharmony_ci *              returns a package.
4062306a36Sopenharmony_ci *
4162306a36Sopenharmony_ci ******************************************************************************/
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ciconst union acpi_predefined_info *acpi_ut_get_next_predefined_method(const union
4462306a36Sopenharmony_ci								     acpi_predefined_info
4562306a36Sopenharmony_ci								     *this_name)
4662306a36Sopenharmony_ci{
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_ci	/*
4962306a36Sopenharmony_ci	 * Skip next entry in the table if this name returns a Package
5062306a36Sopenharmony_ci	 * (next entry contains the package info)
5162306a36Sopenharmony_ci	 */
5262306a36Sopenharmony_ci	if ((this_name->info.expected_btypes & ACPI_RTYPE_PACKAGE) &&
5362306a36Sopenharmony_ci	    (this_name->info.expected_btypes != ACPI_RTYPE_ALL)) {
5462306a36Sopenharmony_ci		this_name++;
5562306a36Sopenharmony_ci	}
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	this_name++;
5862306a36Sopenharmony_ci	return (this_name);
5962306a36Sopenharmony_ci}
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci/*******************************************************************************
6262306a36Sopenharmony_ci *
6362306a36Sopenharmony_ci * FUNCTION:    acpi_ut_match_predefined_method
6462306a36Sopenharmony_ci *
6562306a36Sopenharmony_ci * PARAMETERS:  name                - Name to find
6662306a36Sopenharmony_ci *
6762306a36Sopenharmony_ci * RETURN:      Pointer to entry in predefined table. NULL indicates not found.
6862306a36Sopenharmony_ci *
6962306a36Sopenharmony_ci * DESCRIPTION: Check an object name against the predefined object list.
7062306a36Sopenharmony_ci *
7162306a36Sopenharmony_ci ******************************************************************************/
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ciconst union acpi_predefined_info *acpi_ut_match_predefined_method(char *name)
7462306a36Sopenharmony_ci{
7562306a36Sopenharmony_ci	const union acpi_predefined_info *this_name;
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_ci	/* Quick check for a predefined name, first character must be underscore */
7862306a36Sopenharmony_ci
7962306a36Sopenharmony_ci	if (name[0] != '_') {
8062306a36Sopenharmony_ci		return (NULL);
8162306a36Sopenharmony_ci	}
8262306a36Sopenharmony_ci
8362306a36Sopenharmony_ci	/* Search info table for a predefined method/object name */
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	this_name = acpi_gbl_predefined_methods;
8662306a36Sopenharmony_ci	while (this_name->info.name[0]) {
8762306a36Sopenharmony_ci		if (ACPI_COMPARE_NAMESEG(name, this_name->info.name)) {
8862306a36Sopenharmony_ci			return (this_name);
8962306a36Sopenharmony_ci		}
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci		this_name = acpi_ut_get_next_predefined_method(this_name);
9262306a36Sopenharmony_ci	}
9362306a36Sopenharmony_ci
9462306a36Sopenharmony_ci	return (NULL);		/* Not found */
9562306a36Sopenharmony_ci}
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci/*******************************************************************************
9862306a36Sopenharmony_ci *
9962306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_expected_return_types
10062306a36Sopenharmony_ci *
10162306a36Sopenharmony_ci * PARAMETERS:  buffer              - Where the formatted string is returned
10262306a36Sopenharmony_ci *              expected_Btypes     - Bitfield of expected data types
10362306a36Sopenharmony_ci *
10462306a36Sopenharmony_ci * RETURN:      Formatted string in Buffer.
10562306a36Sopenharmony_ci *
10662306a36Sopenharmony_ci * DESCRIPTION: Format the expected object types into a printable string.
10762306a36Sopenharmony_ci *
10862306a36Sopenharmony_ci ******************************************************************************/
10962306a36Sopenharmony_ci
11062306a36Sopenharmony_civoid acpi_ut_get_expected_return_types(char *buffer, u32 expected_btypes)
11162306a36Sopenharmony_ci{
11262306a36Sopenharmony_ci	u32 this_rtype;
11362306a36Sopenharmony_ci	u32 i;
11462306a36Sopenharmony_ci	u32 j;
11562306a36Sopenharmony_ci
11662306a36Sopenharmony_ci	if (!expected_btypes) {
11762306a36Sopenharmony_ci		strcpy(buffer, "NONE");
11862306a36Sopenharmony_ci		return;
11962306a36Sopenharmony_ci	}
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	j = 1;
12262306a36Sopenharmony_ci	buffer[0] = 0;
12362306a36Sopenharmony_ci	this_rtype = ACPI_RTYPE_INTEGER;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	for (i = 0; i < ACPI_NUM_RTYPES; i++) {
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci		/* If one of the expected types, concatenate the name of this type */
12862306a36Sopenharmony_ci
12962306a36Sopenharmony_ci		if (expected_btypes & this_rtype) {
13062306a36Sopenharmony_ci			strcat(buffer, &ut_rtype_names[i][j]);
13162306a36Sopenharmony_ci			j = 0;	/* Use name separator from now on */
13262306a36Sopenharmony_ci		}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci		this_rtype <<= 1;	/* Next Rtype */
13562306a36Sopenharmony_ci	}
13662306a36Sopenharmony_ci}
13762306a36Sopenharmony_ci
13862306a36Sopenharmony_ci/*******************************************************************************
13962306a36Sopenharmony_ci *
14062306a36Sopenharmony_ci * The remaining functions are used by iASL and acpi_help only
14162306a36Sopenharmony_ci *
14262306a36Sopenharmony_ci ******************************************************************************/
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_ci#if (defined ACPI_ASL_COMPILER || defined ACPI_HELP_APP)
14562306a36Sopenharmony_ci
14662306a36Sopenharmony_ci/* Local prototypes */
14762306a36Sopenharmony_ci
14862306a36Sopenharmony_cistatic u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types);
14962306a36Sopenharmony_ci
15062306a36Sopenharmony_ci/* Types that can be returned externally by a predefined name */
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_cistatic const char *ut_external_type_names[] =	/* Indexed by ACPI_TYPE_* */
15362306a36Sopenharmony_ci{
15462306a36Sopenharmony_ci	", Type_ANY",
15562306a36Sopenharmony_ci	", Integer",
15662306a36Sopenharmony_ci	", String",
15762306a36Sopenharmony_ci	", Buffer",
15862306a36Sopenharmony_ci	", Package"
15962306a36Sopenharmony_ci};
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci/* Bit widths for resource descriptor predefined names */
16262306a36Sopenharmony_ci
16362306a36Sopenharmony_cistatic const char *ut_resource_type_names[] = {
16462306a36Sopenharmony_ci	"/1",
16562306a36Sopenharmony_ci	"/2",
16662306a36Sopenharmony_ci	"/3",
16762306a36Sopenharmony_ci	"/8",
16862306a36Sopenharmony_ci	"/16",
16962306a36Sopenharmony_ci	"/32",
17062306a36Sopenharmony_ci	"/64",
17162306a36Sopenharmony_ci	"/variable",
17262306a36Sopenharmony_ci};
17362306a36Sopenharmony_ci
17462306a36Sopenharmony_ci/*******************************************************************************
17562306a36Sopenharmony_ci *
17662306a36Sopenharmony_ci * FUNCTION:    acpi_ut_match_resource_name
17762306a36Sopenharmony_ci *
17862306a36Sopenharmony_ci * PARAMETERS:  name                - Name to find
17962306a36Sopenharmony_ci *
18062306a36Sopenharmony_ci * RETURN:      Pointer to entry in the resource table. NULL indicates not
18162306a36Sopenharmony_ci *              found.
18262306a36Sopenharmony_ci *
18362306a36Sopenharmony_ci * DESCRIPTION: Check an object name against the predefined resource
18462306a36Sopenharmony_ci *              descriptor object list.
18562306a36Sopenharmony_ci *
18662306a36Sopenharmony_ci ******************************************************************************/
18762306a36Sopenharmony_ci
18862306a36Sopenharmony_ciconst union acpi_predefined_info *acpi_ut_match_resource_name(char *name)
18962306a36Sopenharmony_ci{
19062306a36Sopenharmony_ci	const union acpi_predefined_info *this_name;
19162306a36Sopenharmony_ci
19262306a36Sopenharmony_ci	/*
19362306a36Sopenharmony_ci	 * Quick check for a predefined name, first character must
19462306a36Sopenharmony_ci	 * be underscore
19562306a36Sopenharmony_ci	 */
19662306a36Sopenharmony_ci	if (name[0] != '_') {
19762306a36Sopenharmony_ci		return (NULL);
19862306a36Sopenharmony_ci	}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_ci	/* Search info table for a predefined method/object name */
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	this_name = acpi_gbl_resource_names;
20362306a36Sopenharmony_ci	while (this_name->info.name[0]) {
20462306a36Sopenharmony_ci		if (ACPI_COMPARE_NAMESEG(name, this_name->info.name)) {
20562306a36Sopenharmony_ci			return (this_name);
20662306a36Sopenharmony_ci		}
20762306a36Sopenharmony_ci
20862306a36Sopenharmony_ci		this_name++;
20962306a36Sopenharmony_ci	}
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_ci	return (NULL);		/* Not found */
21262306a36Sopenharmony_ci}
21362306a36Sopenharmony_ci
21462306a36Sopenharmony_ci/*******************************************************************************
21562306a36Sopenharmony_ci *
21662306a36Sopenharmony_ci * FUNCTION:    acpi_ut_display_predefined_method
21762306a36Sopenharmony_ci *
21862306a36Sopenharmony_ci * PARAMETERS:  buffer              - Scratch buffer for this function
21962306a36Sopenharmony_ci *              this_name           - Entry in the predefined method/name table
22062306a36Sopenharmony_ci *              multi_line          - TRUE if output should be on >1 line
22162306a36Sopenharmony_ci *
22262306a36Sopenharmony_ci * RETURN:      None
22362306a36Sopenharmony_ci *
22462306a36Sopenharmony_ci * DESCRIPTION: Display information about a predefined method. Number and
22562306a36Sopenharmony_ci *              type of the input arguments, and expected type(s) for the
22662306a36Sopenharmony_ci *              return value, if any.
22762306a36Sopenharmony_ci *
22862306a36Sopenharmony_ci ******************************************************************************/
22962306a36Sopenharmony_ci
23062306a36Sopenharmony_civoid
23162306a36Sopenharmony_ciacpi_ut_display_predefined_method(char *buffer,
23262306a36Sopenharmony_ci				  const union acpi_predefined_info *this_name,
23362306a36Sopenharmony_ci				  u8 multi_line)
23462306a36Sopenharmony_ci{
23562306a36Sopenharmony_ci	u32 arg_count;
23662306a36Sopenharmony_ci
23762306a36Sopenharmony_ci	/*
23862306a36Sopenharmony_ci	 * Get the argument count and the string buffer
23962306a36Sopenharmony_ci	 * containing all argument types
24062306a36Sopenharmony_ci	 */
24162306a36Sopenharmony_ci	arg_count = acpi_ut_get_argument_types(buffer,
24262306a36Sopenharmony_ci					       this_name->info.argument_list);
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci	if (multi_line) {
24562306a36Sopenharmony_ci		printf("      ");
24662306a36Sopenharmony_ci	}
24762306a36Sopenharmony_ci
24862306a36Sopenharmony_ci	printf("%4.4s    Requires %s%u argument%s",
24962306a36Sopenharmony_ci	       this_name->info.name,
25062306a36Sopenharmony_ci	       (this_name->info.argument_list & ARG_COUNT_IS_MINIMUM) ?
25162306a36Sopenharmony_ci	       "(at least) " : "", arg_count, arg_count != 1 ? "s" : "");
25262306a36Sopenharmony_ci
25362306a36Sopenharmony_ci	/* Display the types for any arguments */
25462306a36Sopenharmony_ci
25562306a36Sopenharmony_ci	if (arg_count > 0) {
25662306a36Sopenharmony_ci		printf(" (%s)", buffer);
25762306a36Sopenharmony_ci	}
25862306a36Sopenharmony_ci
25962306a36Sopenharmony_ci	if (multi_line) {
26062306a36Sopenharmony_ci		printf("\n    ");
26162306a36Sopenharmony_ci	}
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	/* Get the return value type(s) allowed */
26462306a36Sopenharmony_ci
26562306a36Sopenharmony_ci	if (this_name->info.expected_btypes) {
26662306a36Sopenharmony_ci		acpi_ut_get_expected_return_types(buffer,
26762306a36Sopenharmony_ci						  this_name->info.
26862306a36Sopenharmony_ci						  expected_btypes);
26962306a36Sopenharmony_ci		printf("  Return value types: %s\n", buffer);
27062306a36Sopenharmony_ci	} else {
27162306a36Sopenharmony_ci		printf("  No return value\n");
27262306a36Sopenharmony_ci	}
27362306a36Sopenharmony_ci}
27462306a36Sopenharmony_ci
27562306a36Sopenharmony_ci/*******************************************************************************
27662306a36Sopenharmony_ci *
27762306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_argument_types
27862306a36Sopenharmony_ci *
27962306a36Sopenharmony_ci * PARAMETERS:  buffer              - Where to return the formatted types
28062306a36Sopenharmony_ci *              argument_types      - Types field for this method
28162306a36Sopenharmony_ci *
28262306a36Sopenharmony_ci * RETURN:      count - the number of arguments required for this method
28362306a36Sopenharmony_ci *
28462306a36Sopenharmony_ci * DESCRIPTION: Format the required data types for this method (Integer,
28562306a36Sopenharmony_ci *              String, Buffer, or Package) and return the required argument
28662306a36Sopenharmony_ci *              count.
28762306a36Sopenharmony_ci *
28862306a36Sopenharmony_ci ******************************************************************************/
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_cistatic u32 acpi_ut_get_argument_types(char *buffer, u16 argument_types)
29162306a36Sopenharmony_ci{
29262306a36Sopenharmony_ci	u16 this_argument_type;
29362306a36Sopenharmony_ci	u16 sub_index;
29462306a36Sopenharmony_ci	u16 arg_count;
29562306a36Sopenharmony_ci	u32 i;
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_ci	*buffer = 0;
29862306a36Sopenharmony_ci	sub_index = 2;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	/* First field in the types list is the count of args to follow */
30162306a36Sopenharmony_ci
30262306a36Sopenharmony_ci	arg_count = METHOD_GET_ARG_COUNT(argument_types);
30362306a36Sopenharmony_ci	if (arg_count > METHOD_PREDEF_ARGS_MAX) {
30462306a36Sopenharmony_ci		printf("**** Invalid argument count (%u) "
30562306a36Sopenharmony_ci		       "in predefined info structure\n", arg_count);
30662306a36Sopenharmony_ci		return (arg_count);
30762306a36Sopenharmony_ci	}
30862306a36Sopenharmony_ci
30962306a36Sopenharmony_ci	/* Get each argument from the list, convert to ascii, store to buffer */
31062306a36Sopenharmony_ci
31162306a36Sopenharmony_ci	for (i = 0; i < arg_count; i++) {
31262306a36Sopenharmony_ci		this_argument_type = METHOD_GET_NEXT_TYPE(argument_types);
31362306a36Sopenharmony_ci
31462306a36Sopenharmony_ci		if (this_argument_type > METHOD_MAX_ARG_TYPE) {
31562306a36Sopenharmony_ci			printf("**** Invalid argument type (%u) "
31662306a36Sopenharmony_ci			       "in predefined info structure\n",
31762306a36Sopenharmony_ci			       this_argument_type);
31862306a36Sopenharmony_ci			return (arg_count);
31962306a36Sopenharmony_ci		}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci		strcat(buffer,
32262306a36Sopenharmony_ci		       ut_external_type_names[this_argument_type] + sub_index);
32362306a36Sopenharmony_ci		sub_index = 0;
32462306a36Sopenharmony_ci	}
32562306a36Sopenharmony_ci
32662306a36Sopenharmony_ci	return (arg_count);
32762306a36Sopenharmony_ci}
32862306a36Sopenharmony_ci
32962306a36Sopenharmony_ci/*******************************************************************************
33062306a36Sopenharmony_ci *
33162306a36Sopenharmony_ci * FUNCTION:    acpi_ut_get_resource_bit_width
33262306a36Sopenharmony_ci *
33362306a36Sopenharmony_ci * PARAMETERS:  buffer              - Where the formatted string is returned
33462306a36Sopenharmony_ci *              types               - Bitfield of expected data types
33562306a36Sopenharmony_ci *
33662306a36Sopenharmony_ci * RETURN:      Count of return types. Formatted string in Buffer.
33762306a36Sopenharmony_ci *
33862306a36Sopenharmony_ci * DESCRIPTION: Format the resource bit widths into a printable string.
33962306a36Sopenharmony_ci *
34062306a36Sopenharmony_ci ******************************************************************************/
34162306a36Sopenharmony_ci
34262306a36Sopenharmony_ciu32 acpi_ut_get_resource_bit_width(char *buffer, u16 types)
34362306a36Sopenharmony_ci{
34462306a36Sopenharmony_ci	u32 i;
34562306a36Sopenharmony_ci	u16 sub_index;
34662306a36Sopenharmony_ci	u32 found;
34762306a36Sopenharmony_ci
34862306a36Sopenharmony_ci	*buffer = 0;
34962306a36Sopenharmony_ci	sub_index = 1;
35062306a36Sopenharmony_ci	found = 0;
35162306a36Sopenharmony_ci
35262306a36Sopenharmony_ci	for (i = 0; i < NUM_RESOURCE_WIDTHS; i++) {
35362306a36Sopenharmony_ci		if (types & 1) {
35462306a36Sopenharmony_ci			strcat(buffer, &(ut_resource_type_names[i][sub_index]));
35562306a36Sopenharmony_ci			sub_index = 0;
35662306a36Sopenharmony_ci			found++;
35762306a36Sopenharmony_ci		}
35862306a36Sopenharmony_ci
35962306a36Sopenharmony_ci		types >>= 1;
36062306a36Sopenharmony_ci	}
36162306a36Sopenharmony_ci
36262306a36Sopenharmony_ci	return (found);
36362306a36Sopenharmony_ci}
36462306a36Sopenharmony_ci#endif
365