cregit-Linux how code gets into the kernel

Release 4.11 drivers/acpi/acpica/rsmisc.c

/*******************************************************************************
 *
 * Module Name: rsmisc - Miscellaneous resource descriptors
 *
 ******************************************************************************/

/*
 * Copyright (C) 2000 - 2017, Intel Corp.
 * All rights reserved.
 *
 * Redistribution and use in source and binary forms, with or without
 * modification, are permitted provided that the following conditions
 * are met:
 * 1. Redistributions of source code must retain the above copyright
 *    notice, this list of conditions, and the following disclaimer,
 *    without modification.
 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
 *    substantially similar to the "NO WARRANTY" disclaimer below
 *    ("Disclaimer") and any redistribution must be conditioned upon
 *    including a substantially similar Disclaimer requirement for further
 *    binary redistribution.
 * 3. Neither the names of the above-listed copyright holders nor the names
 *    of any contributors may be used to endorse or promote products derived
 *    from this software without specific prior written permission.
 *
 * Alternatively, this software may be distributed under the terms of the
 * GNU General Public License ("GPL") version 2 as published by the Free
 * Software Foundation.
 *
 * NO WARRANTY
 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
 * POSSIBILITY OF SUCH DAMAGES.
 */

#include <acpi/acpi.h>
#include "accommon.h"
#include "acresrc.h"


#define _COMPONENT          ACPI_RESOURCES
ACPI_MODULE_NAME("rsmisc")

#define INIT_RESOURCE_TYPE(i)       i->resource_offset

#define INIT_RESOURCE_LENGTH(i)     i->aml_offset

#define INIT_TABLE_LENGTH(i)        i->value

#define COMPARE_OPCODE(i)           i->resource_offset

#define COMPARE_TARGET(i)           i->aml_offset

#define COMPARE_VALUE(i)            i->value
/*******************************************************************************
 *
 * FUNCTION:    acpi_rs_convert_aml_to_resource
 *
 * PARAMETERS:  resource            - Pointer to the resource descriptor
 *              aml                 - Where the AML descriptor is returned
 *              info                - Pointer to appropriate conversion table
 *
 * RETURN:      Status
 *
 * DESCRIPTION: Convert an external AML resource descriptor to the corresponding
 *              internal resource descriptor
 *
 ******************************************************************************/

acpi_status acpi_rs_convert_aml_to_resource(struct acpi_resource *resource, union aml_resource *aml, struct acpi_rsconvert_info *info) { acpi_rs_length aml_resource_length; void *source; void *destination; char *target; u8 count; u8 flags_mode = FALSE; u16 item_count = 0; u16 temp16 = 0; ACPI_FUNCTION_TRACE(rs_convert_aml_to_resource); if (!info) { return_ACPI_STATUS(AE_BAD_PARAMETER); } if (((acpi_size)resource) & 0x3) { /* Each internal resource struct is expected to be 32-bit aligned */ ACPI_WARNING((AE_INFO, "Misaligned resource pointer (get): %p Type 0x%2.2X Length %u", resource, resource->type, resource->length)); } /* Extract the resource Length field (does not include header length) */ aml_resource_length = acpi_ut_get_resource_length(aml); /* * First table entry must be ACPI_RSC_INITxxx and must contain the * table length (# of table entries) */ count = INIT_TABLE_LENGTH(info); while (count) { /* * Source is the external AML byte stream buffer, * destination is the internal resource descriptor */ source = ACPI_ADD_PTR(void, aml, info->aml_offset); destination = ACPI_ADD_PTR(void, resource, info->resource_offset); switch (info->opcode) { case ACPI_RSC_INITGET: /* * Get the resource type and the initial (minimum) length */ memset(resource, 0, INIT_RESOURCE_LENGTH(info)); resource->type = INIT_RESOURCE_TYPE(info); resource->length = INIT_RESOURCE_LENGTH(info); break; case ACPI_RSC_INITSET: break; case ACPI_RSC_FLAGINIT: flags_mode = TRUE; break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ ACPI_SET8(destination, ((ACPI_GET8(source) >> info->value) & 0x01)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ ACPI_SET8(destination, ((ACPI_GET8(source) >> info->value) & 0x03)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ ACPI_SET8(destination, ((ACPI_GET8(source) >> info->value) & 0x07)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); break; case ACPI_RSC_COUNT16: item_count = aml_resource_length; ACPI_SET16(destination, item_count); resource->length = resource->length + (info->value * (item_count - 1)); break; case ACPI_RSC_COUNT_GPIO_PIN: target = ACPI_ADD_PTR(void, aml, info->value); item_count = ACPI_GET16(target) - ACPI_GET16(source); resource->length = resource->length + item_count; item_count = item_count / 2; ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET8(source); ACPI_SET8(destination, item_count); resource->length = resource->length + (info->value * item_count); break; case ACPI_RSC_COUNT_GPIO_RES: /* * Vendor data is optional (length/offset may both be zero) * Examine vendor data length field first */ target = ACPI_ADD_PTR(void, aml, (info->value + 2)); if (ACPI_GET16(target)) { /* Use vendor offset to get resource source length */ target = ACPI_ADD_PTR(void, aml, info->value); item_count = ACPI_GET16(target) - ACPI_GET16(source); } else { /* No vendor data to worry about */ item_count = aml->large_header.resource_length + sizeof(struct aml_resource_large_header) - ACPI_GET16(source); } resource->length = resource->length + item_count; ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_VEN: item_count = ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; ACPI_SET16(destination, item_count); break; case ACPI_RSC_COUNT_SERIAL_RES: item_count = (aml_resource_length + sizeof(struct aml_resource_large_header)) - ACPI_GET16(source) - info->value; resource->length = resource->length + item_count; ACPI_SET16(destination, item_count); break; case ACPI_RSC_LENGTH: resource->length = resource->length + info->value; break; case ACPI_RSC_MOVE8: case ACPI_RSC_MOVE16: case ACPI_RSC_MOVE32: case ACPI_RSC_MOVE64: /* * Raw data move. Use the Info value field unless item_count has * been previously initialized via a COUNT opcode */ if (info->value) { item_count = info->value; } acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_GPIO_PIN: /* Generate and set the PIN data pointer */ target = (char *)ACPI_ADD_PTR(void, resource, (resource->length - item_count * 2)); *(u16 **)destination = ACPI_CAST_PTR(u16, target); /* Copy the PIN data */ source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); acpi_rs_move_data(target, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_GPIO_RES: /* Generate and set the resource_source string pointer */ target = (char *)ACPI_ADD_PTR(void, resource, (resource->length - item_count)); *(u8 **)destination = ACPI_CAST_PTR(u8, target); /* Copy the resource_source string */ source = ACPI_ADD_PTR(void, aml, ACPI_GET16(source)); acpi_rs_move_data(target, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_SERIAL_VEN: /* Generate and set the Vendor Data pointer */ target = (char *)ACPI_ADD_PTR(void, resource, (resource->length - item_count)); *(u8 **)destination = ACPI_CAST_PTR(u8, target); /* Copy the Vendor Data */ source = ACPI_ADD_PTR(void, aml, info->value); acpi_rs_move_data(target, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_SERIAL_RES: /* Generate and set the resource_source string pointer */ target = (char *)ACPI_ADD_PTR(void, resource, (resource->length - item_count)); *(u8 **)destination = ACPI_CAST_PTR(u8, target); /* Copy the resource_source string */ source = ACPI_ADD_PTR(void, aml, (ACPI_GET16(source) + info->value)); acpi_rs_move_data(target, source, item_count, info->opcode); break; case ACPI_RSC_SET8: memset(destination, info->aml_offset, info->value); break; case ACPI_RSC_DATA8: target = ACPI_ADD_PTR(char, resource, info->value); memcpy(destination, source, ACPI_GET16(target)); break; case ACPI_RSC_ADDRESS: /* * Common handler for address descriptor flags */ if (!acpi_rs_get_address_common(resource, aml)) { return_ACPI_STATUS (AE_AML_INVALID_RESOURCE_TYPE); } break; case ACPI_RSC_SOURCE: /* * Optional resource_source (Index and String) */ resource->length += acpi_rs_get_resource_source(aml_resource_length, info->value, destination, aml, NULL); break; case ACPI_RSC_SOURCEX: /* * Optional resource_source (Index and String). This is the more * complicated case used by the Interrupt() macro */ target = ACPI_ADD_PTR(char, resource, info->aml_offset + (item_count * 4)); resource->length += acpi_rs_get_resource_source(aml_resource_length, (acpi_rs_length) (((item_count - 1) * sizeof(u32)) + info->value), destination, aml, target); break; case ACPI_RSC_BITMASK: /* * 8-bit encoded bitmask (DMA macro) */ item_count = acpi_rs_decode_bitmask(ACPI_GET8(source), destination); if (item_count) { resource->length += (item_count - 1); } target = ACPI_ADD_PTR(char, resource, info->value); ACPI_SET8(target, item_count); break; case ACPI_RSC_BITMASK16: /* * 16-bit encoded bitmask (IRQ macro) */ ACPI_MOVE_16_TO_16(&temp16, source); item_count = acpi_rs_decode_bitmask(temp16, destination); if (item_count) { resource->length += (item_count - 1); } target = ACPI_ADD_PTR(char, resource, info->value); ACPI_SET8(target, item_count); break; case ACPI_RSC_EXIT_NE: /* * control - Exit conversion if not equal */ switch (info->resource_offset) { case ACPI_RSC_COMPARE_AML_LENGTH: if (aml_resource_length != info->value) { goto exit; } break; case ACPI_RSC_COMPARE_VALUE: if (ACPI_GET8(source) != info->value) { goto exit; } break; default: ACPI_ERROR((AE_INFO, "Invalid conversion sub-opcode")); return_ACPI_STATUS(AE_BAD_PARAMETER); } break; default: ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); return_ACPI_STATUS(AE_BAD_PARAMETER); } count--; info++; } exit: if (!flags_mode) { /* Round the resource struct length up to the next boundary (32 or 64) */ resource->length = (u32) ACPI_ROUND_UP_TO_NATIVE_WORD(resource->length); } return_ACPI_STATUS(AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Lin Ming85764.39%16.25%
Robert Moore42031.56%1168.75%
Lv Zheng272.03%16.25%
Linus Torvalds (pre-git)181.35%212.50%
Linus Torvalds90.68%16.25%
Total1331100.00%16100.00%

/******************************************************************************* * * FUNCTION: acpi_rs_convert_resource_to_aml * * PARAMETERS: resource - Pointer to the resource descriptor * aml - Where the AML descriptor is returned * info - Pointer to appropriate conversion table * * RETURN: Status * * DESCRIPTION: Convert an internal resource descriptor to the corresponding * external AML resource descriptor. * ******************************************************************************/
acpi_status acpi_rs_convert_resource_to_aml(struct acpi_resource *resource, union aml_resource *aml, struct acpi_rsconvert_info *info) { void *source = NULL; void *destination; char *target; acpi_rsdesc_size aml_length = 0; u8 count; u16 temp16 = 0; u16 item_count = 0; ACPI_FUNCTION_TRACE(rs_convert_resource_to_aml); if (!info) { return_ACPI_STATUS(AE_BAD_PARAMETER); } /* * First table entry must be ACPI_RSC_INITxxx and must contain the * table length (# of table entries) */ count = INIT_TABLE_LENGTH(info); while (count) { /* * Source is the internal resource descriptor, * destination is the external AML byte stream buffer */ source = ACPI_ADD_PTR(void, resource, info->resource_offset); destination = ACPI_ADD_PTR(void, aml, info->aml_offset); switch (info->opcode) { case ACPI_RSC_INITSET: memset(aml, 0, INIT_RESOURCE_LENGTH(info)); aml_length = INIT_RESOURCE_LENGTH(info); acpi_rs_set_resource_header(INIT_RESOURCE_TYPE(info), aml_length, aml); break; case ACPI_RSC_INITGET: break; case ACPI_RSC_FLAGINIT: /* * Clear the flag byte */ ACPI_SET8(destination, 0); break; case ACPI_RSC_1BITFLAG: /* * Mask and shift the flag bit */ ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) ((ACPI_GET8(source) & 0x01) << info-> value)); break; case ACPI_RSC_2BITFLAG: /* * Mask and shift the flag bits */ ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) ((ACPI_GET8(source) & 0x03) << info-> value)); break; case ACPI_RSC_3BITFLAG: /* * Mask and shift the flag bits */ ACPI_SET_BIT(*ACPI_CAST8(destination), (u8) ((ACPI_GET8(source) & 0x07) << info-> value)); break; case ACPI_RSC_COUNT: item_count = ACPI_GET8(source); ACPI_SET8(destination, item_count); aml_length = (u16) (aml_length + (info->value * (item_count - 1))); break; case ACPI_RSC_COUNT16: item_count = ACPI_GET16(source); aml_length = (u16) (aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_PIN: item_count = ACPI_GET16(source); ACPI_SET16(destination, aml_length); aml_length = (u16)(aml_length + item_count * 2); target = ACPI_ADD_PTR(void, aml, info->value); ACPI_SET16(target, aml_length); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_VEN: item_count = ACPI_GET16(source); ACPI_SET16(destination, item_count); aml_length = (u16)(aml_length + (info->value * item_count)); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_GPIO_RES: /* Set resource source string length */ item_count = ACPI_GET16(source); ACPI_SET16(destination, aml_length); /* Compute offset for the Vendor Data */ aml_length = (u16)(aml_length + item_count); target = ACPI_ADD_PTR(void, aml, info->value); /* Set vendor offset only if there is vendor data */ if (resource->data.gpio.vendor_length) { ACPI_SET16(target, aml_length); } acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_SERIAL_VEN: item_count = ACPI_GET16(source); ACPI_SET16(destination, item_count + info->value); aml_length = (u16)(aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_COUNT_SERIAL_RES: item_count = ACPI_GET16(source); aml_length = (u16)(aml_length + item_count); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_LENGTH: acpi_rs_set_resource_length(info->value, aml); break; case ACPI_RSC_MOVE8: case ACPI_RSC_MOVE16: case ACPI_RSC_MOVE32: case ACPI_RSC_MOVE64: if (info->value) { item_count = info->value; } acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_GPIO_PIN: destination = (char *)ACPI_ADD_PTR(void, aml, ACPI_GET16 (destination)); source = *(u16 **)source; acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_GPIO_RES: /* Used for both resource_source string and vendor_data */ destination = (char *)ACPI_ADD_PTR(void, aml, ACPI_GET16 (destination)); source = *(u8 **)source; acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_SERIAL_VEN: destination = (char *)ACPI_ADD_PTR(void, aml, (aml_length - item_count)); source = *(u8 **)source; acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_MOVE_SERIAL_RES: destination = (char *)ACPI_ADD_PTR(void, aml, (aml_length - item_count)); source = *(u8 **)source; acpi_rs_move_data(destination, source, item_count, info->opcode); break; case ACPI_RSC_ADDRESS: /* Set the Resource Type, General Flags, and Type-Specific Flags */ acpi_rs_set_address_common(aml, resource); break; case ACPI_RSC_SOURCEX: /* * Optional resource_source (Index and String) */ aml_length = acpi_rs_set_resource_source(aml, (acpi_rs_length) aml_length, source); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_SOURCE: /* * Optional resource_source (Index and String). This is the more * complicated case used by the Interrupt() macro */ aml_length = acpi_rs_set_resource_source(aml, info->value, source); acpi_rs_set_resource_length(aml_length, aml); break; case ACPI_RSC_BITMASK: /* * 8-bit encoded bitmask (DMA macro) */ ACPI_SET8(destination, acpi_rs_encode_bitmask(source, *ACPI_ADD_PTR(u8, resource, info-> value))); break; case ACPI_RSC_BITMASK16: /* * 16-bit encoded bitmask (IRQ macro) */ temp16 = acpi_rs_encode_bitmask(source, *ACPI_ADD_PTR(u8, resource, info->value)); ACPI_MOVE_16_TO_16(destination, &temp16); break; case ACPI_RSC_EXIT_LE: /* * control - Exit conversion if less than or equal */ if (item_count <= info->value) { goto exit; } break; case ACPI_RSC_EXIT_NE: /* * control - Exit conversion if not equal */ switch (COMPARE_OPCODE(info)) { case ACPI_RSC_COMPARE_VALUE: if (*ACPI_ADD_PTR(u8, resource, COMPARE_TARGET(info)) != COMPARE_VALUE(info)) { goto exit; } break; default: ACPI_ERROR((AE_INFO, "Invalid conversion sub-opcode")); return_ACPI_STATUS(AE_BAD_PARAMETER); } break; case ACPI_RSC_EXIT_EQ: /* * control - Exit conversion if equal */ if (*ACPI_ADD_PTR(u8, resource, COMPARE_TARGET(info)) == COMPARE_VALUE(info)) { goto exit; } break; default: ACPI_ERROR((AE_INFO, "Invalid conversion opcode")); return_ACPI_STATUS(AE_BAD_PARAMETER); } count--; info++; } exit: return_ACPI_STATUS(AE_OK); }

Contributors

PersonTokensPropCommitsCommitProp
Lin Ming59956.24%18.33%
Robert Moore38436.06%866.67%
Lv Zheng363.38%18.33%
Linus Torvalds (pre-git)242.25%18.33%
Linus Torvalds222.07%18.33%
Total1065100.00%12100.00%

#if 0 /* Previous resource validations */ if (aml->ext_address64.revision_ID != AML_RESOURCE_EXTENDED_ADDRESS_REVISION) { return_ACPI_STATUS(AE_SUPPORT); } if (resource->data.start_dpf.performance_robustness >= 3) { return_ACPI_STATUS(AE_AML_BAD_RESOURCE_VALUE); } if (((aml->irq.flags & 0x09) == 0x00) || ((aml->irq.flags & 0x09) == 0x09)) { /* * Only [active_high, edge_sensitive] or [active_low, level_sensitive] * polarity/trigger interrupts are allowed (ACPI spec, section * "IRQ Format"), so 0x00 and 0x09 are illegal. */ ACPI_ERROR((AE_INFO, "Invalid interrupt polarity/trigger in resource list, 0x%X", aml->irq.flags)); return_ACPI_STATUS(AE_BAD_DATA); } resource->data.extended_irq.interrupt_count = temp8; if (temp8 < 1) { /* Must have at least one IRQ */ return_ACPI_STATUS(AE_AML_BAD_RESOURCE_LENGTH); } if (resource->data.dma.transfer == 0x03) { ACPI_ERROR((AE_INFO, "Invalid DMA.Transfer preference (3)")); return_ACPI_STATUS(AE_BAD_DATA); } #endif

Overall Contributors

PersonTokensPropCommitsCommitProp
Lin Ming145658.95%14.00%
Robert Moore86234.90%1456.00%
Lv Zheng632.55%14.00%
Linus Torvalds (pre-git)522.11%312.00%
Linus Torvalds321.30%28.00%
Len Brown20.08%14.00%
Andy Grover20.08%28.00%
Patrick Mochel10.04%14.00%
Total2470100.00%25100.00%
Information contained on this website is for historical information purposes only and does not indicate or represent copyright ownership.
Created with cregit.