525 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: utxface - External interfaces, miscellaneous utility functions5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#define EXPORT_ACPI_INTERFACES11 12#include <acpi/acpi.h>13#include "accommon.h"14#include "acdebug.h"15 16#define _COMPONENT ACPI_UTILITIES17ACPI_MODULE_NAME("utxface")18 19/*******************************************************************************20 *21 * FUNCTION: acpi_terminate22 *23 * PARAMETERS: None24 *25 * RETURN: Status26 *27 * DESCRIPTION: Shutdown the ACPICA subsystem and release all resources.28 *29 ******************************************************************************/30acpi_status ACPI_INIT_FUNCTION acpi_terminate(void)31{32 acpi_status status;33 34 ACPI_FUNCTION_TRACE(acpi_terminate);35 36 /* Shutdown and free all resources */37 38 acpi_ut_subsystem_shutdown();39 40 /* Free the mutex objects */41 42 acpi_ut_mutex_terminate();43 44 /* Now we can shutdown the OS-dependent layer */45 46 status = acpi_os_terminate();47 return_ACPI_STATUS(status);48}49 50ACPI_EXPORT_SYMBOL_INIT(acpi_terminate)51 52#ifndef ACPI_ASL_COMPILER53#ifdef ACPI_FUTURE_USAGE54/*******************************************************************************55 *56 * FUNCTION: acpi_subsystem_status57 *58 * PARAMETERS: None59 *60 * RETURN: Status of the ACPI subsystem61 *62 * DESCRIPTION: Other drivers that use the ACPI subsystem should call this63 * before making any other calls, to ensure the subsystem64 * initialized successfully.65 *66 ******************************************************************************/67acpi_status acpi_subsystem_status(void)68{69 70 if (acpi_gbl_startup_flags & ACPI_INITIALIZED_OK) {71 return (AE_OK);72 } else {73 return (AE_ERROR);74 }75}76 77ACPI_EXPORT_SYMBOL(acpi_subsystem_status)78 79/*******************************************************************************80 *81 * FUNCTION: acpi_get_system_info82 *83 * PARAMETERS: out_buffer - A buffer to receive the resources for the84 * device85 *86 * RETURN: status - the status of the call87 *88 * DESCRIPTION: This function is called to get information about the current89 * state of the ACPI subsystem. It will return system information90 * in the out_buffer.91 *92 * If the function fails an appropriate status will be returned93 * and the value of out_buffer is undefined.94 *95 ******************************************************************************/96acpi_status acpi_get_system_info(struct acpi_buffer *out_buffer)97{98 struct acpi_system_info *info_ptr;99 acpi_status status;100 101 ACPI_FUNCTION_TRACE(acpi_get_system_info);102 103 /* Parameter validation */104 105 status = acpi_ut_validate_buffer(out_buffer);106 if (ACPI_FAILURE(status)) {107 return_ACPI_STATUS(status);108 }109 110 /* Validate/Allocate/Clear caller buffer */111 112 status =113 acpi_ut_initialize_buffer(out_buffer,114 sizeof(struct acpi_system_info));115 if (ACPI_FAILURE(status)) {116 return_ACPI_STATUS(status);117 }118 119 /*120 * Populate the return buffer121 */122 info_ptr = (struct acpi_system_info *)out_buffer->pointer;123 info_ptr->acpi_ca_version = ACPI_CA_VERSION;124 125 /* System flags (ACPI capabilities) */126 127 info_ptr->flags = ACPI_SYS_MODE_ACPI;128 129 /* Timer resolution - 24 or 32 bits */130 131 if (acpi_gbl_FADT.flags & ACPI_FADT_32BIT_TIMER) {132 info_ptr->timer_resolution = 24;133 } else {134 info_ptr->timer_resolution = 32;135 }136 137 /* Clear the reserved fields */138 139 info_ptr->reserved1 = 0;140 info_ptr->reserved2 = 0;141 142 /* Current debug levels */143 144 info_ptr->debug_layer = acpi_dbg_layer;145 info_ptr->debug_level = acpi_dbg_level;146 147 return_ACPI_STATUS(AE_OK);148}149 150ACPI_EXPORT_SYMBOL(acpi_get_system_info)151 152/*******************************************************************************153 *154 * FUNCTION: acpi_get_statistics155 *156 * PARAMETERS: stats - Where the statistics are returned157 *158 * RETURN: status - the status of the call159 *160 * DESCRIPTION: Get the contents of the various system counters161 *162 ******************************************************************************/163acpi_status acpi_get_statistics(struct acpi_statistics *stats)164{165 ACPI_FUNCTION_TRACE(acpi_get_statistics);166 167 /* Parameter validation */168 169 if (!stats) {170 return_ACPI_STATUS(AE_BAD_PARAMETER);171 }172 173 /* Various interrupt-based event counters */174 175 stats->sci_count = acpi_sci_count;176 stats->gpe_count = acpi_gpe_count;177 178 memcpy(stats->fixed_event_count, acpi_fixed_event_count,179 sizeof(acpi_fixed_event_count));180 181 /* Other counters */182 183 stats->method_count = acpi_method_count;184 return_ACPI_STATUS(AE_OK);185}186 187ACPI_EXPORT_SYMBOL(acpi_get_statistics)188 189/*****************************************************************************190 *191 * FUNCTION: acpi_install_initialization_handler192 *193 * PARAMETERS: handler - Callback procedure194 * function - Not (currently) used, see below195 *196 * RETURN: Status197 *198 * DESCRIPTION: Install an initialization handler199 *200 * TBD: When a second function is added, must save the Function also.201 *202 ****************************************************************************/203acpi_status204acpi_install_initialization_handler(acpi_init_handler handler, u32 function)205{206 207 if (!handler) {208 return (AE_BAD_PARAMETER);209 }210 211 if (acpi_gbl_init_handler) {212 return (AE_ALREADY_EXISTS);213 }214 215 acpi_gbl_init_handler = handler;216 return (AE_OK);217}218 219ACPI_EXPORT_SYMBOL(acpi_install_initialization_handler)220#endif221 222/*****************************************************************************223 *224 * FUNCTION: acpi_purge_cached_objects225 *226 * PARAMETERS: None227 *228 * RETURN: Status229 *230 * DESCRIPTION: Empty all caches (delete the cached objects)231 *232 ****************************************************************************/233acpi_status acpi_purge_cached_objects(void)234{235 ACPI_FUNCTION_TRACE(acpi_purge_cached_objects);236 237 (void)acpi_os_purge_cache(acpi_gbl_state_cache);238 (void)acpi_os_purge_cache(acpi_gbl_operand_cache);239 (void)acpi_os_purge_cache(acpi_gbl_ps_node_cache);240 (void)acpi_os_purge_cache(acpi_gbl_ps_node_ext_cache);241 242 return_ACPI_STATUS(AE_OK);243}244 245ACPI_EXPORT_SYMBOL(acpi_purge_cached_objects)246 247/*****************************************************************************248 *249 * FUNCTION: acpi_install_interface250 *251 * PARAMETERS: interface_name - The interface to install252 *253 * RETURN: Status254 *255 * DESCRIPTION: Install an _OSI interface to the global list256 *257 ****************************************************************************/258acpi_status acpi_install_interface(acpi_string interface_name)259{260 acpi_status status;261 struct acpi_interface_info *interface_info;262 263 /* Parameter validation */264 265 if (!interface_name || (strlen(interface_name) == 0)) {266 return (AE_BAD_PARAMETER);267 }268 269 status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);270 if (ACPI_FAILURE(status)) {271 return (status);272 }273 274 /* Check if the interface name is already in the global list */275 276 interface_info = acpi_ut_get_interface(interface_name);277 if (interface_info) {278 /*279 * The interface already exists in the list. This is OK if the280 * interface has been marked invalid -- just clear the bit.281 */282 if (interface_info->flags & ACPI_OSI_INVALID) {283 interface_info->flags &= ~ACPI_OSI_INVALID;284 status = AE_OK;285 } else {286 status = AE_ALREADY_EXISTS;287 }288 } else {289 /* New interface name, install into the global list */290 291 status = acpi_ut_install_interface(interface_name);292 }293 294 acpi_os_release_mutex(acpi_gbl_osi_mutex);295 return (status);296}297 298ACPI_EXPORT_SYMBOL(acpi_install_interface)299 300/*****************************************************************************301 *302 * FUNCTION: acpi_remove_interface303 *304 * PARAMETERS: interface_name - The interface to remove305 *306 * RETURN: Status307 *308 * DESCRIPTION: Remove an _OSI interface from the global list309 *310 ****************************************************************************/311acpi_status acpi_remove_interface(acpi_string interface_name)312{313 acpi_status status;314 315 /* Parameter validation */316 317 if (!interface_name || (strlen(interface_name) == 0)) {318 return (AE_BAD_PARAMETER);319 }320 321 status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);322 if (ACPI_FAILURE(status)) {323 return (status);324 }325 326 status = acpi_ut_remove_interface(interface_name);327 328 acpi_os_release_mutex(acpi_gbl_osi_mutex);329 return (status);330}331 332ACPI_EXPORT_SYMBOL(acpi_remove_interface)333 334/*****************************************************************************335 *336 * FUNCTION: acpi_install_interface_handler337 *338 * PARAMETERS: handler - The _OSI interface handler to install339 * NULL means "remove existing handler"340 *341 * RETURN: Status342 *343 * DESCRIPTION: Install a handler for the predefined _OSI ACPI method.344 * invoked during execution of the internal implementation of345 * _OSI. A NULL handler simply removes any existing handler.346 *347 ****************************************************************************/348acpi_status acpi_install_interface_handler(acpi_interface_handler handler)349{350 acpi_status status;351 352 status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);353 if (ACPI_FAILURE(status)) {354 return (status);355 }356 357 if (handler && acpi_gbl_interface_handler) {358 status = AE_ALREADY_EXISTS;359 } else {360 acpi_gbl_interface_handler = handler;361 }362 363 acpi_os_release_mutex(acpi_gbl_osi_mutex);364 return (status);365}366 367ACPI_EXPORT_SYMBOL(acpi_install_interface_handler)368 369/*****************************************************************************370 *371 * FUNCTION: acpi_update_interfaces372 *373 * PARAMETERS: action - Actions to be performed during the374 * update375 *376 * RETURN: Status377 *378 * DESCRIPTION: Update _OSI interface strings, disabling or enabling OS vendor379 * string or/and feature group strings.380 *381 ****************************************************************************/382acpi_status acpi_update_interfaces(u8 action)383{384 acpi_status status;385 386 status = acpi_os_acquire_mutex(acpi_gbl_osi_mutex, ACPI_WAIT_FOREVER);387 if (ACPI_FAILURE(status)) {388 return (status);389 }390 391 status = acpi_ut_update_interfaces(action);392 393 acpi_os_release_mutex(acpi_gbl_osi_mutex);394 return (status);395}396 397/*****************************************************************************398 *399 * FUNCTION: acpi_check_address_range400 *401 * PARAMETERS: space_id - Address space ID402 * address - Start address403 * length - Length404 * warn - TRUE if warning on overlap desired405 *406 * RETURN: Count of the number of conflicts detected.407 *408 * DESCRIPTION: Check if the input address range overlaps any of the409 * ASL operation region address ranges.410 *411 ****************************************************************************/412 413u32414acpi_check_address_range(acpi_adr_space_type space_id,415 acpi_physical_address address,416 acpi_size length, u8 warn)417{418 u32 overlaps;419 acpi_status status;420 421 status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);422 if (ACPI_FAILURE(status)) {423 return (0);424 }425 426 overlaps = acpi_ut_check_address_range(space_id, address,427 (u32)length, warn);428 429 (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);430 return (overlaps);431}432 433ACPI_EXPORT_SYMBOL(acpi_check_address_range)434#endif /* !ACPI_ASL_COMPILER */435/*******************************************************************************436 *437 * FUNCTION: acpi_decode_pld_buffer438 *439 * PARAMETERS: in_buffer - Buffer returned by _PLD method440 * length - Length of the in_buffer441 * return_buffer - Where the decode buffer is returned442 *443 * RETURN: Status and the decoded _PLD buffer. User must deallocate444 * the buffer via ACPI_FREE.445 *446 * DESCRIPTION: Decode the bit-packed buffer returned by the _PLD method into447 * a local struct that is much more useful to an ACPI driver.448 *449 ******************************************************************************/450acpi_status451acpi_decode_pld_buffer(u8 *in_buffer,452 acpi_size length, struct acpi_pld_info **return_buffer)453{454 struct acpi_pld_info *pld_info;455 u32 *buffer = ACPI_CAST_PTR(u32, in_buffer);456 u32 dword;457 458 /* Parameter validation */459 460 if (!in_buffer || !return_buffer461 || (length < ACPI_PLD_REV1_BUFFER_SIZE)) {462 return (AE_BAD_PARAMETER);463 }464 465 pld_info = ACPI_ALLOCATE_ZEROED(sizeof(struct acpi_pld_info));466 if (!pld_info) {467 return (AE_NO_MEMORY);468 }469 470 /* First 32-bit DWord */471 472 ACPI_MOVE_32_TO_32(&dword, &buffer[0]);473 pld_info->revision = ACPI_PLD_GET_REVISION(&dword);474 pld_info->ignore_color = ACPI_PLD_GET_IGNORE_COLOR(&dword);475 pld_info->red = ACPI_PLD_GET_RED(&dword);476 pld_info->green = ACPI_PLD_GET_GREEN(&dword);477 pld_info->blue = ACPI_PLD_GET_BLUE(&dword);478 479 /* Second 32-bit DWord */480 481 ACPI_MOVE_32_TO_32(&dword, &buffer[1]);482 pld_info->width = ACPI_PLD_GET_WIDTH(&dword);483 pld_info->height = ACPI_PLD_GET_HEIGHT(&dword);484 485 /* Third 32-bit DWord */486 487 ACPI_MOVE_32_TO_32(&dword, &buffer[2]);488 pld_info->user_visible = ACPI_PLD_GET_USER_VISIBLE(&dword);489 pld_info->dock = ACPI_PLD_GET_DOCK(&dword);490 pld_info->lid = ACPI_PLD_GET_LID(&dword);491 pld_info->panel = ACPI_PLD_GET_PANEL(&dword);492 pld_info->vertical_position = ACPI_PLD_GET_VERTICAL(&dword);493 pld_info->horizontal_position = ACPI_PLD_GET_HORIZONTAL(&dword);494 pld_info->shape = ACPI_PLD_GET_SHAPE(&dword);495 pld_info->group_orientation = ACPI_PLD_GET_ORIENTATION(&dword);496 pld_info->group_token = ACPI_PLD_GET_TOKEN(&dword);497 pld_info->group_position = ACPI_PLD_GET_POSITION(&dword);498 pld_info->bay = ACPI_PLD_GET_BAY(&dword);499 500 /* Fourth 32-bit DWord */501 502 ACPI_MOVE_32_TO_32(&dword, &buffer[3]);503 pld_info->ejectable = ACPI_PLD_GET_EJECTABLE(&dword);504 pld_info->ospm_eject_required = ACPI_PLD_GET_OSPM_EJECT(&dword);505 pld_info->cabinet_number = ACPI_PLD_GET_CABINET(&dword);506 pld_info->card_cage_number = ACPI_PLD_GET_CARD_CAGE(&dword);507 pld_info->reference = ACPI_PLD_GET_REFERENCE(&dword);508 pld_info->rotation = ACPI_PLD_GET_ROTATION(&dword);509 pld_info->order = ACPI_PLD_GET_ORDER(&dword);510 511 if (length >= ACPI_PLD_REV2_BUFFER_SIZE) {512 513 /* Fifth 32-bit DWord (Revision 2 of _PLD) */514 515 ACPI_MOVE_32_TO_32(&dword, &buffer[4]);516 pld_info->vertical_offset = ACPI_PLD_GET_VERT_OFFSET(&dword);517 pld_info->horizontal_offset = ACPI_PLD_GET_HORIZ_OFFSET(&dword);518 }519 520 *return_buffer = pld_info;521 return (AE_OK);522}523 524ACPI_EXPORT_SYMBOL(acpi_decode_pld_buffer)525