hwvalid.c revision 9980:13d7f3eec672
1270866Simp 2270866Simp/****************************************************************************** 3270866Simp * 4270866Simp * Module Name: hwvalid - I/O request validation 5270866Simp * 6270866Simp *****************************************************************************/ 7270866Simp 8270866Simp/****************************************************************************** 9270866Simp * 10270866Simp * 1. Copyright Notice 11270866Simp * 12270866Simp * Some or all of this work - Copyright (c) 1999 - 2009, Intel Corp. 13270866Simp * All rights reserved. 14270866Simp * 15270866Simp * 2. License 16270866Simp * 17270866Simp * 2.1. This is your license from Intel Corp. under its intellectual property 18270866Simp * rights. You may have additional license terms from the party that provided 19270866Simp * you this software, covering your right to use that party's intellectual 20270866Simp * property rights. 21270866Simp * 22270866Simp * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a 23270866Simp * copy of the source code appearing in this file ("Covered Code") an 24270866Simp * irrevocable, perpetual, worldwide license under Intel's copyrights in the 25270866Simp * base code distributed originally by Intel ("Original Intel Code") to copy, 26270866Simp * make derivatives, distribute, use and display any portion of the Covered 27270866Simp * Code in any form, with the right to sublicense such rights; and 28270866Simp * 29270866Simp * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent 30270866Simp * license (with the right to sublicense), under only those claims of Intel 31270866Simp * patents that are infringed by the Original Intel Code, to make, use, sell, 32270866Simp * offer to sell, and import the Covered Code and derivative works thereof 33270866Simp * solely to the minimum extent necessary to exercise the above copyright 34270866Simp * license, and in no event shall the patent license extend to any additions 35270866Simp * to or modifications of the Original Intel Code. No other license or right 36270866Simp * is granted directly or by implication, estoppel or otherwise; 37270866Simp * 38270866Simp * The above copyright and patent license is granted only if the following 39270866Simp * conditions are met: 40270866Simp * 41270866Simp * 3. Conditions 42270866Simp * 43270866Simp * 3.1. Redistribution of Source with Rights to Further Distribute Source. 44270866Simp * Redistribution of source code of any substantial portion of the Covered 45270866Simp * Code or modification with rights to further distribute source must include 46270866Simp * the above Copyright Notice, the above License, this list of Conditions, 47270866Simp * and the following Disclaimer and Export Compliance provision. In addition, 48270866Simp * Licensee must cause all Covered Code to which Licensee contributes to 49270866Simp * contain a file documenting the changes Licensee made to create that Covered 50270866Simp * Code and the date of any change. Licensee must include in that file the 51270866Simp * documentation of any changes made by any predecessor Licensee. Licensee 52270866Simp * must include a prominent statement that the modification is derived, 53270866Simp * directly or indirectly, from Original Intel Code. 54270866Simp * 55270866Simp * 3.2. Redistribution of Source with no Rights to Further Distribute Source. 56270866Simp * Redistribution of source code of any substantial portion of the Covered 57270866Simp * Code or modification without rights to further distribute source must 58270866Simp * include the following Disclaimer and Export Compliance provision in the 59270866Simp * documentation and/or other materials provided with distribution. In 60270866Simp * addition, Licensee may not authorize further sublicense of source of any 61270866Simp * portion of the Covered Code, and must include terms to the effect that the 62270866Simp * license from Licensee to its licensee is limited to the intellectual 63270866Simp * property embodied in the software Licensee provides to its licensee, and 64270866Simp * not to intellectual property embodied in modifications its licensee may 65270866Simp * make. 66270866Simp * 67270866Simp * 3.3. Redistribution of Executable. Redistribution in executable form of any 68270866Simp * substantial portion of the Covered Code or modification must reproduce the 69270866Simp * above Copyright Notice, and the following Disclaimer and Export Compliance 70270866Simp * provision in the documentation and/or other materials provided with the 71270866Simp * distribution. 72270866Simp * 73270866Simp * 3.4. Intel retains all right, title, and interest in and to the Original 74270866Simp * Intel Code. 75270866Simp * 76270866Simp * 3.5. Neither the name Intel nor any other trademark owned or controlled by 77270866Simp * Intel shall be used in advertising or otherwise to promote the sale, use or 78270866Simp * other dealings in products derived from or relating to the Covered Code 79270866Simp * without prior written authorization from Intel. 80270866Simp * 81270866Simp * 4. Disclaimer and Export Compliance 82270866Simp * 83270866Simp * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED 84270866Simp * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE 85270866Simp * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE, 86270866Simp * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY 87270866Simp * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY 88270866Simp * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A 89270866Simp * PARTICULAR PURPOSE. 90270866Simp * 91270866Simp * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES 92270866Simp * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR 93270866Simp * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT, 94270866Simp * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY 95270866Simp * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL 96270866Simp * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS 97270866Simp * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY 98270866Simp * LIMITED REMEDY. 99270866Simp * 100270866Simp * 4.3. Licensee shall not export, either directly or indirectly, any of this 101270866Simp * software or system incorporating such software without first obtaining any 102270866Simp * required license or other approval from the U. S. Department of Commerce or 103270866Simp * any other agency or department of the United States Government. In the 104270866Simp * event Licensee exports any such software from the United States or 105270866Simp * re-exports any such software from a foreign destination, Licensee shall 106270866Simp * ensure that the distribution and export/re-export of the software is in 107270866Simp * compliance with all laws, regulations, orders, or other restrictions of the 108270866Simp * U.S. Export Administration Regulations. Licensee agrees that neither it nor 109270866Simp * any of its subsidiaries will export/re-export any technical data, process, 110270866Simp * software, or service, directly or indirectly, to any country for which the 111270866Simp * United States government or any agency thereof requires an export license, 112270866Simp * other governmental approval, or letter of assurance, without first obtaining 113270866Simp * such license, approval or letter. 114270866Simp * 115270866Simp *****************************************************************************/ 116270866Simp 117270866Simp#define __HWVALID_C__ 118270866Simp 119270866Simp#include "acpi.h" 120270866Simp#include "accommon.h" 121270866Simp 122270866Simp#define _COMPONENT ACPI_HARDWARE 123270866Simp ACPI_MODULE_NAME ("hwvalid") 124270866Simp 125270866Simp/* Local prototypes */ 126270866Simp 127270866Simpstatic ACPI_STATUS 128270866SimpAcpiHwValidateIoRequest ( 129270866Simp ACPI_IO_ADDRESS Address, 130270866Simp UINT32 BitWidth); 131270866Simp 132270866Simp 133270866Simp/* 134270866Simp * Protected I/O ports. Some ports are always illegal, and some are 135270866Simp * conditionally illegal. This table must remain ordered by port address. 136270866Simp * 137270866Simp * The table is used to implement the Microsoft port access rules that 138270866Simp * first appeared in Windows XP. Some ports are always illegal, and some 139270866Simp * ports are only illegal if the BIOS calls _OSI with a WinXP string or 140270866Simp * later (meaning that the BIOS itelf is post-XP.) 141270866Simp * 142270866Simp * This provides ACPICA with the desired port protections and 143270866Simp * Microsoft compatibility. 144270866Simp * 145270866Simp * Description of port entries: 146270866Simp * DMA: DMA controller 147270866Simp * PIC0: Programmable Interrupt Controller (8259A) 148270866Simp * PIT1: System Timer 1 149270866Simp * PIT2: System Timer 2 failsafe 150270866Simp * RTC: Real-time clock 151270866Simp * CMOS: Extended CMOS 152270866Simp * DMA1: DMA 1 page registers 153270866Simp * DMA1L: DMA 1 Ch 0 low page 154270866Simp * DMA2: DMA 2 page registers 155270866Simp * DMA2L: DMA 2 low page refresh 156270866Simp * ARBC: Arbitration control 157270866Simp * SETUP: Reserved system board setup 158270866Simp * POS: POS channel select 159270866Simp * PIC1: Cascaded PIC 160270866Simp * IDMA: ISA DMA 161270866Simp * ELCR: PIC edge/level registers 162270866Simp * PCI: PCI configuration space 163270866Simp */ 164270866Simpstatic const ACPI_PORT_INFO AcpiProtectedPorts[] = 165270866Simp{ 166270866Simp {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, 167270866Simp {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, 168270866Simp {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, 169270866Simp {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, 170270866Simp {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, 171270866Simp {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, 172270866Simp {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, 173270866Simp {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, 174270866Simp {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP}, 175270866Simp {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, 176270866Simp {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, 177270866Simp {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, 178270866Simp {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, 179270866Simp {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, 180270866Simp {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, 181270866Simp {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, 182270866Simp {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP} 183270866Simp}; 184270866Simp 185270866Simp#define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (AcpiProtectedPorts) 186270866Simp 187270866Simp 188270866Simp/****************************************************************************** 189270866Simp * 190270866Simp * FUNCTION: AcpiHwValidateIoRequest 191270866Simp * 192270866Simp * PARAMETERS: Address Address of I/O port/register 193270866Simp * BitWidth Number of bits (8,16,32) 194270866Simp * 195270866Simp * RETURN: Status 196270866Simp * 197270866Simp * DESCRIPTION: Validates an I/O request (address/length). Certain ports are 198270866Simp * always illegal and some ports are only illegal depending on 199270866Simp * the requests the BIOS AML code makes to the predefined 200270866Simp * _OSI method. 201270866Simp * 202270866Simp ******************************************************************************/ 203270866Simp 204270866Simpstatic ACPI_STATUS 205270866SimpAcpiHwValidateIoRequest ( 206270866Simp ACPI_IO_ADDRESS Address, 207270866Simp UINT32 BitWidth) 208270866Simp{ 209270866Simp UINT32 i; 210270866Simp UINT32 ByteWidth; 211270866Simp ACPI_IO_ADDRESS LastAddress; 212270866Simp const ACPI_PORT_INFO *PortInfo; 213270866Simp 214270866Simp 215270866Simp ACPI_FUNCTION_TRACE (HwValidateIoRequest); 216270866Simp 217270866Simp 218270866Simp /* Supported widths are 8/16/32 */ 219270866Simp 220270866Simp if ((BitWidth != 8) && 221270866Simp (BitWidth != 16) && 222270866Simp (BitWidth != 32)) 223270866Simp { 224270866Simp return (AE_BAD_PARAMETER); 225270866Simp } 226270866Simp 227270866Simp PortInfo = AcpiProtectedPorts; 228270866Simp ByteWidth = ACPI_DIV_8 (BitWidth); 229270866Simp LastAddress = Address + ByteWidth - 1; 230270866Simp 231270866Simp ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %p LastAddress %p Length %X", 232270866Simp ACPI_CAST_PTR (void, Address), ACPI_CAST_PTR (void, LastAddress), 233270866Simp ByteWidth)); 234270866Simp 235270866Simp /* Maximum 16-bit address in I/O space */ 236270866Simp 237270866Simp if (LastAddress > ACPI_UINT16_MAX) 238270866Simp { 239270866Simp ACPI_ERROR ((AE_INFO, 240270866Simp "Illegal I/O port address/length above 64K: 0x%p/%X", 241270866Simp ACPI_CAST_PTR (void, Address), ByteWidth)); 242270866Simp return_ACPI_STATUS (AE_LIMIT); 243270866Simp } 244270866Simp 245270866Simp /* Exit if requested address is not within the protected port table */ 246270866Simp 247270866Simp if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End) 248270866Simp { 249270866Simp return_ACPI_STATUS (AE_OK); 250270866Simp } 251270866Simp 252270866Simp /* Check request against the list of protected I/O ports */ 253270866Simp 254270866Simp for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++) 255270866Simp { 256270866Simp /* 257270866Simp * Check if the requested address range will write to a reserved 258270866Simp * port. Four cases to consider: 259270866Simp * 260270866Simp * 1) Address range is contained completely in the port address range 261270866Simp * 2) Address range overlaps port range at the port range start 262270866Simp * 3) Address range overlaps port range at the port range end 263270866Simp * 4) Address range completely encompasses the port range 264270866Simp */ 265270866Simp if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start)) 266270866Simp { 267270866Simp /* Port illegality may depend on the _OSI calls made by the BIOS */ 268270866Simp 269270866Simp if (AcpiGbl_OsiData >= PortInfo->OsiDependency) 270270866Simp { 271270866Simp ACPI_DEBUG_PRINT ((ACPI_DB_IO, 272270866Simp "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", 273270866Simp ACPI_CAST_PTR (void, Address), ByteWidth, PortInfo->Name, 274270866Simp PortInfo->Start, PortInfo->End)); 275270866Simp 276270866Simp return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS); 277270866Simp } 278270866Simp } 279270866Simp 280270866Simp /* Finished if address range ends before the end of this port */ 281270866Simp 282270866Simp if (LastAddress <= PortInfo->End) 283270866Simp { 284270866Simp break; 285270866Simp } 286270866Simp } 287270866Simp 288270866Simp return_ACPI_STATUS (AE_OK); 289270866Simp} 290270866Simp 291270866Simp 292270866Simp/****************************************************************************** 293270866Simp * 294270866Simp * FUNCTION: AcpiHwReadPort 295270866Simp * 296270866Simp * PARAMETERS: Address Address of I/O port/register to read 297270866Simp * Value Where value is placed 298270866Simp * Width Number of bits 299270866Simp * 300270866Simp * RETURN: Status and value read from port 301270866Simp * 302270866Simp * DESCRIPTION: Read data from an I/O port or register. This is a front-end 303270866Simp * to AcpiOsReadPort that performs validation on both the port 304270866Simp * address and the length. 305270866Simp * 306270866Simp *****************************************************************************/ 307270866Simp 308270866SimpACPI_STATUS 309270866SimpAcpiHwReadPort ( 310270866Simp ACPI_IO_ADDRESS Address, 311270866Simp UINT32 *Value, 312270866Simp UINT32 Width) 313270866Simp{ 314270866Simp ACPI_STATUS Status; 315270866Simp UINT32 OneByte; 316270866Simp UINT32 i; 317270866Simp 318270866Simp 319270866Simp /* Validate the entire request and perform the I/O */ 320270866Simp 321270866Simp Status = AcpiHwValidateIoRequest (Address, Width); 322270866Simp if (ACPI_SUCCESS (Status)) 323270866Simp { 324270866Simp Status = AcpiOsReadPort (Address, Value, Width); 325270866Simp return (Status); 326270866Simp } 327270866Simp 328270866Simp if (Status != AE_AML_ILLEGAL_ADDRESS) 329270866Simp { 330270866Simp return (Status); 331270866Simp } 332270866Simp 333270866Simp /* 334270866Simp * There has been a protection violation within the request. Fall 335270866Simp * back to byte granularity port I/O and ignore the failing bytes. 336270866Simp * This provides Windows compatibility. 337270866Simp */ 338270866Simp for (i = 0, *Value = 0; i < Width; i += 8) 339270866Simp { 340270866Simp /* Validate and read one byte */ 341270866Simp 342270866Simp if (AcpiHwValidateIoRequest (Address, 8) == AE_OK) 343270866Simp { 344270866Simp Status = AcpiOsReadPort (Address, &OneByte, 8); 345270866Simp if (ACPI_FAILURE (Status)) 346270866Simp { 347270866Simp return (Status); 348270866Simp } 349270866Simp 350270866Simp *Value |= (OneByte << i); 351270866Simp } 352270866Simp 353270866Simp Address++; 354270866Simp } 355270866Simp 356270866Simp return (AE_OK); 357270866Simp} 358270866Simp 359270866Simp 360270866Simp/****************************************************************************** 361270866Simp * 362270866Simp * FUNCTION: AcpiHwWritePort 363270866Simp * 364270866Simp * PARAMETERS: Address Address of I/O port/register to write 365270866Simp * Value Value to write 366270866Simp * Width Number of bits 367270866Simp * 368270866Simp * RETURN: Status 369270866Simp * 370270866Simp * DESCRIPTION: Write data to an I/O port or register. This is a front-end 371270866Simp * to AcpiOsWritePort that performs validation on both the port 372270866Simp * address and the length. 373270866Simp * 374270866Simp *****************************************************************************/ 375270866Simp 376270866SimpACPI_STATUS 377270866SimpAcpiHwWritePort ( 378270866Simp ACPI_IO_ADDRESS Address, 379270866Simp UINT32 Value, 380270866Simp UINT32 Width) 381270866Simp{ 382270866Simp ACPI_STATUS Status; 383270866Simp UINT32 i; 384270866Simp 385270866Simp 386270866Simp /* Validate the entire request and perform the I/O */ 387270866Simp 388270866Simp Status = AcpiHwValidateIoRequest (Address, Width); 389270866Simp if (ACPI_SUCCESS (Status)) 390270866Simp { 391270866Simp Status = AcpiOsWritePort (Address, Value, Width); 392270866Simp return (Status); 393270866Simp } 394270866Simp 395270866Simp if (Status != AE_AML_ILLEGAL_ADDRESS) 396270866Simp { 397270866Simp return (Status); 398270866Simp } 399270866Simp 400270866Simp /* 401270866Simp * There has been a protection violation within the request. Fall 402270866Simp * back to byte granularity port I/O and ignore the failing bytes. 403270866Simp * This provides Windows compatibility. 404270866Simp */ 405270866Simp for (i = 0; i < Width; i += 8) 406270866Simp { 407270866Simp /* Validate and write one byte */ 408270866Simp 409270866Simp if (AcpiHwValidateIoRequest (Address, 8) == AE_OK) 410270866Simp { 411270866Simp Status = AcpiOsWritePort (Address, (Value >> i) & 0xFF, 8); 412270866Simp if (ACPI_FAILURE (Status)) 413270866Simp { 414270866Simp return (Status); 415270866Simp } 416270866Simp } 417270866Simp 418270866Simp Address++; 419270866Simp } 420270866Simp 421270866Simp return (AE_OK); 422270866Simp} 423270866Simp 424270866Simp 425270866Simp