brintos

brintos / linux-shallow public Read only

0
0
Text · 7.6 KiB · be94d2f Raw
257 lines · c
1// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.02/******************************************************************************3 *4 * Module Name: utaddress - op_region address range check5 *6 * Copyright (C) 2000 - 2023, Intel Corp.7 *8 *****************************************************************************/9 10#include <acpi/acpi.h>11#include "accommon.h"12#include "acnamesp.h"13 14#define _COMPONENT          ACPI_UTILITIES15ACPI_MODULE_NAME("utaddress")16 17/*******************************************************************************18 *19 * FUNCTION:    acpi_ut_add_address_range20 *21 * PARAMETERS:  space_id            - Address space ID22 *              address             - op_region start address23 *              length              - op_region length24 *              region_node         - op_region namespace node25 *26 * RETURN:      Status27 *28 * DESCRIPTION: Add the Operation Region address range to the global list.29 *              The only supported Space IDs are Memory and I/O. Called when30 *              the op_region address/length operands are fully evaluated.31 *32 * MUTEX:       Locks the namespace33 *34 * NOTE: Because this interface is only called when an op_region argument35 * list is evaluated, there cannot be any duplicate region_nodes.36 * Duplicate Address/Length values are allowed, however, so that multiple37 * address conflicts can be detected.38 *39 ******************************************************************************/40acpi_status41acpi_ut_add_address_range(acpi_adr_space_type space_id,42			  acpi_physical_address address,43			  u32 length, struct acpi_namespace_node *region_node)44{45	struct acpi_address_range *range_info;46 47	ACPI_FUNCTION_TRACE(ut_add_address_range);48 49	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&50	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {51		return_ACPI_STATUS(AE_OK);52	}53 54	/* Allocate/init a new info block, add it to the appropriate list */55 56	range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));57	if (!range_info) {58		return_ACPI_STATUS(AE_NO_MEMORY);59	}60 61	range_info->start_address = address;62	range_info->end_address = (address + length - 1);63	range_info->region_node = region_node;64 65	range_info->next = acpi_gbl_address_range_list[space_id];66	acpi_gbl_address_range_list[space_id] = range_info;67 68	ACPI_DEBUG_PRINT((ACPI_DB_NAMES,69			  "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",70			  acpi_ut_get_node_name(range_info->region_node),71			  ACPI_FORMAT_UINT64(address),72			  ACPI_FORMAT_UINT64(range_info->end_address)));73 74	return_ACPI_STATUS(AE_OK);75}76 77/*******************************************************************************78 *79 * FUNCTION:    acpi_ut_remove_address_range80 *81 * PARAMETERS:  space_id            - Address space ID82 *              region_node         - op_region namespace node83 *84 * RETURN:      None85 *86 * DESCRIPTION: Remove the Operation Region from the global list. The only87 *              supported Space IDs are Memory and I/O. Called when an88 *              op_region is deleted.89 *90 * MUTEX:       Assumes the namespace is locked91 *92 ******************************************************************************/93 94void95acpi_ut_remove_address_range(acpi_adr_space_type space_id,96			     struct acpi_namespace_node *region_node)97{98	struct acpi_address_range *range_info;99	struct acpi_address_range *prev;100 101	ACPI_FUNCTION_TRACE(ut_remove_address_range);102 103	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&104	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {105		return_VOID;106	}107 108	/* Get the appropriate list head and check the list */109 110	range_info = prev = acpi_gbl_address_range_list[space_id];111	while (range_info) {112		if (range_info->region_node == region_node) {113			if (range_info == prev) {	/* Found at list head */114				acpi_gbl_address_range_list[space_id] =115				    range_info->next;116			} else {117				prev->next = range_info->next;118			}119 120			ACPI_DEBUG_PRINT((ACPI_DB_NAMES,121					  "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",122					  acpi_ut_get_node_name(range_info->123								region_node),124					  ACPI_FORMAT_UINT64(range_info->125							     start_address),126					  ACPI_FORMAT_UINT64(range_info->127							     end_address)));128 129			ACPI_FREE(range_info);130			return_VOID;131		}132 133		prev = range_info;134		range_info = range_info->next;135	}136 137	return_VOID;138}139 140/*******************************************************************************141 *142 * FUNCTION:    acpi_ut_check_address_range143 *144 * PARAMETERS:  space_id            - Address space ID145 *              address             - Start address146 *              length              - Length of address range147 *              warn                - TRUE if warning on overlap desired148 *149 * RETURN:      Count of the number of conflicts detected. Zero is always150 *              returned for Space IDs other than Memory or I/O.151 *152 * DESCRIPTION: Check if the input address range overlaps any of the153 *              ASL operation region address ranges. The only supported154 *              Space IDs are Memory and I/O.155 *156 * MUTEX:       Assumes the namespace is locked.157 *158 ******************************************************************************/159 160u32161acpi_ut_check_address_range(acpi_adr_space_type space_id,162			    acpi_physical_address address, u32 length, u8 warn)163{164	struct acpi_address_range *range_info;165	acpi_physical_address end_address;166	char *pathname;167	u32 overlap_count = 0;168 169	ACPI_FUNCTION_TRACE(ut_check_address_range);170 171	if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&172	    (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {173		return_UINT32(0);174	}175 176	range_info = acpi_gbl_address_range_list[space_id];177	end_address = address + length - 1;178 179	/* Check entire list for all possible conflicts */180 181	while (range_info) {182		/*183		 * Check if the requested address/length overlaps this184		 * address range. There are four cases to consider:185		 *186		 * 1) Input address/length is contained completely in the187		 *    address range188		 * 2) Input address/length overlaps range at the range start189		 * 3) Input address/length overlaps range at the range end190		 * 4) Input address/length completely encompasses the range191		 */192		if ((address <= range_info->end_address) &&193		    (end_address >= range_info->start_address)) {194 195			/* Found an address range overlap */196 197			overlap_count++;198			if (warn) {	/* Optional warning message */199				pathname =200				    acpi_ns_get_normalized_pathname(range_info->201								    region_node,202								    TRUE);203 204				ACPI_WARNING((AE_INFO,205					      "%s range 0x%8.8X%8.8X-0x%8.8X%8.8X conflicts with OpRegion 0x%8.8X%8.8X-0x%8.8X%8.8X (%s)",206					      acpi_ut_get_region_name(space_id),207					      ACPI_FORMAT_UINT64(address),208					      ACPI_FORMAT_UINT64(end_address),209					      ACPI_FORMAT_UINT64(range_info->210								 start_address),211					      ACPI_FORMAT_UINT64(range_info->212								 end_address),213					      pathname));214				ACPI_FREE(pathname);215			}216		}217 218		range_info = range_info->next;219	}220 221	return_UINT32(overlap_count);222}223 224/*******************************************************************************225 *226 * FUNCTION:    acpi_ut_delete_address_lists227 *228 * PARAMETERS:  None229 *230 * RETURN:      None231 *232 * DESCRIPTION: Delete all global address range lists (called during233 *              subsystem shutdown).234 *235 ******************************************************************************/236 237void acpi_ut_delete_address_lists(void)238{239	struct acpi_address_range *next;240	struct acpi_address_range *range_info;241	int i;242 243	/* Delete all elements in all address range lists */244 245	for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {246		next = acpi_gbl_address_range_list[i];247 248		while (next) {249			range_info = next;250			next = range_info->next;251			ACPI_FREE(range_info);252		}253 254		acpi_gbl_address_range_list[i] = NULL;255	}256}257