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