Home | History | Annotate | Line # | Download | only in utilities
utaddress.c revision 1.1.1.3
      1 /******************************************************************************
      2  *
      3  * Module Name: utaddress - OpRegion 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.h"
     45 #include "accommon.h"
     46 #include "acnamesp.h"
     47 
     48 
     49 #define _COMPONENT          ACPI_UTILITIES
     50         ACPI_MODULE_NAME    ("utaddress")
     51 
     52 
     53 /*******************************************************************************
     54  *
     55  * FUNCTION:    AcpiUtAddAddressRange
     56  *
     57  * PARAMETERS:  SpaceId             - Address space ID
     58  *              Address             - OpRegion start address
     59  *              Length              - OpRegion length
     60  *              RegionNode          - OpRegion namespace node
     61  *
     62  * RETURN:      Status
     63  *
     64  * DESCRIPTION: Add the Operation Region address range to the global list.
     65  *              The only supported Space IDs are Memory and I/O. Called when
     66  *              the OpRegion address/length operands are fully evaluated.
     67  *
     68  * MUTEX:       Locks the namespace
     69  *
     70  * NOTE: Because this interface is only called when an OpRegion argument
     71  * list is evaluated, there cannot be any duplicate RegionNodes.
     72  * Duplicate Address/Length values are allowed, however, so that multiple
     73  * address conflicts can be detected.
     74  *
     75  ******************************************************************************/
     76 
     77 ACPI_STATUS
     78 AcpiUtAddAddressRange (
     79     ACPI_ADR_SPACE_TYPE     SpaceId,
     80     ACPI_PHYSICAL_ADDRESS   Address,
     81     UINT32                  Length,
     82     ACPI_NAMESPACE_NODE     *RegionNode)
     83 {
     84     ACPI_ADDRESS_RANGE      *RangeInfo;
     85     ACPI_STATUS             Status;
     86 
     87 
     88     ACPI_FUNCTION_TRACE (UtAddAddressRange);
     89 
     90 
     91     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
     92         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
     93     {
     94         return_ACPI_STATUS (AE_OK);
     95     }
     96 
     97     /* Allocate/init a new info block, add it to the appropriate list */
     98 
     99     RangeInfo = ACPI_ALLOCATE (sizeof (ACPI_ADDRESS_RANGE));
    100     if (!RangeInfo)
    101     {
    102         return_ACPI_STATUS (AE_NO_MEMORY);
    103     }
    104 
    105     RangeInfo->StartAddress = Address;
    106     RangeInfo->EndAddress = (Address + Length - 1);
    107     RangeInfo->RegionNode = RegionNode;
    108 
    109     Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
    110     if (ACPI_FAILURE (Status))
    111     {
    112         ACPI_FREE (RangeInfo);
    113         return_ACPI_STATUS (Status);
    114     }
    115 
    116     RangeInfo->Next = AcpiGbl_AddressRangeList[SpaceId];
    117     AcpiGbl_AddressRangeList[SpaceId] = RangeInfo;
    118 
    119     ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
    120         "\nAdded [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
    121         AcpiUtGetNodeName (RangeInfo->RegionNode),
    122         ACPI_FORMAT_UINT64 (Address),
    123         ACPI_FORMAT_UINT64 (RangeInfo->EndAddress)));
    124 
    125     (void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
    126     return_ACPI_STATUS (AE_OK);
    127 }
    128 
    129 
    130 /*******************************************************************************
    131  *
    132  * FUNCTION:    AcpiUtRemoveAddressRange
    133  *
    134  * PARAMETERS:  SpaceId             - Address space ID
    135  *              RegionNode          - OpRegion namespace node
    136  *
    137  * RETURN:      None
    138  *
    139  * DESCRIPTION: Remove the Operation Region from the global list. The only
    140  *              supported Space IDs are Memory and I/O. Called when an
    141  *              OpRegion is deleted.
    142  *
    143  * MUTEX:       Assumes the namespace is locked
    144  *
    145  ******************************************************************************/
    146 
    147 void
    148 AcpiUtRemoveAddressRange (
    149     ACPI_ADR_SPACE_TYPE     SpaceId,
    150     ACPI_NAMESPACE_NODE     *RegionNode)
    151 {
    152     ACPI_ADDRESS_RANGE      *RangeInfo;
    153     ACPI_ADDRESS_RANGE      *Prev;
    154 
    155 
    156     ACPI_FUNCTION_TRACE (UtRemoveAddressRange);
    157 
    158 
    159     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
    160         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
    161     {
    162         return_VOID;
    163     }
    164 
    165     /* Get the appropriate list head and check the list */
    166 
    167     RangeInfo = Prev = AcpiGbl_AddressRangeList[SpaceId];
    168     while (RangeInfo)
    169     {
    170         if (RangeInfo->RegionNode == RegionNode)
    171         {
    172             if (RangeInfo == Prev) /* Found at list head */
    173             {
    174                 AcpiGbl_AddressRangeList[SpaceId] = RangeInfo->Next;
    175             }
    176             else
    177             {
    178                 Prev->Next = RangeInfo->Next;
    179             }
    180 
    181             ACPI_DEBUG_PRINT ((ACPI_DB_NAMES,
    182                 "\nRemoved [%4.4s] address range: 0x%8.8X%8.8X-0x%8.8X%8.8X\n",
    183                 AcpiUtGetNodeName (RangeInfo->RegionNode),
    184                 ACPI_FORMAT_UINT64 (RangeInfo->StartAddress),
    185                 ACPI_FORMAT_UINT64 (RangeInfo->EndAddress)));
    186 
    187             ACPI_FREE (RangeInfo);
    188             return_VOID;
    189         }
    190 
    191         Prev = RangeInfo;
    192         RangeInfo = RangeInfo->Next;
    193     }
    194 
    195     return_VOID;
    196 }
    197 
    198 
    199 /*******************************************************************************
    200  *
    201  * FUNCTION:    AcpiUtCheckAddressRange
    202  *
    203  * PARAMETERS:  SpaceId             - Address space ID
    204  *              Address             - Start address
    205  *              Length              - Length of address range
    206  *              Warn                - TRUE if warning on overlap desired
    207  *
    208  * RETURN:      Count of the number of conflicts detected. Zero is always
    209  *              returned for Space IDs other than Memory or I/O.
    210  *
    211  * DESCRIPTION: Check if the input address range overlaps any of the
    212  *              ASL operation region address ranges. The only supported
    213  *              Space IDs are Memory and I/O.
    214  *
    215  * MUTEX:       Assumes the namespace is locked.
    216  *
    217  ******************************************************************************/
    218 
    219 UINT32
    220 AcpiUtCheckAddressRange (
    221     ACPI_ADR_SPACE_TYPE     SpaceId,
    222     ACPI_PHYSICAL_ADDRESS   Address,
    223     UINT32                  Length,
    224     BOOLEAN                 Warn)
    225 {
    226     ACPI_ADDRESS_RANGE      *RangeInfo;
    227     ACPI_PHYSICAL_ADDRESS   EndAddress;
    228     char                    *Pathname;
    229     UINT32                  OverlapCount = 0;
    230 
    231 
    232     ACPI_FUNCTION_TRACE (UtCheckAddressRange);
    233 
    234 
    235     if ((SpaceId != ACPI_ADR_SPACE_SYSTEM_MEMORY) &&
    236         (SpaceId != ACPI_ADR_SPACE_SYSTEM_IO))
    237     {
    238         return_UINT32 (0);
    239     }
    240 
    241     RangeInfo = AcpiGbl_AddressRangeList[SpaceId];
    242     EndAddress = Address + Length - 1;
    243 
    244     /* Check entire list for all possible conflicts */
    245 
    246     while (RangeInfo)
    247     {
    248         /*
    249          * Check if the requested address/length overlaps this
    250          * address range. There are four cases to consider:
    251          *
    252          * 1) Input address/length is contained completely in the
    253          *    address range
    254          * 2) Input address/length overlaps range at the range start
    255          * 3) Input address/length overlaps range at the range end
    256          * 4) Input address/length completely encompasses the range
    257          */
    258         if ((Address <= RangeInfo->EndAddress) &&
    259             (EndAddress >= RangeInfo->StartAddress))
    260         {
    261             /* Found an address range overlap */
    262 
    263             OverlapCount++;
    264             if (Warn)   /* Optional warning message */
    265             {
    266                 Pathname = AcpiNsGetExternalPathname (RangeInfo->RegionNode);
    267 
    268                 ACPI_WARNING ((AE_INFO,
    269                     "%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)",
    270                     AcpiUtGetRegionName (SpaceId),
    271                     ACPI_FORMAT_UINT64 (Address),
    272                     ACPI_FORMAT_UINT64 (EndAddress),
    273                     ACPI_FORMAT_UINT64 (RangeInfo->StartAddress),
    274                     ACPI_FORMAT_UINT64 (RangeInfo->EndAddress),
    275                     Pathname));
    276                 ACPI_FREE (Pathname);
    277             }
    278         }
    279 
    280         RangeInfo = RangeInfo->Next;
    281     }
    282 
    283     return_UINT32 (OverlapCount);
    284 }
    285 
    286 
    287 /*******************************************************************************
    288  *
    289  * FUNCTION:    AcpiUtDeleteAddressLists
    290  *
    291  * PARAMETERS:  None
    292  *
    293  * RETURN:      None
    294  *
    295  * DESCRIPTION: Delete all global address range lists (called during
    296  *              subsystem shutdown).
    297  *
    298  ******************************************************************************/
    299 
    300 void
    301 AcpiUtDeleteAddressLists (
    302     void)
    303 {
    304     ACPI_ADDRESS_RANGE      *Next;
    305     ACPI_ADDRESS_RANGE      *RangeInfo;
    306     int                     i;
    307 
    308 
    309     /* Delete all elements in all address range lists */
    310 
    311     for (i = 0; i < ACPI_ADDRESS_RANGE_MAX; i++)
    312     {
    313         Next = AcpiGbl_AddressRangeList[i];
    314 
    315         while (Next)
    316         {
    317             RangeInfo = Next;
    318             Next = RangeInfo->Next;
    319             ACPI_FREE (RangeInfo);
    320         }
    321 
    322         AcpiGbl_AddressRangeList[i] = NULL;
    323     }
    324 }
    325