383 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/*******************************************************************************3 *4 * Module Name: utmisc - common utility procedures5 *6 ******************************************************************************/7 8#include <acpi/acpi.h>9#include "accommon.h"10#include "acnamesp.h"11 12#define _COMPONENT ACPI_UTILITIES13ACPI_MODULE_NAME("utmisc")14 15/*******************************************************************************16 *17 * FUNCTION: acpi_ut_is_pci_root_bridge18 *19 * PARAMETERS: id - The HID/CID in string format20 *21 * RETURN: TRUE if the Id is a match for a PCI/PCI-Express Root Bridge22 *23 * DESCRIPTION: Determine if the input ID is a PCI Root Bridge ID.24 *25 ******************************************************************************/26u8 acpi_ut_is_pci_root_bridge(char *id)27{28 29 /*30 * Check if this is a PCI root bridge.31 * ACPI 3.0+: check for a PCI Express root also.32 */33 if (!(strcmp(id,34 PCI_ROOT_HID_STRING)) ||35 !(strcmp(id, PCI_EXPRESS_ROOT_HID_STRING))) {36 return (TRUE);37 }38 39 return (FALSE);40}41 42#if (defined ACPI_ASL_COMPILER || defined ACPI_EXEC_APP || defined ACPI_NAMES_APP)43/*******************************************************************************44 *45 * FUNCTION: acpi_ut_is_aml_table46 *47 * PARAMETERS: table - An ACPI table48 *49 * RETURN: TRUE if table contains executable AML; FALSE otherwise50 *51 * DESCRIPTION: Check ACPI Signature for a table that contains AML code.52 * Currently, these are DSDT,SSDT,PSDT. All other table types are53 * data tables that do not contain AML code.54 *55 ******************************************************************************/56 57u8 acpi_ut_is_aml_table(struct acpi_table_header *table)58{59 60 /* These are the only tables that contain executable AML */61 62 if (ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_DSDT) ||63 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_PSDT) ||64 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_SSDT) ||65 ACPI_COMPARE_NAMESEG(table->signature, ACPI_SIG_OSDT) ||66 ACPI_IS_OEM_SIG(table->signature)) {67 return (TRUE);68 }69 70 return (FALSE);71}72#endif73 74/*******************************************************************************75 *76 * FUNCTION: acpi_ut_dword_byte_swap77 *78 * PARAMETERS: value - Value to be converted79 *80 * RETURN: u32 integer with bytes swapped81 *82 * DESCRIPTION: Convert a 32-bit value to big-endian (swap the bytes)83 *84 ******************************************************************************/85 86u32 acpi_ut_dword_byte_swap(u32 value)87{88 union {89 u32 value;90 u8 bytes[4];91 } out;92 union {93 u32 value;94 u8 bytes[4];95 } in;96 97 ACPI_FUNCTION_ENTRY();98 99 in.value = value;100 101 out.bytes[0] = in.bytes[3];102 out.bytes[1] = in.bytes[2];103 out.bytes[2] = in.bytes[1];104 out.bytes[3] = in.bytes[0];105 106 return (out.value);107}108 109/*******************************************************************************110 *111 * FUNCTION: acpi_ut_set_integer_width112 *113 * PARAMETERS: Revision From DSDT header114 *115 * RETURN: None116 *117 * DESCRIPTION: Set the global integer bit width based upon the revision118 * of the DSDT. For Revision 1 and 0, Integers are 32 bits.119 * For Revision 2 and above, Integers are 64 bits. Yes, this120 * makes a difference.121 *122 ******************************************************************************/123 124void acpi_ut_set_integer_width(u8 revision)125{126 127 if (revision < 2) {128 129 /* 32-bit case */130 131 acpi_gbl_integer_bit_width = 32;132 acpi_gbl_integer_nybble_width = 8;133 acpi_gbl_integer_byte_width = 4;134 } else {135 /* 64-bit case (ACPI 2.0+) */136 137 acpi_gbl_integer_bit_width = 64;138 acpi_gbl_integer_nybble_width = 16;139 acpi_gbl_integer_byte_width = 8;140 }141}142 143/*******************************************************************************144 *145 * FUNCTION: acpi_ut_create_update_state_and_push146 *147 * PARAMETERS: object - Object to be added to the new state148 * action - Increment/Decrement149 * state_list - List the state will be added to150 *151 * RETURN: Status152 *153 * DESCRIPTION: Create a new state and push it154 *155 ******************************************************************************/156 157acpi_status158acpi_ut_create_update_state_and_push(union acpi_operand_object *object,159 u16 action,160 union acpi_generic_state **state_list)161{162 union acpi_generic_state *state;163 164 ACPI_FUNCTION_ENTRY();165 166 /* Ignore null objects; these are expected */167 168 if (!object) {169 return (AE_OK);170 }171 172 state = acpi_ut_create_update_state(object, action);173 if (!state) {174 return (AE_NO_MEMORY);175 }176 177 acpi_ut_push_generic_state(state_list, state);178 return (AE_OK);179}180 181/*******************************************************************************182 *183 * FUNCTION: acpi_ut_walk_package_tree184 *185 * PARAMETERS: source_object - The package to walk186 * target_object - Target object (if package is being copied)187 * walk_callback - Called once for each package element188 * context - Passed to the callback function189 *190 * RETURN: Status191 *192 * DESCRIPTION: Walk through a package, including subpackages193 *194 ******************************************************************************/195 196acpi_status197acpi_ut_walk_package_tree(union acpi_operand_object *source_object,198 void *target_object,199 acpi_pkg_callback walk_callback, void *context)200{201 acpi_status status = AE_OK;202 union acpi_generic_state *state_list = NULL;203 union acpi_generic_state *state;204 union acpi_operand_object *this_source_obj;205 u32 this_index;206 207 ACPI_FUNCTION_TRACE(ut_walk_package_tree);208 209 state = acpi_ut_create_pkg_state(source_object, target_object, 0);210 if (!state) {211 return_ACPI_STATUS(AE_NO_MEMORY);212 }213 214 while (state) {215 216 /* Get one element of the package */217 218 this_index = state->pkg.index;219 this_source_obj =220 state->pkg.source_object->package.elements[this_index];221 state->pkg.this_target_obj =222 &state->pkg.source_object->package.elements[this_index];223 224 /*225 * Check for:226 * 1) An uninitialized package element. It is completely227 * legal to declare a package and leave it uninitialized228 * 2) Not an internal object - can be a namespace node instead229 * 3) Any type other than a package. Packages are handled in else230 * case below.231 */232 if ((!this_source_obj) ||233 (ACPI_GET_DESCRIPTOR_TYPE(this_source_obj) !=234 ACPI_DESC_TYPE_OPERAND) ||235 (this_source_obj->common.type != ACPI_TYPE_PACKAGE)) {236 status =237 walk_callback(ACPI_COPY_TYPE_SIMPLE,238 this_source_obj, state, context);239 if (ACPI_FAILURE(status)) {240 return_ACPI_STATUS(status);241 }242 243 state->pkg.index++;244 while (state->pkg.index >=245 state->pkg.source_object->package.count) {246 /*247 * We've handled all of the objects at this level, This means248 * that we have just completed a package. That package may249 * have contained one or more packages itself.250 *251 * Delete this state and pop the previous state (package).252 */253 acpi_ut_delete_generic_state(state);254 state = acpi_ut_pop_generic_state(&state_list);255 256 /* Finished when there are no more states */257 258 if (!state) {259 /*260 * We have handled all of the objects in the top level261 * package just add the length of the package objects262 * and exit263 */264 return_ACPI_STATUS(AE_OK);265 }266 267 /*268 * Go back up a level and move the index past the just269 * completed package object.270 */271 state->pkg.index++;272 }273 } else {274 /* This is a subobject of type package */275 276 status =277 walk_callback(ACPI_COPY_TYPE_PACKAGE,278 this_source_obj, state, context);279 if (ACPI_FAILURE(status)) {280 return_ACPI_STATUS(status);281 }282 283 /*284 * Push the current state and create a new one285 * The callback above returned a new target package object.286 */287 acpi_ut_push_generic_state(&state_list, state);288 state =289 acpi_ut_create_pkg_state(this_source_obj,290 state->pkg.this_target_obj,291 0);292 if (!state) {293 294 /* Free any stacked Update State objects */295 296 while (state_list) {297 state =298 acpi_ut_pop_generic_state299 (&state_list);300 acpi_ut_delete_generic_state(state);301 }302 return_ACPI_STATUS(AE_NO_MEMORY);303 }304 }305 }306 307 /* We should never get here */308 309 ACPI_ERROR((AE_INFO, "State list did not terminate correctly"));310 311 return_ACPI_STATUS(AE_AML_INTERNAL);312}313 314#ifdef ACPI_DEBUG_OUTPUT315/*******************************************************************************316 *317 * FUNCTION: acpi_ut_display_init_pathname318 *319 * PARAMETERS: type - Object type of the node320 * obj_handle - Handle whose pathname will be displayed321 * path - Additional path string to be appended.322 * (NULL if no extra path)323 *324 * RETURN: acpi_status325 *326 * DESCRIPTION: Display full pathname of an object, DEBUG ONLY327 *328 ******************************************************************************/329 330void331acpi_ut_display_init_pathname(u8 type,332 struct acpi_namespace_node *obj_handle,333 const char *path)334{335 acpi_status status;336 struct acpi_buffer buffer;337 338 ACPI_FUNCTION_ENTRY();339 340 /* Only print the path if the appropriate debug level is enabled */341 342 if (!(acpi_dbg_level & ACPI_LV_INIT_NAMES)) {343 return;344 }345 346 /* Get the full pathname to the node */347 348 buffer.length = ACPI_ALLOCATE_LOCAL_BUFFER;349 status = acpi_ns_handle_to_pathname(obj_handle, &buffer, TRUE);350 if (ACPI_FAILURE(status)) {351 return;352 }353 354 /* Print what we're doing */355 356 switch (type) {357 case ACPI_TYPE_METHOD:358 359 acpi_os_printf("Executing ");360 break;361 362 default:363 364 acpi_os_printf("Initializing ");365 break;366 }367 368 /* Print the object type and pathname */369 370 acpi_os_printf("%-12s %s",371 acpi_ut_get_type_name(type), (char *)buffer.pointer);372 373 /* Extra path is used to append names like _STA, _INI, etc. */374 375 if (path) {376 acpi_os_printf(".%s", path);377 }378 acpi_os_printf("\n");379 380 ACPI_FREE(buffer.pointer);381}382#endif383