diff options
author | Bob Moore <robert.moore@intel.com> | 2009-03-18 21:37:47 -0400 |
---|---|---|
committer | Len Brown <len.brown@intel.com> | 2009-03-27 12:11:03 -0400 |
commit | 7f0719039085cc40114abce84cf29fe57da226f4 (patch) | |
tree | 8e210cd936bfb11fdc122b44d79100660b8ffb6a /drivers/acpi/acpica | |
parent | 20869dcfde204e1c21b642608d708d82472fee2b (diff) |
ACPICA: New: I/O port protection
Protect certain I/O ports from reads/writes. Provides MS
compatibility. New module, hwvalid.c
Signed-off-by: Bob Moore <robert.moore@intel.com>
Signed-off-by: Lin Ming <ming.m.lin@intel.com>
Signed-off-by: Len Brown <len.brown@intel.com>
Diffstat (limited to 'drivers/acpi/acpica')
-rw-r--r-- | drivers/acpi/acpica/Makefile | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/acglobal.h | 1 | ||||
-rw-r--r-- | drivers/acpi/acpica/achware.h | 7 | ||||
-rw-r--r-- | drivers/acpi/acpica/aclocal.h | 24 | ||||
-rw-r--r-- | drivers/acpi/acpica/exregion.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwacpi.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwregs.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwsleep.c | 2 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwvalid.c | 240 | ||||
-rw-r--r-- | drivers/acpi/acpica/hwxface.c | 4 | ||||
-rw-r--r-- | drivers/acpi/acpica/uteval.c | 55 | ||||
-rw-r--r-- | drivers/acpi/acpica/utglobal.c | 1 |
12 files changed, 319 insertions, 29 deletions
diff --git a/drivers/acpi/acpica/Makefile b/drivers/acpi/acpica/Makefile index 290be74b774d..17e50824a6f1 100644 --- a/drivers/acpi/acpica/Makefile +++ b/drivers/acpi/acpica/Makefile | |||
@@ -18,7 +18,7 @@ obj-y += exconfig.o exfield.o exnames.o exoparg6.o exresolv.o exstorob.o\ | |||
18 | excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ | 18 | excreate.o exmisc.o exoparg2.o exregion.o exstore.o exutils.o \ |
19 | exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o | 19 | exdump.o exmutex.o exoparg3.o exresnte.o exstoren.o |
20 | 20 | ||
21 | obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o | 21 | obj-y += hwacpi.o hwgpe.o hwregs.o hwsleep.o hwxface.o hwvalid.o |
22 | 22 | ||
23 | obj-$(ACPI_FUTURE_USAGE) += hwtimer.o | 23 | obj-$(ACPI_FUTURE_USAGE) += hwtimer.o |
24 | 24 | ||
diff --git a/drivers/acpi/acpica/acglobal.h b/drivers/acpi/acpica/acglobal.h index f431b997d2f8..16e5210ae936 100644 --- a/drivers/acpi/acpica/acglobal.h +++ b/drivers/acpi/acpica/acglobal.h | |||
@@ -252,6 +252,7 @@ ACPI_EXTERN u8 acpi_gbl_step_to_next_call; | |||
252 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; | 252 | ACPI_EXTERN u8 acpi_gbl_acpi_hardware_present; |
253 | ACPI_EXTERN u8 acpi_gbl_events_initialized; | 253 | ACPI_EXTERN u8 acpi_gbl_events_initialized; |
254 | ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; | 254 | ACPI_EXTERN u8 acpi_gbl_system_awake_and_running; |
255 | ACPI_EXTERN u8 acpi_gbl_osi_data; | ||
255 | 256 | ||
256 | #ifndef DEFINE_ACPI_GLOBALS | 257 | #ifndef DEFINE_ACPI_GLOBALS |
257 | 258 | ||
diff --git a/drivers/acpi/acpica/achware.h b/drivers/acpi/acpica/achware.h index 4fa6ee6b1f7c..4afa3d8e0efb 100644 --- a/drivers/acpi/acpica/achware.h +++ b/drivers/acpi/acpica/achware.h | |||
@@ -73,6 +73,13 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value); | |||
73 | acpi_status acpi_hw_clear_acpi_status(void); | 73 | acpi_status acpi_hw_clear_acpi_status(void); |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * hwvalid - Port I/O with validation | ||
77 | */ | ||
78 | acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width); | ||
79 | |||
80 | acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width); | ||
81 | |||
82 | /* | ||
76 | * hwgpe - GPE support | 83 | * hwgpe - GPE support |
77 | */ | 84 | */ |
78 | acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); | 85 | acpi_status acpi_hw_low_disable_gpe(struct acpi_gpe_event_info *gpe_event_info); |
diff --git a/drivers/acpi/acpica/aclocal.h b/drivers/acpi/acpica/aclocal.h index f01e155b2bcc..42ef0cbf70f8 100644 --- a/drivers/acpi/acpica/aclocal.h +++ b/drivers/acpi/acpica/aclocal.h | |||
@@ -863,6 +863,30 @@ struct acpi_bit_register_info { | |||
863 | 863 | ||
864 | #define ACPI_BITPOSITION_ARB_DISABLE 0x00 | 864 | #define ACPI_BITPOSITION_ARB_DISABLE 0x00 |
865 | 865 | ||
866 | /* Structs and definitions for _OSI support and I/O port validation */ | ||
867 | |||
868 | #define ACPI_OSI_WIN_2000 0x01 | ||
869 | #define ACPI_OSI_WIN_XP 0x02 | ||
870 | #define ACPI_OSI_WIN_XP_SP1 0x03 | ||
871 | #define ACPI_OSI_WINSRV_2003 0x04 | ||
872 | #define ACPI_OSI_WIN_XP_SP2 0x05 | ||
873 | #define ACPI_OSI_WINSRV_2003_SP1 0x06 | ||
874 | #define ACPI_OSI_WIN_VISTA 0x07 | ||
875 | |||
876 | #define ACPI_ALWAYS_ILLEGAL 0x00 | ||
877 | |||
878 | struct acpi_interface_info { | ||
879 | char *name; | ||
880 | u8 value; | ||
881 | }; | ||
882 | |||
883 | struct acpi_port_info { | ||
884 | char *name; | ||
885 | u16 start; | ||
886 | u16 end; | ||
887 | u8 osi_dependency; | ||
888 | }; | ||
889 | |||
866 | /***************************************************************************** | 890 | /***************************************************************************** |
867 | * | 891 | * |
868 | * Resource descriptors | 892 | * Resource descriptors |
diff --git a/drivers/acpi/acpica/exregion.c b/drivers/acpi/acpica/exregion.c index 76ec8ff903b8..3a54b737d2da 100644 --- a/drivers/acpi/acpica/exregion.c +++ b/drivers/acpi/acpica/exregion.c | |||
@@ -294,14 +294,14 @@ acpi_ex_system_io_space_handler(u32 function, | |||
294 | switch (function) { | 294 | switch (function) { |
295 | case ACPI_READ: | 295 | case ACPI_READ: |
296 | 296 | ||
297 | status = acpi_os_read_port((acpi_io_address) address, | 297 | status = acpi_hw_read_port((acpi_io_address) address, |
298 | &value32, bit_width); | 298 | &value32, bit_width); |
299 | *value = value32; | 299 | *value = value32; |
300 | break; | 300 | break; |
301 | 301 | ||
302 | case ACPI_WRITE: | 302 | case ACPI_WRITE: |
303 | 303 | ||
304 | status = acpi_os_write_port((acpi_io_address) address, | 304 | status = acpi_hw_write_port((acpi_io_address) address, |
305 | (u32) * value, bit_width); | 305 | (u32) * value, bit_width); |
306 | break; | 306 | break; |
307 | 307 | ||
diff --git a/drivers/acpi/acpica/hwacpi.c b/drivers/acpi/acpica/hwacpi.c index e7949b133365..9af361a191e7 100644 --- a/drivers/acpi/acpica/hwacpi.c +++ b/drivers/acpi/acpica/hwacpi.c | |||
@@ -96,7 +96,7 @@ acpi_status acpi_hw_set_mode(u32 mode) | |||
96 | 96 | ||
97 | /* BIOS should have disabled ALL fixed and GP events */ | 97 | /* BIOS should have disabled ALL fixed and GP events */ |
98 | 98 | ||
99 | status = acpi_os_write_port(acpi_gbl_FADT.smi_command, | 99 | status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, |
100 | (u32) acpi_gbl_FADT.acpi_enable, 8); | 100 | (u32) acpi_gbl_FADT.acpi_enable, 8); |
101 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 101 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
102 | "Attempting to enable ACPI mode\n")); | 102 | "Attempting to enable ACPI mode\n")); |
@@ -108,7 +108,7 @@ acpi_status acpi_hw_set_mode(u32 mode) | |||
108 | * BIOS should clear all fixed status bits and restore fixed event | 108 | * BIOS should clear all fixed status bits and restore fixed event |
109 | * enable bits to default | 109 | * enable bits to default |
110 | */ | 110 | */ |
111 | status = acpi_os_write_port(acpi_gbl_FADT.smi_command, | 111 | status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, |
112 | (u32) acpi_gbl_FADT.acpi_disable, | 112 | (u32) acpi_gbl_FADT.acpi_disable, |
113 | 8); | 113 | 8); |
114 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, | 114 | ACPI_DEBUG_PRINT((ACPI_DB_INFO, |
diff --git a/drivers/acpi/acpica/hwregs.c b/drivers/acpi/acpica/hwregs.c index 611736266f9f..f8ee0a7fd44d 100644 --- a/drivers/acpi/acpica/hwregs.c +++ b/drivers/acpi/acpica/hwregs.c | |||
@@ -222,7 +222,7 @@ acpi_hw_register_read(u32 register_id, u32 * return_value) | |||
222 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ | 222 | case ACPI_REGISTER_SMI_COMMAND_BLOCK: /* 8-bit access */ |
223 | 223 | ||
224 | status = | 224 | status = |
225 | acpi_os_read_port(acpi_gbl_FADT.smi_command, &value, 8); | 225 | acpi_hw_read_port(acpi_gbl_FADT.smi_command, &value, 8); |
226 | break; | 226 | break; |
227 | 227 | ||
228 | default: | 228 | default: |
@@ -356,7 +356,7 @@ acpi_status acpi_hw_register_write(u32 register_id, u32 value) | |||
356 | /* SMI_CMD is currently always in IO space */ | 356 | /* SMI_CMD is currently always in IO space */ |
357 | 357 | ||
358 | status = | 358 | status = |
359 | acpi_os_write_port(acpi_gbl_FADT.smi_command, value, 8); | 359 | acpi_hw_write_port(acpi_gbl_FADT.smi_command, value, 8); |
360 | break; | 360 | break; |
361 | 361 | ||
362 | default: | 362 | default: |
diff --git a/drivers/acpi/acpica/hwsleep.c b/drivers/acpi/acpica/hwsleep.c index 2ea4c59e8838..baa5fc05e124 100644 --- a/drivers/acpi/acpica/hwsleep.c +++ b/drivers/acpi/acpica/hwsleep.c | |||
@@ -430,7 +430,7 @@ acpi_status asmlinkage acpi_enter_sleep_state_s4bios(void) | |||
430 | 430 | ||
431 | ACPI_FLUSH_CPU_CACHE(); | 431 | ACPI_FLUSH_CPU_CACHE(); |
432 | 432 | ||
433 | status = acpi_os_write_port(acpi_gbl_FADT.smi_command, | 433 | status = acpi_hw_write_port(acpi_gbl_FADT.smi_command, |
434 | (u32) acpi_gbl_FADT.S4bios_request, 8); | 434 | (u32) acpi_gbl_FADT.S4bios_request, 8); |
435 | 435 | ||
436 | do { | 436 | do { |
diff --git a/drivers/acpi/acpica/hwvalid.c b/drivers/acpi/acpica/hwvalid.c new file mode 100644 index 000000000000..e0b562fbe7c1 --- /dev/null +++ b/drivers/acpi/acpica/hwvalid.c | |||
@@ -0,0 +1,240 @@ | |||
1 | |||
2 | /****************************************************************************** | ||
3 | * | ||
4 | * Module Name: hwvalid - I/O request validation | ||
5 | * | ||
6 | *****************************************************************************/ | ||
7 | |||
8 | /* | ||
9 | * Copyright (C) 2000 - 2009, Intel Corp. | ||
10 | * All rights reserved. | ||
11 | * | ||
12 | * Redistribution and use in source and binary forms, with or without | ||
13 | * modification, are permitted provided that the following conditions | ||
14 | * are met: | ||
15 | * 1. Redistributions of source code must retain the above copyright | ||
16 | * notice, this list of conditions, and the following disclaimer, | ||
17 | * without modification. | ||
18 | * 2. Redistributions in binary form must reproduce at minimum a disclaimer | ||
19 | * substantially similar to the "NO WARRANTY" disclaimer below | ||
20 | * ("Disclaimer") and any redistribution must be conditioned upon | ||
21 | * including a substantially similar Disclaimer requirement for further | ||
22 | * binary redistribution. | ||
23 | * 3. Neither the names of the above-listed copyright holders nor the names | ||
24 | * of any contributors may be used to endorse or promote products derived | ||
25 | * from this software without specific prior written permission. | ||
26 | * | ||
27 | * Alternatively, this software may be distributed under the terms of the | ||
28 | * GNU General Public License ("GPL") version 2 as published by the Free | ||
29 | * Software Foundation. | ||
30 | * | ||
31 | * NO WARRANTY | ||
32 | * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS | ||
33 | * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT | ||
34 | * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR | ||
35 | * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT | ||
36 | * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL | ||
37 | * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS | ||
38 | * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) | ||
39 | * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, | ||
40 | * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING | ||
41 | * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE | ||
42 | * POSSIBILITY OF SUCH DAMAGES. | ||
43 | */ | ||
44 | |||
45 | #include <acpi/acpi.h> | ||
46 | #include "accommon.h" | ||
47 | |||
48 | #define _COMPONENT ACPI_HARDWARE | ||
49 | ACPI_MODULE_NAME("hwvalid") | ||
50 | |||
51 | /* Local prototypes */ | ||
52 | static acpi_status | ||
53 | acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width); | ||
54 | |||
55 | /* | ||
56 | * Protected I/O ports. Some ports are always illegal, and some are | ||
57 | * conditionally illegal. This table must remain ordered by port address. | ||
58 | * | ||
59 | * The table is used to implement the Microsoft port access rules that | ||
60 | * first appeared in Windows XP. Some ports are always illegal, and some | ||
61 | * ports are only illegal if the BIOS calls _OSI with a win_xP string or | ||
62 | * later (meaning that the BIOS itelf is post-XP.) | ||
63 | * | ||
64 | * This provides ACPICA with the desired port protections and | ||
65 | * Microsoft compatibility. | ||
66 | */ | ||
67 | static const struct acpi_port_info acpi_protected_ports[] = { | ||
68 | {"DMA1", 0x0000, 0x000F, ACPI_OSI_WIN_XP}, | ||
69 | {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL}, | ||
70 | {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP}, | ||
71 | {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP}, | ||
72 | {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP}, | ||
73 | {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP}, | ||
74 | {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP}, | ||
75 | {"DMA1", 0x0087, 0x0087, ACPI_OSI_WIN_XP}, | ||
76 | {"DMA2", 0x0089, 0x0089, ACPI_OSI_WIN_XP}, | ||
77 | {"DMA2", 0x008A, 0x008B, ACPI_OSI_WIN_XP}, | ||
78 | {"DMA2", 0x008F, 0x008F, ACPI_OSI_WIN_XP}, | ||
79 | {"Arb", 0x0090, 0x0091, ACPI_OSI_WIN_XP}, | ||
80 | {"Setup", 0x0093, 0x0094, ACPI_OSI_WIN_XP}, | ||
81 | {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP}, | ||
82 | {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL}, | ||
83 | {"DMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP}, | ||
84 | {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL}, | ||
85 | {"PCI", 0x0CF8, 0x0D00, ACPI_OSI_WIN_XP} | ||
86 | }; | ||
87 | |||
88 | #define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports) | ||
89 | |||
90 | /****************************************************************************** | ||
91 | * | ||
92 | * FUNCTION: acpi_hw_validate_io_request | ||
93 | * | ||
94 | * PARAMETERS: Address Address of I/O port/register | ||
95 | * bit_width Number of bits (8,16,32) | ||
96 | * | ||
97 | * RETURN: Status | ||
98 | * | ||
99 | * DESCRIPTION: Validates an I/O request (address/length). Certain ports are | ||
100 | * always illegal and some ports are only illegal depending on | ||
101 | * the requests the BIOS AML code makes to the predefined | ||
102 | * _OSI method. | ||
103 | * | ||
104 | ******************************************************************************/ | ||
105 | |||
106 | static acpi_status | ||
107 | acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width) | ||
108 | { | ||
109 | u32 i; | ||
110 | u32 byte_width; | ||
111 | acpi_io_address last_address; | ||
112 | const struct acpi_port_info *port_info; | ||
113 | |||
114 | ACPI_FUNCTION_TRACE(hw_validate_io_request); | ||
115 | |||
116 | /* Supported widths are 8/16/32 */ | ||
117 | |||
118 | if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) { | ||
119 | return AE_BAD_PARAMETER; | ||
120 | } | ||
121 | |||
122 | port_info = acpi_protected_ports; | ||
123 | byte_width = ACPI_DIV_8(bit_width); | ||
124 | last_address = address + byte_width - 1; | ||
125 | |||
126 | ACPI_DEBUG_PRINT((ACPI_DB_IO, "Address %p LastAddress %p Length %X", | ||
127 | ACPI_CAST_PTR(void, address), ACPI_CAST_PTR(void, | ||
128 | last_address), | ||
129 | byte_width)); | ||
130 | |||
131 | /* Maximum 16-bit address in I/O space */ | ||
132 | |||
133 | if (last_address > ACPI_UINT16_MAX) { | ||
134 | ACPI_ERROR((AE_INFO, | ||
135 | "Illegal I/O port address/length above 64K: 0x%p/%X", | ||
136 | ACPI_CAST_PTR(void, address), byte_width)); | ||
137 | return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); | ||
138 | } | ||
139 | |||
140 | /* Exit if requested address is not within the protected port table */ | ||
141 | |||
142 | if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) { | ||
143 | return_ACPI_STATUS(AE_OK); | ||
144 | } | ||
145 | |||
146 | /* Check request against the list of protected I/O ports */ | ||
147 | |||
148 | for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) { | ||
149 | /* | ||
150 | * Check if the requested address range will write to a reserved | ||
151 | * port. Four cases to consider: | ||
152 | * | ||
153 | * 1) Address range is contained completely in the port address range | ||
154 | * 2) Address range overlaps port range at the port range start | ||
155 | * 3) Address range overlaps port range at the port range end | ||
156 | * 4) Address range completely encompasses the port range | ||
157 | */ | ||
158 | if ((address <= port_info->end) | ||
159 | && (last_address >= port_info->start)) { | ||
160 | |||
161 | /* Port illegality may depend on the _OSI calls made by the BIOS */ | ||
162 | |||
163 | if (acpi_gbl_osi_data >= port_info->osi_dependency) { | ||
164 | ACPI_ERROR((AE_INFO, | ||
165 | "Denied AML access to port 0x%p/%X (%s 0x%.4X-0x%.4X)", | ||
166 | ACPI_CAST_PTR(void, address), | ||
167 | byte_width, port_info->name, | ||
168 | port_info->start, port_info->end)); | ||
169 | |||
170 | return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS); | ||
171 | } | ||
172 | } | ||
173 | |||
174 | /* Finished if address range ends before the end of this port */ | ||
175 | |||
176 | if (last_address <= port_info->end) { | ||
177 | break; | ||
178 | } | ||
179 | } | ||
180 | |||
181 | return_ACPI_STATUS(AE_OK); | ||
182 | } | ||
183 | |||
184 | /****************************************************************************** | ||
185 | * | ||
186 | * FUNCTION: acpi_hw_read_port | ||
187 | * | ||
188 | * PARAMETERS: Address Address of I/O port/register to read | ||
189 | * Value Where value is placed | ||
190 | * Width Number of bits | ||
191 | * | ||
192 | * RETURN: Value read from port | ||
193 | * | ||
194 | * DESCRIPTION: Read data from an I/O port or register. This is a front-end | ||
195 | * to acpi_os_read_port that performs validation on both the port | ||
196 | * address and the length. | ||
197 | * | ||
198 | *****************************************************************************/ | ||
199 | |||
200 | acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width) | ||
201 | { | ||
202 | acpi_status status; | ||
203 | |||
204 | status = acpi_hw_validate_io_request(address, width); | ||
205 | if (ACPI_FAILURE(status)) { | ||
206 | return status; | ||
207 | } | ||
208 | |||
209 | status = acpi_os_read_port(address, value, width); | ||
210 | return status; | ||
211 | } | ||
212 | |||
213 | /****************************************************************************** | ||
214 | * | ||
215 | * FUNCTION: acpi_hw_write_port | ||
216 | * | ||
217 | * PARAMETERS: Address Address of I/O port/register to write | ||
218 | * Value Value to write | ||
219 | * Width Number of bits | ||
220 | * | ||
221 | * RETURN: None | ||
222 | * | ||
223 | * DESCRIPTION: Write data to an I/O port or register. This is a front-end | ||
224 | * to acpi_os_write_port that performs validation on both the port | ||
225 | * address and the length. | ||
226 | * | ||
227 | *****************************************************************************/ | ||
228 | |||
229 | acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width) | ||
230 | { | ||
231 | acpi_status status; | ||
232 | |||
233 | status = acpi_hw_validate_io_request(address, width); | ||
234 | if (ACPI_FAILURE(status)) { | ||
235 | return status; | ||
236 | } | ||
237 | |||
238 | status = acpi_os_write_port(address, value, width); | ||
239 | return status; | ||
240 | } | ||
diff --git a/drivers/acpi/acpica/hwxface.c b/drivers/acpi/acpica/hwxface.c index 26e66427f4ff..9829979f2bdd 100644 --- a/drivers/acpi/acpica/hwxface.c +++ b/drivers/acpi/acpica/hwxface.c | |||
@@ -146,7 +146,7 @@ acpi_status acpi_read(u32 *value, struct acpi_generic_address *reg) | |||
146 | case ACPI_ADR_SPACE_SYSTEM_IO: | 146 | case ACPI_ADR_SPACE_SYSTEM_IO: |
147 | 147 | ||
148 | status = | 148 | status = |
149 | acpi_os_read_port((acpi_io_address) address, value, width); | 149 | acpi_hw_read_port((acpi_io_address) address, value, width); |
150 | break; | 150 | break; |
151 | 151 | ||
152 | default: | 152 | default: |
@@ -220,7 +220,7 @@ acpi_status acpi_write(u32 value, struct acpi_generic_address *reg) | |||
220 | 220 | ||
221 | case ACPI_ADR_SPACE_SYSTEM_IO: | 221 | case ACPI_ADR_SPACE_SYSTEM_IO: |
222 | 222 | ||
223 | status = acpi_os_write_port((acpi_io_address) address, value, | 223 | status = acpi_hw_write_port((acpi_io_address) address, value, |
224 | width); | 224 | width); |
225 | break; | 225 | break; |
226 | 226 | ||
diff --git a/drivers/acpi/acpica/uteval.c b/drivers/acpi/acpica/uteval.c index 3b9152579d04..006b16c26017 100644 --- a/drivers/acpi/acpica/uteval.c +++ b/drivers/acpi/acpica/uteval.c | |||
@@ -59,26 +59,35 @@ acpi_ut_translate_one_cid(union acpi_operand_object *obj_desc, | |||
59 | 59 | ||
60 | /* | 60 | /* |
61 | * Strings supported by the _OSI predefined (internal) method. | 61 | * Strings supported by the _OSI predefined (internal) method. |
62 | * | ||
63 | * March 2009: Removed "Linux" as this host no longer wants to respond true | ||
64 | * for this string. Basically, the only safe OS strings are windows-related | ||
65 | * and in many or most cases represent the only test path within the | ||
66 | * BIOS-provided ASL code. | ||
67 | * | ||
68 | * The second element of each entry is used to track the newest version of | ||
69 | * Windows that the BIOS has requested. | ||
62 | */ | 70 | */ |
63 | static char *acpi_interfaces_supported[] = { | 71 | static struct acpi_interface_info acpi_interfaces_supported[] = { |
64 | /* Operating System Vendor Strings */ | 72 | /* Operating System Vendor Strings */ |
65 | 73 | ||
66 | "Windows 2000", /* Windows 2000 */ | 74 | {"Windows 2000", ACPI_OSI_WIN_2000}, /* Windows 2000 */ |
67 | "Windows 2001", /* Windows XP */ | 75 | {"Windows 2001", ACPI_OSI_WIN_XP}, /* Windows XP */ |
68 | "Windows 2001 SP1", /* Windows XP SP1 */ | 76 | {"Windows 2001 SP1", ACPI_OSI_WIN_XP_SP1}, /* Windows XP SP1 */ |
69 | "Windows 2001 SP2", /* Windows XP SP2 */ | 77 | {"Windows 2001.1", ACPI_OSI_WINSRV_2003}, /* Windows Server 2003 */ |
70 | "Windows 2001.1", /* Windows Server 2003 */ | 78 | {"Windows 2001 SP2", ACPI_OSI_WIN_XP_SP2}, /* Windows XP SP2 */ |
71 | "Windows 2001.1 SP1", /* Windows Server 2003 SP1 - Added 03/2006 */ | 79 | {"Windows 2001.1 SP1", ACPI_OSI_WINSRV_2003_SP1}, /* Windows Server 2003 SP1 - Added 03/2006 */ |
72 | "Windows 2006", /* Windows Vista - Added 03/2006 */ | 80 | {"Windows 2006", ACPI_OSI_WIN_VISTA}, /* Windows Vista - Added 03/2006 */ |
73 | 81 | ||
74 | /* Feature Group Strings */ | 82 | /* Feature Group Strings */ |
75 | 83 | ||
76 | "Extended Address Space Descriptor" | 84 | {"Extended Address Space Descriptor", 0} |
77 | /* | 85 | |
78 | * All "optional" feature group strings (features that are implemented | 86 | /* |
79 | * by the host) should be implemented in the host version of | 87 | * All "optional" feature group strings (features that are implemented |
80 | * acpi_os_validate_interface and should not be added here. | 88 | * by the host) should be implemented in the host version of |
81 | */ | 89 | * acpi_os_validate_interface and should not be added here. |
90 | */ | ||
82 | }; | 91 | }; |
83 | 92 | ||
84 | /******************************************************************************* | 93 | /******************************************************************************* |
@@ -125,9 +134,17 @@ acpi_status acpi_ut_osi_implementation(struct acpi_walk_state *walk_state) | |||
125 | 134 | ||
126 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { | 135 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { |
127 | if (!ACPI_STRCMP(string_desc->string.pointer, | 136 | if (!ACPI_STRCMP(string_desc->string.pointer, |
128 | acpi_interfaces_supported[i])) { | 137 | acpi_interfaces_supported[i].name)) { |
129 | 138 | /* | |
130 | /* The interface is supported */ | 139 | * The interface is supported. |
140 | * Update the osi_data if necessary. We keep track of the latest | ||
141 | * version of Windows that has been requested by the BIOS. | ||
142 | */ | ||
143 | if (acpi_interfaces_supported[i].value > | ||
144 | acpi_gbl_osi_data) { | ||
145 | acpi_gbl_osi_data = | ||
146 | acpi_interfaces_supported[i].value; | ||
147 | } | ||
131 | 148 | ||
132 | return_value = ACPI_UINT32_MAX; | 149 | return_value = ACPI_UINT32_MAX; |
133 | goto exit; | 150 | goto exit; |
@@ -176,8 +193,8 @@ acpi_status acpi_osi_invalidate(char *interface) | |||
176 | int i; | 193 | int i; |
177 | 194 | ||
178 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { | 195 | for (i = 0; i < ACPI_ARRAY_LENGTH(acpi_interfaces_supported); i++) { |
179 | if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i])) { | 196 | if (!ACPI_STRCMP(interface, acpi_interfaces_supported[i].name)) { |
180 | *acpi_interfaces_supported[i] = '\0'; | 197 | *acpi_interfaces_supported[i].name = '\0'; |
181 | return AE_OK; | 198 | return AE_OK; |
182 | } | 199 | } |
183 | } | 200 | } |
diff --git a/drivers/acpi/acpica/utglobal.c b/drivers/acpi/acpica/utglobal.c index 256ce7778565..59e46f257c02 100644 --- a/drivers/acpi/acpica/utglobal.c +++ b/drivers/acpi/acpica/utglobal.c | |||
@@ -789,6 +789,7 @@ acpi_status acpi_ut_init_globals(void) | |||
789 | acpi_gbl_trace_dbg_layer = 0; | 789 | acpi_gbl_trace_dbg_layer = 0; |
790 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; | 790 | acpi_gbl_debugger_configuration = DEBUGGER_THREADING; |
791 | acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; | 791 | acpi_gbl_db_output_flags = ACPI_DB_CONSOLE_OUTPUT; |
792 | acpi_gbl_osi_data = 0; | ||
792 | 793 | ||
793 | /* Hardware oriented */ | 794 | /* Hardware oriented */ |
794 | 795 | ||