Subversion Repositories Kolibri OS

Rev

Go to most recent revision | Blame | Last modification | View Log | Download | RSS feed

  1. /******************************************************************************
  2.  *
  3.  * Module Name: utaddress - op_region address range check
  4.  *
  5.  *****************************************************************************/
  6.  
  7. /*
  8.  * Copyright (C) 2000 - 2015, Intel Corp.
  9.  * All rights reserved.
  10.  *
  11.  * Redistribution and use in source and binary forms, with or without
  12.  * modification, are permitted provided that the following conditions
  13.  * are met:
  14.  * 1. Redistributions of source code must retain the above copyright
  15.  *    notice, this list of conditions, and the following disclaimer,
  16.  *    without modification.
  17.  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
  18.  *    substantially similar to the "NO WARRANTY" disclaimer below
  19.  *    ("Disclaimer") and any redistribution must be conditioned upon
  20.  *    including a substantially similar Disclaimer requirement for further
  21.  *    binary redistribution.
  22.  * 3. Neither the names of the above-listed copyright holders nor the names
  23.  *    of any contributors may be used to endorse or promote products derived
  24.  *    from this software without specific prior written permission.
  25.  *
  26.  * Alternatively, this software may be distributed under the terms of the
  27.  * GNU General Public License ("GPL") version 2 as published by the Free
  28.  * Software Foundation.
  29.  *
  30.  * NO WARRANTY
  31.  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
  32.  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
  33.  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
  34.  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
  35.  * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
  36.  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
  37.  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
  38.  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
  39.  * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
  40.  * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
  41.  * POSSIBILITY OF SUCH DAMAGES.
  42.  */
  43.  
  44. #include <acpi/acpi.h>
  45. #include "accommon.h"
  46. #include "acnamesp.h"
  47.  
  48. #define _COMPONENT          ACPI_UTILITIES
  49. ACPI_MODULE_NAME("utaddress")
  50.  
  51. /*******************************************************************************
  52.  *
  53.  * FUNCTION:    acpi_ut_add_address_range
  54.  *
  55.  * PARAMETERS:  space_id            - Address space ID
  56.  *              address             - op_region start address
  57.  *              length              - op_region length
  58.  *              region_node         - op_region namespace node
  59.  *
  60.  * RETURN:      Status
  61.  *
  62.  * DESCRIPTION: Add the Operation Region address range to the global list.
  63.  *              The only supported Space IDs are Memory and I/O. Called when
  64.  *              the op_region address/length operands are fully evaluated.
  65.  *
  66.  * MUTEX:       Locks the namespace
  67.  *
  68.  * NOTE: Because this interface is only called when an op_region argument
  69.  * list is evaluated, there cannot be any duplicate region_nodes.
  70.  * Duplicate Address/Length values are allowed, however, so that multiple
  71.  * address conflicts can be detected.
  72.  *
  73.  ******************************************************************************/
  74. acpi_status
  75. acpi_ut_add_address_range(acpi_adr_space_type space_id,
  76.                           acpi_physical_address address,
  77.                           u32 length, struct acpi_namespace_node *region_node)
  78. {
  79.         struct acpi_address_range *range_info;
  80.         acpi_status status;
  81.  
  82.         ACPI_FUNCTION_TRACE(ut_add_address_range);
  83.  
  84.         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  85.             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
  86.                 return_ACPI_STATUS(AE_OK);
  87.         }
  88.  
  89.         /* Allocate/init a new info block, add it to the appropriate list */
  90.  
  91.         range_info = ACPI_ALLOCATE(sizeof(struct acpi_address_range));
  92.         if (!range_info) {
  93.                 return_ACPI_STATUS(AE_NO_MEMORY);
  94.         }
  95.  
  96.         range_info->start_address = address;
  97.         range_info->end_address = (address + length - 1);
  98.         range_info->region_node = region_node;
  99.  
  100.         status = acpi_ut_acquire_mutex(ACPI_MTX_NAMESPACE);
  101.         if (ACPI_FAILURE(status)) {
  102.                 ACPI_FREE(range_info);
  103.                 return_ACPI_STATUS(status);
  104.         }
  105.  
  106.         range_info->next = acpi_gbl_address_range_list[space_id];
  107.         acpi_gbl_address_range_list[space_id] = range_info;
  108.  
  109.         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  110.                           "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
  111.                           acpi_ut_get_node_name(range_info->region_node),
  112.                           ACPI_FORMAT_UINT64(address),
  113.                           ACPI_FORMAT_UINT64(range_info->end_address)));
  114.  
  115.         (void)acpi_ut_release_mutex(ACPI_MTX_NAMESPACE);
  116.         return_ACPI_STATUS(AE_OK);
  117. }
  118.  
  119. /*******************************************************************************
  120.  *
  121.  * FUNCTION:    acpi_ut_remove_address_range
  122.  *
  123.  * PARAMETERS:  space_id            - Address space ID
  124.  *              region_node         - op_region namespace node
  125.  *
  126.  * RETURN:      None
  127.  *
  128.  * DESCRIPTION: Remove the Operation Region from the global list. The only
  129.  *              supported Space IDs are Memory and I/O. Called when an
  130.  *              op_region is deleted.
  131.  *
  132.  * MUTEX:       Assumes the namespace is locked
  133.  *
  134.  ******************************************************************************/
  135.  
  136. void
  137. acpi_ut_remove_address_range(acpi_adr_space_type space_id,
  138.                              struct acpi_namespace_node *region_node)
  139. {
  140.         struct acpi_address_range *range_info;
  141.         struct acpi_address_range *prev;
  142.  
  143.         ACPI_FUNCTION_TRACE(ut_remove_address_range);
  144.  
  145.         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  146.             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
  147.                 return_VOID;
  148.         }
  149.  
  150.         /* Get the appropriate list head and check the list */
  151.  
  152.         range_info = prev = acpi_gbl_address_range_list[space_id];
  153.         while (range_info) {
  154.                 if (range_info->region_node == region_node) {
  155.                         if (range_info == prev) {       /* Found at list head */
  156.                                 acpi_gbl_address_range_list[space_id] =
  157.                                     range_info->next;
  158.                         } else {
  159.                                 prev->next = range_info->next;
  160.                         }
  161.  
  162.                         ACPI_DEBUG_PRINT((ACPI_DB_NAMES,
  163.                                           "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
  164.                                           acpi_ut_get_node_name(range_info->
  165.                                                                 region_node),
  166.                                           ACPI_FORMAT_UINT64(range_info->
  167.                                                              start_address),
  168.                                           ACPI_FORMAT_UINT64(range_info->
  169.                                                              end_address)));
  170.  
  171.                         ACPI_FREE(range_info);
  172.                         return_VOID;
  173.                 }
  174.  
  175.                 prev = range_info;
  176.                 range_info = range_info->next;
  177.         }
  178.  
  179.         return_VOID;
  180. }
  181.  
  182. /*******************************************************************************
  183.  *
  184.  * FUNCTION:    acpi_ut_check_address_range
  185.  *
  186.  * PARAMETERS:  space_id            - Address space ID
  187.  *              address             - Start address
  188.  *              length              - Length of address range
  189.  *              warn                - TRUE if warning on overlap desired
  190.  *
  191.  * RETURN:      Count of the number of conflicts detected. Zero is always
  192.  *              returned for Space IDs other than Memory or I/O.
  193.  *
  194.  * DESCRIPTION: Check if the input address range overlaps any of the
  195.  *              ASL operation region address ranges. The only supported
  196.  *              Space IDs are Memory and I/O.
  197.  *
  198.  * MUTEX:       Assumes the namespace is locked.
  199.  *
  200.  ******************************************************************************/
  201.  
  202. u32
  203. acpi_ut_check_address_range(acpi_adr_space_type space_id,
  204.                             acpi_physical_address address, u32 length, u8 warn)
  205. {
  206.         struct acpi_address_range *range_info;
  207.         acpi_physical_address end_address;
  208.         char *pathname;
  209.         u32 overlap_count = 0;
  210.  
  211.         ACPI_FUNCTION_TRACE(ut_check_address_range);
  212.  
  213.         if ((space_id != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
  214.             (space_id != ACPI_ADR_SPACE_SYSTEM_IO)) {
  215.                 return_UINT32(0);
  216.         }
  217.  
  218.         range_info = acpi_gbl_address_range_list[space_id];
  219.         end_address = address + length - 1;
  220.  
  221.         /* Check entire list for all possible conflicts */
  222.  
  223.         while (range_info) {
  224.                 /*
  225.                  * Check if the requested address/length overlaps this
  226.                  * address range. There are four cases to consider:
  227.                  *
  228.                  * 1) Input address/length is contained completely in the
  229.                  *    address range
  230.                  * 2) Input address/length overlaps range at the range start
  231.                  * 3) Input address/length overlaps range at the range end
  232.                  * 4) Input address/length completely encompasses the range
  233.                  */
  234.                 if ((address <= range_info->end_address) &&
  235.                     (end_address >= range_info->start_address)) {
  236.  
  237.                         /* Found an address range overlap */
  238.  
  239.                         overlap_count++;
  240.                         if (warn) {     /* Optional warning message */
  241.                                 pathname =
  242.                                     acpi_ns_get_external_pathname(range_info->
  243.                                                                   region_node);
  244.  
  245.                                 ACPI_WARNING((AE_INFO,
  246.                                               "%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)",
  247.                                               acpi_ut_get_region_name(space_id),
  248.                                               ACPI_FORMAT_UINT64(address),
  249.                                               ACPI_FORMAT_UINT64(end_address),
  250.                                               ACPI_FORMAT_UINT64(range_info->
  251.                                                                  start_address),
  252.                                               ACPI_FORMAT_UINT64(range_info->
  253.                                                                  end_address),
  254.                                               pathname));
  255.                                 ACPI_FREE(pathname);
  256.                         }
  257.                 }
  258.  
  259.                 range_info = range_info->next;
  260.         }
  261.  
  262.         return_UINT32(overlap_count);
  263. }
  264.  
  265. /*******************************************************************************
  266.  *
  267.  * FUNCTION:    acpi_ut_delete_address_lists
  268.  *
  269.  * PARAMETERS:  None
  270.  *
  271.  * RETURN:      None
  272.  *
  273.  * DESCRIPTION: Delete all global address range lists (called during
  274.  *              subsystem shutdown).
  275.  *
  276.  ******************************************************************************/
  277.  
  278. void acpi_ut_delete_address_lists(void)
  279. {
  280.         struct acpi_address_range *next;
  281.         struct acpi_address_range *range_info;
  282.         int i;
  283.  
  284.         /* Delete all elements in all address range lists */
  285.  
  286.         for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++) {
  287.                 next = acpi_gbl_address_range_list[i];
  288.  
  289.                 while (next) {
  290.                         range_info = next;
  291.                         next = range_info->next;
  292.                         ACPI_FREE(range_info);
  293.                 }
  294.  
  295.                 acpi_gbl_address_range_list[i] = NULL;
  296.         }
  297. }
  298.