Print this page
acpica-unix2-20130823
PANKOVs restructure
Split |
Close |
Expand all |
Collapse all |
--- old/usr/src/uts/intel/io/acpica/hardware/hwvalid.c
+++ new/usr/src/common/acpica/components/hardware/hwvalid.c
1 -
2 1 /******************************************************************************
3 2 *
4 3 * Module Name: hwvalid - I/O request validation
5 4 *
6 5 *****************************************************************************/
7 6
8 7 /*
9 - * Copyright (C) 2000 - 2011, Intel Corp.
8 + * Copyright (C) 2000 - 2013, Intel Corp.
10 9 * All rights reserved.
11 10 *
12 11 * Redistribution and use in source and binary forms, with or without
13 12 * modification, are permitted provided that the following conditions
14 13 * are met:
15 14 * 1. Redistributions of source code must retain the above copyright
16 15 * notice, this list of conditions, and the following disclaimer,
17 16 * without modification.
18 17 * 2. Redistributions in binary form must reproduce at minimum a disclaimer
19 18 * substantially similar to the "NO WARRANTY" disclaimer below
20 19 * ("Disclaimer") and any redistribution must be conditioned upon
21 20 * including a substantially similar Disclaimer requirement for further
22 21 * binary redistribution.
23 22 * 3. Neither the names of the above-listed copyright holders nor the names
24 23 * of any contributors may be used to endorse or promote products derived
25 24 * from this software without specific prior written permission.
26 25 *
27 26 * Alternatively, this software may be distributed under the terms of the
28 27 * GNU General Public License ("GPL") version 2 as published by the Free
29 28 * Software Foundation.
30 29 *
31 30 * NO WARRANTY
32 31 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
33 32 * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
34 33 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR
35 34 * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
36 35 * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
37 36 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
38 37 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
39 38 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
40 39 * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
41 40 * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
42 41 * POSSIBILITY OF SUCH DAMAGES.
43 42 */
44 43
45 44 #define __HWVALID_C__
46 45
47 46 #include "acpi.h"
48 47 #include "accommon.h"
49 48
50 49 #define _COMPONENT ACPI_HARDWARE
51 50 ACPI_MODULE_NAME ("hwvalid")
52 51
53 52 /* Local prototypes */
54 53
55 54 static ACPI_STATUS
56 55 AcpiHwValidateIoRequest (
57 56 ACPI_IO_ADDRESS Address,
58 57 UINT32 BitWidth);
59 58
60 59
61 60 /*
62 61 * Protected I/O ports. Some ports are always illegal, and some are
63 62 * conditionally illegal. This table must remain ordered by port address.
64 63 *
65 64 * The table is used to implement the Microsoft port access rules that
66 65 * first appeared in Windows XP. Some ports are always illegal, and some
67 66 * ports are only illegal if the BIOS calls _OSI with a WinXP string or
68 67 * later (meaning that the BIOS itelf is post-XP.)
69 68 *
70 69 * This provides ACPICA with the desired port protections and
71 70 * Microsoft compatibility.
72 71 *
73 72 * Description of port entries:
74 73 * DMA: DMA controller
75 74 * PIC0: Programmable Interrupt Controller (8259A)
76 75 * PIT1: System Timer 1
77 76 * PIT2: System Timer 2 failsafe
78 77 * RTC: Real-time clock
79 78 * CMOS: Extended CMOS
80 79 * DMA1: DMA 1 page registers
81 80 * DMA1L: DMA 1 Ch 0 low page
82 81 * DMA2: DMA 2 page registers
83 82 * DMA2L: DMA 2 low page refresh
84 83 * ARBC: Arbitration control
85 84 * SETUP: Reserved system board setup
86 85 * POS: POS channel select
87 86 * PIC1: Cascaded PIC
88 87 * IDMA: ISA DMA
89 88 * ELCR: PIC edge/level registers
90 89 * PCI: PCI configuration space
91 90 */
92 91 static const ACPI_PORT_INFO AcpiProtectedPorts[] =
93 92 {
94 93 {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP},
95 94 {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
96 95 {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP},
97 96 {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
98 97 {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
99 98 {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
100 99 {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
101 100 {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
102 101 {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
103 102 {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
104 103 {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP},
105 104 {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP},
106 105 {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP},
107 106 {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
108 107 {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
109 108 {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
110 109 {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
111 110 };
112 111
113 112 #define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (AcpiProtectedPorts)
114 113
115 114
116 115 /******************************************************************************
117 116 *
118 117 * FUNCTION: AcpiHwValidateIoRequest
119 118 *
120 119 * PARAMETERS: Address Address of I/O port/register
121 120 * BitWidth Number of bits (8,16,32)
122 121 *
123 122 * RETURN: Status
124 123 *
125 124 * DESCRIPTION: Validates an I/O request (address/length). Certain ports are
126 125 * always illegal and some ports are only illegal depending on
127 126 * the requests the BIOS AML code makes to the predefined
128 127 * _OSI method.
129 128 *
130 129 ******************************************************************************/
131 130
132 131 static ACPI_STATUS
133 132 AcpiHwValidateIoRequest (
134 133 ACPI_IO_ADDRESS Address,
135 134 UINT32 BitWidth)
136 135 {
137 136 UINT32 i;
138 137 UINT32 ByteWidth;
139 138 ACPI_IO_ADDRESS LastAddress;
140 139 const ACPI_PORT_INFO *PortInfo;
141 140
↓ open down ↓ |
122 lines elided |
↑ open up ↑ |
142 141
143 142 ACPI_FUNCTION_TRACE (HwValidateIoRequest);
144 143
145 144
146 145 /* Supported widths are 8/16/32 */
147 146
148 147 if ((BitWidth != 8) &&
149 148 (BitWidth != 16) &&
150 149 (BitWidth != 32))
151 150 {
151 + ACPI_ERROR ((AE_INFO,
152 + "Bad BitWidth parameter: %8.8X", BitWidth));
152 153 return (AE_BAD_PARAMETER);
153 154 }
154 155
155 156 PortInfo = AcpiProtectedPorts;
156 157 ByteWidth = ACPI_DIV_8 (BitWidth);
157 158 LastAddress = Address + ByteWidth - 1;
158 159
159 160 ACPI_DEBUG_PRINT ((ACPI_DB_IO, "Address %p LastAddress %p Length %X",
160 161 ACPI_CAST_PTR (void, Address), ACPI_CAST_PTR (void, LastAddress),
161 162 ByteWidth));
162 163
163 164 /* Maximum 16-bit address in I/O space */
164 165
165 166 if (LastAddress > ACPI_UINT16_MAX)
166 167 {
167 168 ACPI_ERROR ((AE_INFO,
168 169 "Illegal I/O port address/length above 64K: %p/0x%X",
169 170 ACPI_CAST_PTR (void, Address), ByteWidth));
170 171 return_ACPI_STATUS (AE_LIMIT);
171 172 }
172 173
173 174 /* Exit if requested address is not within the protected port table */
174 175
175 176 if (Address > AcpiProtectedPorts[ACPI_PORT_INFO_ENTRIES - 1].End)
176 177 {
177 178 return_ACPI_STATUS (AE_OK);
178 179 }
179 180
180 181 /* Check request against the list of protected I/O ports */
181 182
182 183 for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, PortInfo++)
183 184 {
184 185 /*
185 186 * Check if the requested address range will write to a reserved
186 187 * port. Four cases to consider:
187 188 *
188 189 * 1) Address range is contained completely in the port address range
189 190 * 2) Address range overlaps port range at the port range start
190 191 * 3) Address range overlaps port range at the port range end
191 192 * 4) Address range completely encompasses the port range
192 193 */
193 194 if ((Address <= PortInfo->End) && (LastAddress >= PortInfo->Start))
194 195 {
195 196 /* Port illegality may depend on the _OSI calls made by the BIOS */
196 197
197 198 if (AcpiGbl_OsiData >= PortInfo->OsiDependency)
198 199 {
199 200 ACPI_DEBUG_PRINT ((ACPI_DB_IO,
200 201 "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)",
201 202 ACPI_CAST_PTR (void, Address), ByteWidth, PortInfo->Name,
202 203 PortInfo->Start, PortInfo->End));
203 204
204 205 return_ACPI_STATUS (AE_AML_ILLEGAL_ADDRESS);
205 206 }
206 207 }
207 208
208 209 /* Finished if address range ends before the end of this port */
209 210
210 211 if (LastAddress <= PortInfo->End)
211 212 {
212 213 break;
213 214 }
214 215 }
215 216
216 217 return_ACPI_STATUS (AE_OK);
217 218 }
218 219
219 220
220 221 /******************************************************************************
221 222 *
222 223 * FUNCTION: AcpiHwReadPort
223 224 *
224 225 * PARAMETERS: Address Address of I/O port/register to read
225 226 * Value Where value is placed
226 227 * Width Number of bits
227 228 *
228 229 * RETURN: Status and value read from port
229 230 *
230 231 * DESCRIPTION: Read data from an I/O port or register. This is a front-end
231 232 * to AcpiOsReadPort that performs validation on both the port
232 233 * address and the length.
233 234 *
234 235 *****************************************************************************/
235 236
236 237 ACPI_STATUS
237 238 AcpiHwReadPort (
238 239 ACPI_IO_ADDRESS Address,
239 240 UINT32 *Value,
240 241 UINT32 Width)
241 242 {
242 243 ACPI_STATUS Status;
243 244 UINT32 OneByte;
244 245 UINT32 i;
245 246
246 247
247 248 /* Truncate address to 16 bits if requested */
248 249
249 250 if (AcpiGbl_TruncateIoAddresses)
250 251 {
251 252 Address &= ACPI_UINT16_MAX;
252 253 }
253 254
254 255 /* Validate the entire request and perform the I/O */
255 256
256 257 Status = AcpiHwValidateIoRequest (Address, Width);
257 258 if (ACPI_SUCCESS (Status))
258 259 {
259 260 Status = AcpiOsReadPort (Address, Value, Width);
260 261 return (Status);
261 262 }
262 263
263 264 if (Status != AE_AML_ILLEGAL_ADDRESS)
264 265 {
265 266 return (Status);
266 267 }
267 268
268 269 /*
269 270 * There has been a protection violation within the request. Fall
270 271 * back to byte granularity port I/O and ignore the failing bytes.
271 272 * This provides Windows compatibility.
272 273 */
273 274 for (i = 0, *Value = 0; i < Width; i += 8)
274 275 {
275 276 /* Validate and read one byte */
276 277
277 278 if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
278 279 {
279 280 Status = AcpiOsReadPort (Address, &OneByte, 8);
280 281 if (ACPI_FAILURE (Status))
281 282 {
282 283 return (Status);
283 284 }
284 285
285 286 *Value |= (OneByte << i);
286 287 }
287 288
288 289 Address++;
289 290 }
290 291
291 292 return (AE_OK);
292 293 }
293 294
294 295
295 296 /******************************************************************************
296 297 *
297 298 * FUNCTION: AcpiHwWritePort
298 299 *
299 300 * PARAMETERS: Address Address of I/O port/register to write
300 301 * Value Value to write
301 302 * Width Number of bits
302 303 *
303 304 * RETURN: Status
304 305 *
305 306 * DESCRIPTION: Write data to an I/O port or register. This is a front-end
306 307 * to AcpiOsWritePort that performs validation on both the port
307 308 * address and the length.
308 309 *
309 310 *****************************************************************************/
310 311
311 312 ACPI_STATUS
312 313 AcpiHwWritePort (
313 314 ACPI_IO_ADDRESS Address,
314 315 UINT32 Value,
315 316 UINT32 Width)
316 317 {
317 318 ACPI_STATUS Status;
318 319 UINT32 i;
319 320
320 321
321 322 /* Truncate address to 16 bits if requested */
322 323
323 324 if (AcpiGbl_TruncateIoAddresses)
324 325 {
325 326 Address &= ACPI_UINT16_MAX;
326 327 }
327 328
328 329 /* Validate the entire request and perform the I/O */
329 330
330 331 Status = AcpiHwValidateIoRequest (Address, Width);
331 332 if (ACPI_SUCCESS (Status))
332 333 {
333 334 Status = AcpiOsWritePort (Address, Value, Width);
334 335 return (Status);
335 336 }
336 337
337 338 if (Status != AE_AML_ILLEGAL_ADDRESS)
338 339 {
339 340 return (Status);
340 341 }
341 342
342 343 /*
343 344 * There has been a protection violation within the request. Fall
344 345 * back to byte granularity port I/O and ignore the failing bytes.
345 346 * This provides Windows compatibility.
346 347 */
347 348 for (i = 0; i < Width; i += 8)
348 349 {
349 350 /* Validate and write one byte */
350 351
351 352 if (AcpiHwValidateIoRequest (Address, 8) == AE_OK)
352 353 {
353 354 Status = AcpiOsWritePort (Address, (Value >> i) & 0xFF, 8);
354 355 if (ACPI_FAILURE (Status))
↓ open down ↓ |
193 lines elided |
↑ open up ↑ |
355 356 {
356 357 return (Status);
357 358 }
358 359 }
359 360
360 361 Address++;
361 362 }
362 363
363 364 return (AE_OK);
364 365 }
365 -
366 -
XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX