0001
0002
0003
0004
0005
0006
0007
0008
0009
0010 #include <acpi/acpi.h>
0011 #include "accommon.h"
0012
0013 #define _COMPONENT ACPI_HARDWARE
0014 ACPI_MODULE_NAME("hwvalid")
0015
0016
0017 static acpi_status
0018 acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width);
0019
0020
0021
0022
0023
0024
0025
0026
0027
0028
0029
0030
0031
0032
0033
0034
0035
0036
0037
0038
0039
0040
0041
0042
0043
0044
0045
0046
0047
0048
0049
0050
0051 static const struct acpi_port_info acpi_protected_ports[] = {
0052 {"DMA", 0x0000, 0x000F, ACPI_OSI_WIN_XP},
0053 {"PIC0", 0x0020, 0x0021, ACPI_ALWAYS_ILLEGAL},
0054 {"PIT1", 0x0040, 0x0043, ACPI_OSI_WIN_XP},
0055 {"PIT2", 0x0048, 0x004B, ACPI_OSI_WIN_XP},
0056 {"RTC", 0x0070, 0x0071, ACPI_OSI_WIN_XP},
0057 {"CMOS", 0x0074, 0x0076, ACPI_OSI_WIN_XP},
0058 {"DMA1", 0x0081, 0x0083, ACPI_OSI_WIN_XP},
0059 {"DMA1L", 0x0087, 0x0087, ACPI_OSI_WIN_XP},
0060 {"DMA2", 0x0089, 0x008B, ACPI_OSI_WIN_XP},
0061 {"DMA2L", 0x008F, 0x008F, ACPI_OSI_WIN_XP},
0062 {"ARBC", 0x0090, 0x0091, ACPI_OSI_WIN_XP},
0063 {"SETUP", 0x0093, 0x0094, ACPI_OSI_WIN_XP},
0064 {"POS", 0x0096, 0x0097, ACPI_OSI_WIN_XP},
0065 {"PIC1", 0x00A0, 0x00A1, ACPI_ALWAYS_ILLEGAL},
0066 {"IDMA", 0x00C0, 0x00DF, ACPI_OSI_WIN_XP},
0067 {"ELCR", 0x04D0, 0x04D1, ACPI_ALWAYS_ILLEGAL},
0068 {"PCI", 0x0CF8, 0x0CFF, ACPI_OSI_WIN_XP}
0069 };
0070
0071 #define ACPI_PORT_INFO_ENTRIES ACPI_ARRAY_LENGTH (acpi_protected_ports)
0072
0073
0074
0075
0076
0077
0078
0079
0080
0081
0082
0083
0084
0085
0086
0087
0088
0089 static acpi_status
0090 acpi_hw_validate_io_request(acpi_io_address address, u32 bit_width)
0091 {
0092 u32 i;
0093 u32 byte_width;
0094 acpi_io_address last_address;
0095 const struct acpi_port_info *port_info;
0096
0097 ACPI_FUNCTION_TRACE(hw_validate_io_request);
0098
0099
0100
0101 if ((bit_width != 8) && (bit_width != 16) && (bit_width != 32)) {
0102 ACPI_ERROR((AE_INFO,
0103 "Bad BitWidth parameter: %8.8X", bit_width));
0104 return_ACPI_STATUS(AE_BAD_PARAMETER);
0105 }
0106
0107 port_info = acpi_protected_ports;
0108 byte_width = ACPI_DIV_8(bit_width);
0109 last_address = address + byte_width - 1;
0110
0111 ACPI_DEBUG_PRINT((ACPI_DB_IO,
0112 "Address %8.8X%8.8X LastAddress %8.8X%8.8X Length %X",
0113 ACPI_FORMAT_UINT64(address),
0114 ACPI_FORMAT_UINT64(last_address), byte_width));
0115
0116
0117
0118 if (last_address > ACPI_UINT16_MAX) {
0119 ACPI_ERROR((AE_INFO,
0120 "Illegal I/O port address/length above 64K: %8.8X%8.8X/0x%X",
0121 ACPI_FORMAT_UINT64(address), byte_width));
0122 return_ACPI_STATUS(AE_LIMIT);
0123 }
0124
0125
0126
0127 if (address > acpi_protected_ports[ACPI_PORT_INFO_ENTRIES - 1].end) {
0128 return_ACPI_STATUS(AE_OK);
0129 }
0130
0131
0132
0133 for (i = 0; i < ACPI_PORT_INFO_ENTRIES; i++, port_info++) {
0134
0135
0136
0137
0138
0139
0140
0141
0142
0143 if ((address <= port_info->end)
0144 && (last_address >= port_info->start)) {
0145
0146
0147
0148 if (acpi_gbl_osi_data >= port_info->osi_dependency) {
0149 ACPI_DEBUG_PRINT((ACPI_DB_VALUES,
0150 "Denied AML access to port 0x%8.8X%8.8X/%X (%s 0x%.4X-0x%.4X)\n",
0151 ACPI_FORMAT_UINT64(address),
0152 byte_width, port_info->name,
0153 port_info->start,
0154 port_info->end));
0155
0156 return_ACPI_STATUS(AE_AML_ILLEGAL_ADDRESS);
0157 }
0158 }
0159
0160
0161
0162 if (last_address <= port_info->end) {
0163 break;
0164 }
0165 }
0166
0167 return_ACPI_STATUS(AE_OK);
0168 }
0169
0170
0171
0172
0173
0174
0175
0176
0177
0178
0179
0180
0181
0182
0183
0184
0185
0186 acpi_status acpi_hw_read_port(acpi_io_address address, u32 *value, u32 width)
0187 {
0188 acpi_status status;
0189 u32 one_byte;
0190 u32 i;
0191
0192
0193
0194 if (acpi_gbl_truncate_io_addresses) {
0195 address &= ACPI_UINT16_MAX;
0196 }
0197
0198
0199
0200 status = acpi_hw_validate_io_request(address, width);
0201 if (ACPI_SUCCESS(status)) {
0202 status = acpi_os_read_port(address, value, width);
0203 return (status);
0204 }
0205
0206 if (status != AE_AML_ILLEGAL_ADDRESS) {
0207 return (status);
0208 }
0209
0210
0211
0212
0213
0214
0215 for (i = 0, *value = 0; i < width; i += 8) {
0216
0217
0218
0219 if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
0220 status = acpi_os_read_port(address, &one_byte, 8);
0221 if (ACPI_FAILURE(status)) {
0222 return (status);
0223 }
0224
0225 *value |= (one_byte << i);
0226 }
0227
0228 address++;
0229 }
0230
0231 return (AE_OK);
0232 }
0233
0234
0235
0236
0237
0238
0239
0240
0241
0242
0243
0244
0245
0246
0247
0248
0249
0250 acpi_status acpi_hw_write_port(acpi_io_address address, u32 value, u32 width)
0251 {
0252 acpi_status status;
0253 u32 i;
0254
0255
0256
0257 if (acpi_gbl_truncate_io_addresses) {
0258 address &= ACPI_UINT16_MAX;
0259 }
0260
0261
0262
0263 status = acpi_hw_validate_io_request(address, width);
0264 if (ACPI_SUCCESS(status)) {
0265 status = acpi_os_write_port(address, value, width);
0266 return (status);
0267 }
0268
0269 if (status != AE_AML_ILLEGAL_ADDRESS) {
0270 return (status);
0271 }
0272
0273
0274
0275
0276
0277
0278 for (i = 0; i < width; i += 8) {
0279
0280
0281
0282 if (acpi_hw_validate_io_request(address, 8) == AE_OK) {
0283 status =
0284 acpi_os_write_port(address, (value >> i) & 0xFF, 8);
0285 if (ACPI_FAILURE(status)) {
0286 return (status);
0287 }
0288 }
0289
0290 address++;
0291 }
0292
0293 return (AE_OK);
0294 }
0295
0296
0297
0298
0299
0300
0301
0302
0303
0304
0305
0306
0307
0308
0309
0310 acpi_status acpi_hw_validate_io_block(u64 address, u32 bit_width, u32 count)
0311 {
0312 acpi_status status;
0313
0314 while (count--) {
0315 status = acpi_hw_validate_io_request((acpi_io_address)address,
0316 bit_width);
0317 if (ACPI_FAILURE(status))
0318 return_ACPI_STATUS(status);
0319
0320 address += ACPI_DIV_8(bit_width);
0321 }
0322
0323 return_ACPI_STATUS(AE_OK);
0324 }