Commit | Line | Data |
---|---|---|
95befdb3 BM |
1 | /****************************************************************************** |
2 | * | |
3 | * Module Name: tbfadt - FADT table utilities | |
4 | * | |
5 | *****************************************************************************/ | |
6 | ||
7 | /* | |
c8100dc4 | 8 | * Copyright (C) 2000 - 2016, Intel Corp. |
95befdb3 BM |
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 MERCHANTIBILITY 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/acpi.h> | |
e2f7a777 LB |
45 | #include "accommon.h" |
46 | #include "actables.h" | |
95befdb3 BM |
47 | |
48 | #define _COMPONENT ACPI_TABLES | |
49 | ACPI_MODULE_NAME("tbfadt") | |
50 | ||
51 | /* Local prototypes */ | |
66be71ff | 52 | static void |
ea5d8ebc | 53 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
66be71ff | 54 | u8 space_id, |
21126b29 | 55 | u8 byte_width, |
0dfaaa3d | 56 | u64 address, const char *register_name, u8 flags); |
95befdb3 | 57 | |
71392844 BM |
58 | static void acpi_tb_convert_fadt(void); |
59 | ||
531c633d BM |
60 | static void acpi_tb_setup_fadt_registers(void); |
61 | ||
0249ed24 BM |
62 | static u64 |
63 | acpi_tb_select_address(char *register_name, u32 address32, u64 address64); | |
64 | ||
ea5d8ebc | 65 | /* Table for conversion of FADT to common internal format and FADT validation */ |
95befdb3 | 66 | |
ea5d8ebc | 67 | typedef struct acpi_fadt_info { |
0dfaaa3d | 68 | const char *name; |
ecafe6fa BM |
69 | u16 address64; |
70 | u16 address32; | |
71 | u16 length; | |
4b67a0e4 | 72 | u8 default_length; |
21126b29 | 73 | u8 flags; |
95befdb3 | 74 | |
ea5d8ebc | 75 | } acpi_fadt_info; |
95befdb3 | 76 | |
ecafe6fa | 77 | #define ACPI_FADT_OPTIONAL 0 |
ea5d8ebc BM |
78 | #define ACPI_FADT_REQUIRED 1 |
79 | #define ACPI_FADT_SEPARATE_LENGTH 2 | |
21126b29 | 80 | #define ACPI_FADT_GPE_REGISTER 4 |
ea5d8ebc BM |
81 | |
82 | static struct acpi_fadt_info fadt_info_table[] = { | |
4b67a0e4 | 83 | {"Pm1aEventBlock", |
84 | ACPI_FADT_OFFSET(xpm1a_event_block), | |
95befdb3 | 85 | ACPI_FADT_OFFSET(pm1a_event_block), |
4b67a0e4 | 86 | ACPI_FADT_OFFSET(pm1_event_length), |
87 | ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ | |
88 | ACPI_FADT_REQUIRED}, | |
ea5d8ebc | 89 | |
4b67a0e4 | 90 | {"Pm1bEventBlock", |
91 | ACPI_FADT_OFFSET(xpm1b_event_block), | |
95befdb3 | 92 | ACPI_FADT_OFFSET(pm1b_event_block), |
4b67a0e4 | 93 | ACPI_FADT_OFFSET(pm1_event_length), |
94 | ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ | |
ecafe6fa | 95 | ACPI_FADT_OPTIONAL}, |
ea5d8ebc | 96 | |
4b67a0e4 | 97 | {"Pm1aControlBlock", |
98 | ACPI_FADT_OFFSET(xpm1a_control_block), | |
95befdb3 | 99 | ACPI_FADT_OFFSET(pm1a_control_block), |
4b67a0e4 | 100 | ACPI_FADT_OFFSET(pm1_control_length), |
101 | ACPI_PM1_REGISTER_WIDTH, | |
102 | ACPI_FADT_REQUIRED}, | |
ea5d8ebc | 103 | |
4b67a0e4 | 104 | {"Pm1bControlBlock", |
105 | ACPI_FADT_OFFSET(xpm1b_control_block), | |
95befdb3 | 106 | ACPI_FADT_OFFSET(pm1b_control_block), |
4b67a0e4 | 107 | ACPI_FADT_OFFSET(pm1_control_length), |
108 | ACPI_PM1_REGISTER_WIDTH, | |
ecafe6fa | 109 | ACPI_FADT_OPTIONAL}, |
ea5d8ebc | 110 | |
4b67a0e4 | 111 | {"Pm2ControlBlock", |
112 | ACPI_FADT_OFFSET(xpm2_control_block), | |
95befdb3 | 113 | ACPI_FADT_OFFSET(pm2_control_block), |
4b67a0e4 | 114 | ACPI_FADT_OFFSET(pm2_control_length), |
115 | ACPI_PM2_REGISTER_WIDTH, | |
116 | ACPI_FADT_SEPARATE_LENGTH}, | |
ea5d8ebc | 117 | |
4b67a0e4 | 118 | {"PmTimerBlock", |
119 | ACPI_FADT_OFFSET(xpm_timer_block), | |
ea5d8ebc | 120 | ACPI_FADT_OFFSET(pm_timer_block), |
4b67a0e4 | 121 | ACPI_FADT_OFFSET(pm_timer_length), |
122 | ACPI_PM_TIMER_WIDTH, | |
1d82980c | 123 | ACPI_FADT_SEPARATE_LENGTH}, /* ACPI 5.0A: Timer is optional */ |
ea5d8ebc | 124 | |
4b67a0e4 | 125 | {"Gpe0Block", |
126 | ACPI_FADT_OFFSET(xgpe0_block), | |
ea5d8ebc | 127 | ACPI_FADT_OFFSET(gpe0_block), |
4b67a0e4 | 128 | ACPI_FADT_OFFSET(gpe0_block_length), |
129 | 0, | |
21126b29 | 130 | ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, |
ea5d8ebc | 131 | |
4b67a0e4 | 132 | {"Gpe1Block", |
133 | ACPI_FADT_OFFSET(xgpe1_block), | |
ea5d8ebc | 134 | ACPI_FADT_OFFSET(gpe1_block), |
4b67a0e4 | 135 | ACPI_FADT_OFFSET(gpe1_block_length), |
136 | 0, | |
21126b29 | 137 | ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} |
95befdb3 BM |
138 | }; |
139 | ||
ec41f193 BM |
140 | #define ACPI_FADT_INFO_ENTRIES \ |
141 | (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) | |
95befdb3 | 142 | |
531c633d BM |
143 | /* Table used to split Event Blocks into separate status/enable registers */ |
144 | ||
145 | typedef struct acpi_fadt_pm_info { | |
146 | struct acpi_generic_address *target; | |
ecafe6fa | 147 | u16 source; |
531c633d BM |
148 | u8 register_num; |
149 | ||
150 | } acpi_fadt_pm_info; | |
151 | ||
152 | static struct acpi_fadt_pm_info fadt_pm_info_table[] = { | |
153 | {&acpi_gbl_xpm1a_status, | |
154 | ACPI_FADT_OFFSET(xpm1a_event_block), | |
155 | 0}, | |
156 | ||
157 | {&acpi_gbl_xpm1a_enable, | |
158 | ACPI_FADT_OFFSET(xpm1a_event_block), | |
159 | 1}, | |
160 | ||
161 | {&acpi_gbl_xpm1b_status, | |
162 | ACPI_FADT_OFFSET(xpm1b_event_block), | |
163 | 0}, | |
164 | ||
165 | {&acpi_gbl_xpm1b_enable, | |
166 | ACPI_FADT_OFFSET(xpm1b_event_block), | |
167 | 1} | |
168 | }; | |
169 | ||
ec41f193 BM |
170 | #define ACPI_FADT_PM_INFO_ENTRIES \ |
171 | (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) | |
531c633d | 172 | |
95befdb3 BM |
173 | /******************************************************************************* |
174 | * | |
175 | * FUNCTION: acpi_tb_init_generic_address | |
176 | * | |
ea5d8ebc | 177 | * PARAMETERS: generic_address - GAS struct to be initialized |
75c8044f | 178 | * space_id - ACPI Space ID for this register |
fcea94ba | 179 | * byte_width - Width of this register |
ba494bee | 180 | * address - Address of the register |
0249ed24 | 181 | * register_name - ASCII name of the ACPI register |
95befdb3 BM |
182 | * |
183 | * RETURN: None | |
184 | * | |
ea5d8ebc BM |
185 | * DESCRIPTION: Initialize a Generic Address Structure (GAS) |
186 | * See the ACPI specification for a full description and | |
187 | * definition of this structure. | |
95befdb3 BM |
188 | * |
189 | ******************************************************************************/ | |
190 | ||
66be71ff | 191 | static void |
ea5d8ebc | 192 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
66be71ff | 193 | u8 space_id, |
21126b29 | 194 | u8 byte_width, |
0dfaaa3d | 195 | u64 address, const char *register_name, u8 flags) |
95befdb3 | 196 | { |
66be71ff BM |
197 | u8 bit_width; |
198 | ||
21126b29 BM |
199 | /* |
200 | * Bit width field in the GAS is only one byte long, 255 max. | |
201 | * Check for bit_width overflow in GAS. | |
202 | */ | |
66be71ff | 203 | bit_width = (u8)(byte_width * 8); |
21126b29 BM |
204 | if (byte_width > 31) { /* (31*8)=248, (32*8)=256 */ |
205 | /* | |
206 | * No error for GPE blocks, because we do not use the bit_width | |
207 | * for GPEs, the legacy length (byte_width) is used instead to | |
208 | * allow for a large number of GPEs. | |
209 | */ | |
210 | if (!(flags & ACPI_FADT_GPE_REGISTER)) { | |
211 | ACPI_ERROR((AE_INFO, | |
212 | "%s - 32-bit FADT register is too long (%u bytes, %u bits) " | |
213 | "to convert to GAS struct - 255 bits max, truncating", | |
214 | register_name, byte_width, | |
215 | (byte_width * 8))); | |
216 | } | |
66be71ff BM |
217 | |
218 | bit_width = 255; | |
219 | } | |
95befdb3 | 220 | |
ea5d8ebc BM |
221 | /* |
222 | * The 64-bit Address field is non-aligned in the byte packed | |
223 | * GAS struct. | |
224 | */ | |
225 | ACPI_MOVE_64_TO_64(&generic_address->address, &address); | |
226 | ||
227 | /* All other fields are byte-wide */ | |
228 | ||
06f55419 | 229 | generic_address->space_id = space_id; |
66be71ff | 230 | generic_address->bit_width = bit_width; |
ea5d8ebc | 231 | generic_address->bit_offset = 0; |
06f55419 | 232 | generic_address->access_width = 0; /* Access width ANY */ |
95befdb3 BM |
233 | } |
234 | ||
0249ed24 BM |
235 | /******************************************************************************* |
236 | * | |
237 | * FUNCTION: acpi_tb_select_address | |
238 | * | |
239 | * PARAMETERS: register_name - ASCII name of the ACPI register | |
240 | * address32 - 32-bit address of the register | |
241 | * address64 - 64-bit address of the register | |
242 | * | |
243 | * RETURN: The resolved 64-bit address | |
244 | * | |
245 | * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within | |
246 | * the FADT. Used for the FACS and DSDT addresses. | |
247 | * | |
248 | * NOTES: | |
249 | * | |
250 | * Check for FACS and DSDT address mismatches. An address mismatch between | |
251 | * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and | |
252 | * DSDT/X_DSDT) could be a corrupted address field or it might indicate | |
253 | * the presence of two FACS or two DSDT tables. | |
254 | * | |
255 | * November 2013: | |
256 | * By default, as per the ACPICA specification, a valid 64-bit address is | |
257 | * used regardless of the value of the 32-bit address. However, this | |
258 | * behavior can be overridden via the acpi_gbl_use32_bit_fadt_addresses flag. | |
259 | * | |
260 | ******************************************************************************/ | |
261 | ||
262 | static u64 | |
263 | acpi_tb_select_address(char *register_name, u32 address32, u64 address64) | |
264 | { | |
265 | ||
266 | if (!address64) { | |
267 | ||
268 | /* 64-bit address is zero, use 32-bit address */ | |
269 | ||
270 | return ((u64)address32); | |
271 | } | |
272 | ||
273 | if (address32 && (address64 != (u64)address32)) { | |
274 | ||
275 | /* Address mismatch between 32-bit and 64-bit versions */ | |
276 | ||
277 | ACPI_BIOS_WARNING((AE_INFO, | |
278 | "32/64X %s address mismatch in FADT: " | |
279 | "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", | |
280 | register_name, address32, | |
281 | ACPI_FORMAT_UINT64(address64), | |
282 | acpi_gbl_use32_bit_fadt_addresses ? 32 : | |
283 | 64)); | |
284 | ||
285 | /* 32-bit address override */ | |
286 | ||
287 | if (acpi_gbl_use32_bit_fadt_addresses) { | |
288 | return ((u64)address32); | |
289 | } | |
290 | } | |
291 | ||
292 | /* Default is to use the 64-bit address */ | |
293 | ||
294 | return (address64); | |
295 | } | |
296 | ||
95befdb3 BM |
297 | /******************************************************************************* |
298 | * | |
299 | * FUNCTION: acpi_tb_parse_fadt | |
300 | * | |
62fcce91 | 301 | * PARAMETERS: None |
95befdb3 BM |
302 | * |
303 | * RETURN: None | |
304 | * | |
305 | * DESCRIPTION: Initialize the FADT, DSDT and FACS tables | |
306 | * (FADT contains the addresses of the DSDT and FACS) | |
307 | * | |
308 | ******************************************************************************/ | |
309 | ||
62fcce91 | 310 | void acpi_tb_parse_fadt(void) |
95befdb3 BM |
311 | { |
312 | u32 length; | |
313 | struct acpi_table_header *table; | |
314 | ||
315 | /* | |
ea5d8ebc BM |
316 | * The FADT has multiple versions with different lengths, |
317 | * and it contains pointers to both the DSDT and FACS tables. | |
95befdb3 BM |
318 | * |
319 | * Get a local copy of the FADT and convert it to a common format | |
320 | * Map entire FADT, assumed to be smaller than one page. | |
321 | */ | |
62fcce91 | 322 | length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length; |
95befdb3 BM |
323 | |
324 | table = | |
62fcce91 LZ |
325 | acpi_os_map_memory(acpi_gbl_root_table_list. |
326 | tables[acpi_gbl_fadt_index].address, length); | |
95befdb3 BM |
327 | if (!table) { |
328 | return; | |
329 | } | |
330 | ||
331 | /* | |
332 | * Validate the FADT checksum before we copy the table. Ignore | |
333 | * checksum error as we want to try to get the DSDT and FACS. | |
334 | */ | |
335 | (void)acpi_tb_verify_checksum(table, length); | |
336 | ||
531c633d | 337 | /* Create a local copy of the FADT in common ACPI 2.0+ format */ |
71392844 BM |
338 | |
339 | acpi_tb_create_local_fadt(table, length); | |
340 | ||
341 | /* All done with the real FADT, unmap it */ | |
342 | ||
343 | acpi_os_unmap_memory(table, length); | |
344 | ||
345 | /* Obtain the DSDT and FACS tables via their addresses within the FADT */ | |
346 | ||
f5c1e1c5 | 347 | acpi_tb_install_fixed_table((acpi_physical_address)acpi_gbl_FADT.Xdsdt, |
8ec3f459 | 348 | ACPI_SIG_DSDT, &acpi_gbl_dsdt_index); |
71392844 | 349 | |
22e5b40a BM |
350 | /* If Hardware Reduced flag is set, there is no FACS */ |
351 | ||
352 | if (!acpi_gbl_reduced_hardware) { | |
c04e1fb4 LZ |
353 | if (acpi_gbl_FADT.facs) { |
354 | acpi_tb_install_fixed_table((acpi_physical_address) | |
355 | acpi_gbl_FADT.facs, | |
356 | ACPI_SIG_FACS, | |
8ec3f459 | 357 | &acpi_gbl_facs_index); |
c04e1fb4 LZ |
358 | } |
359 | if (acpi_gbl_FADT.Xfacs) { | |
360 | acpi_tb_install_fixed_table((acpi_physical_address) | |
361 | acpi_gbl_FADT.Xfacs, | |
362 | ACPI_SIG_FACS, | |
8ec3f459 | 363 | &acpi_gbl_xfacs_index); |
c04e1fb4 | 364 | } |
22e5b40a | 365 | } |
71392844 BM |
366 | } |
367 | ||
368 | /******************************************************************************* | |
369 | * | |
370 | * FUNCTION: acpi_tb_create_local_fadt | |
371 | * | |
ba494bee BM |
372 | * PARAMETERS: table - Pointer to BIOS FADT |
373 | * length - Length of the table | |
71392844 BM |
374 | * |
375 | * RETURN: None | |
376 | * | |
377 | * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. | |
378 | * Performs validation on some important FADT fields. | |
379 | * | |
55f8f3cc BM |
380 | * NOTE: We create a local copy of the FADT regardless of the version. |
381 | * | |
71392844 BM |
382 | ******************************************************************************/ |
383 | ||
384 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) | |
385 | { | |
ea5d8ebc | 386 | /* |
55f8f3cc | 387 | * Check if the FADT is larger than the largest table that we expect |
b94cd811 BM |
388 | * (typically the current ACPI specification version). If so, truncate |
389 | * the table, and issue a warning. | |
ea5d8ebc BM |
390 | */ |
391 | if (length > sizeof(struct acpi_table_fadt)) { | |
3b3ea775 | 392 | ACPI_BIOS_WARNING((AE_INFO, |
b94cd811 | 393 | "FADT (revision %u) is longer than %s length, " |
3b3ea775 | 394 | "truncating length %u to %u", |
b94cd811 BM |
395 | table->revision, ACPI_FADT_CONFORMANCE, |
396 | length, | |
3b3ea775 | 397 | (u32)sizeof(struct acpi_table_fadt))); |
ea5d8ebc | 398 | } |
95befdb3 | 399 | |
55f8f3cc | 400 | /* Clear the entire local FADT */ |
95befdb3 | 401 | |
4fa4616e | 402 | memset(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); |
71392844 | 403 | |
55f8f3cc BM |
404 | /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ |
405 | ||
4fa4616e BM |
406 | memcpy(&acpi_gbl_FADT, table, |
407 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); | |
95befdb3 | 408 | |
22e5b40a BM |
409 | /* Take a copy of the Hardware Reduced flag */ |
410 | ||
411 | acpi_gbl_reduced_hardware = FALSE; | |
412 | if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) { | |
413 | acpi_gbl_reduced_hardware = TRUE; | |
414 | } | |
415 | ||
531c633d BM |
416 | /* Convert the local copy of the FADT to the common internal format */ |
417 | ||
95befdb3 | 418 | acpi_tb_convert_fadt(); |
531c633d | 419 | |
531c633d BM |
420 | /* Initialize the global ACPI register structures */ |
421 | ||
422 | acpi_tb_setup_fadt_registers(); | |
95befdb3 BM |
423 | } |
424 | ||
425 | /******************************************************************************* | |
426 | * | |
427 | * FUNCTION: acpi_tb_convert_fadt | |
428 | * | |
0249ed24 | 429 | * PARAMETERS: none - acpi_gbl_FADT is used. |
95befdb3 BM |
430 | * |
431 | * RETURN: None | |
432 | * | |
433 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. | |
0249ed24 BM |
434 | * Expand 32-bit addresses to 64-bit as necessary. Also validate |
435 | * important fields within the FADT. | |
95befdb3 | 436 | * |
0249ed24 BM |
437 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), and must |
438 | * contain a copy of the actual BIOS-provided FADT. | |
95befdb3 | 439 | * |
31fbc073 | 440 | * Notes on 64-bit register addresses: |
95befdb3 | 441 | * |
31fbc073 BM |
442 | * After this FADT conversion, later ACPICA code will only use the 64-bit "X" |
443 | * fields of the FADT for all ACPI register addresses. | |
95befdb3 | 444 | * |
0249ed24 | 445 | * The 64-bit X fields are optional extensions to the original 32-bit FADT |
31fbc073 BM |
446 | * V1.0 fields. Even if they are present in the FADT, they are optional and |
447 | * are unused if the BIOS sets them to zero. Therefore, we must copy/expand | |
0249ed24 BM |
448 | * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is |
449 | * originally zero. | |
95befdb3 | 450 | * |
0249ed24 BM |
451 | * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address |
452 | * fields are expanded to the corresponding 64-bit X fields in the internal | |
453 | * common FADT. | |
31fbc073 BM |
454 | * |
455 | * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded | |
0249ed24 BM |
456 | * to the corresponding 64-bit X fields, if the 64-bit field is originally |
457 | * zero. Adhering to the ACPI specification, we completely ignore the 32-bit | |
458 | * field if the 64-bit field is valid, regardless of whether the host OS is | |
459 | * 32-bit or 64-bit. | |
460 | * | |
461 | * Possible additional checks: | |
462 | * (acpi_gbl_FADT.pm1_event_length >= 4) | |
463 | * (acpi_gbl_FADT.pm1_control_length >= 2) | |
464 | * (acpi_gbl_FADT.pm_timer_length >= 4) | |
465 | * Gpe block lengths must be multiple of 2 | |
95befdb3 BM |
466 | * |
467 | ******************************************************************************/ | |
468 | ||
71392844 | 469 | static void acpi_tb_convert_fadt(void) |
95befdb3 | 470 | { |
0dfaaa3d | 471 | const char *name; |
31fbc073 BM |
472 | struct acpi_generic_address *address64; |
473 | u32 address32; | |
0249ed24 | 474 | u8 length; |
21126b29 | 475 | u8 flags; |
67a119f9 | 476 | u32 i; |
95befdb3 | 477 | |
95befdb3 | 478 | /* |
55f8f3cc BM |
479 | * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which |
480 | * should be zero are indeed zero. This will workaround BIOSs that | |
481 | * inadvertently place values in these fields. | |
482 | * | |
75c8044f LZ |
483 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located |
484 | * at offset 45, 55, 95, and the word located at offset 109, 110. | |
64b3db22 BM |
485 | * |
486 | * Note: The FADT revision value is unreliable. Only the length can be | |
487 | * trusted. | |
55f8f3cc | 488 | */ |
64b3db22 | 489 | if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { |
55f8f3cc BM |
490 | acpi_gbl_FADT.preferred_profile = 0; |
491 | acpi_gbl_FADT.pstate_control = 0; | |
492 | acpi_gbl_FADT.cst_control = 0; | |
493 | acpi_gbl_FADT.boot_flags = 0; | |
494 | } | |
495 | ||
496 | /* | |
0249ed24 BM |
497 | * Now we can update the local FADT length to the length of the |
498 | * current FADT version as defined by the ACPI specification. | |
499 | * Thus, we will have a common FADT internally. | |
95befdb3 | 500 | */ |
0249ed24 | 501 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); |
95befdb3 | 502 | |
06f55419 | 503 | /* |
c04e1fb4 | 504 | * Expand the 32-bit DSDT addresses to 64-bit as necessary. |
0249ed24 | 505 | * Later ACPICA code will always use the X 64-bit field. |
06f55419 | 506 | */ |
0249ed24 BM |
507 | acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT", |
508 | acpi_gbl_FADT.dsdt, | |
509 | acpi_gbl_FADT.Xdsdt); | |
ea5d8ebc | 510 | |
22e5b40a BM |
511 | /* If Hardware Reduced flag is set, we are all done */ |
512 | ||
513 | if (acpi_gbl_reduced_hardware) { | |
514 | return; | |
515 | } | |
516 | ||
06f55419 | 517 | /* Examine all of the 64-bit extended address fields (X fields) */ |
ea5d8ebc | 518 | |
06f55419 BM |
519 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
520 | /* | |
0249ed24 BM |
521 | * Get the 32-bit and 64-bit addresses, as well as the register |
522 | * length and register name. | |
06f55419 | 523 | */ |
0249ed24 BM |
524 | address32 = *ACPI_ADD_PTR(u32, |
525 | &acpi_gbl_FADT, | |
526 | fadt_info_table[i].address32); | |
527 | ||
06f55419 BM |
528 | address64 = ACPI_ADD_PTR(struct acpi_generic_address, |
529 | &acpi_gbl_FADT, | |
4b67a0e4 | 530 | fadt_info_table[i].address64); |
0249ed24 BM |
531 | |
532 | length = *ACPI_ADD_PTR(u8, | |
533 | &acpi_gbl_FADT, | |
534 | fadt_info_table[i].length); | |
535 | ||
06f55419 | 536 | name = fadt_info_table[i].name; |
21126b29 | 537 | flags = fadt_info_table[i].flags; |
06f55419 | 538 | |
0249ed24 BM |
539 | /* |
540 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" | |
541 | * generic address structures as necessary. Later code will always use | |
542 | * the 64-bit address structures. | |
543 | * | |
544 | * November 2013: | |
545 | * Now always use the 64-bit address if it is valid (non-zero), in | |
546 | * accordance with the ACPI specification which states that a 64-bit | |
547 | * address supersedes the 32-bit version. This behavior can be | |
548 | * overridden by the acpi_gbl_use32_bit_fadt_addresses flag. | |
549 | * | |
550 | * During 64-bit address construction and verification, | |
551 | * these cases are handled: | |
552 | * | |
553 | * Address32 zero, Address64 [don't care] - Use Address64 | |
554 | * | |
555 | * Address32 non-zero, Address64 zero - Copy/use Address32 | |
556 | * Address32 non-zero == Address64 non-zero - Use Address64 | |
557 | * Address32 non-zero != Address64 non-zero - Warning, use Address64 | |
558 | * | |
559 | * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and: | |
560 | * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 | |
561 | * | |
562 | * Note: space_id is always I/O for 32-bit legacy address fields | |
563 | */ | |
564 | if (address32) { | |
565 | if (!address64->address) { | |
566 | ||
567 | /* 64-bit address is zero, use 32-bit address */ | |
568 | ||
569 | acpi_tb_init_generic_address(address64, | |
570 | ACPI_ADR_SPACE_SYSTEM_IO, | |
571 | *ACPI_ADD_PTR(u8, | |
572 | &acpi_gbl_FADT, | |
573 | fadt_info_table | |
574 | [i]. | |
575 | length), | |
576 | (u64)address32, | |
21126b29 | 577 | name, flags); |
0249ed24 BM |
578 | } else if (address64->address != (u64)address32) { |
579 | ||
580 | /* Address mismatch */ | |
581 | ||
582 | ACPI_BIOS_WARNING((AE_INFO, | |
583 | "32/64X address mismatch in FADT/%s: " | |
584 | "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", | |
585 | name, address32, | |
586 | ACPI_FORMAT_UINT64 | |
587 | (address64->address), | |
588 | acpi_gbl_use32_bit_fadt_addresses | |
589 | ? 32 : 64)); | |
590 | ||
591 | if (acpi_gbl_use32_bit_fadt_addresses) { | |
592 | ||
593 | /* 32-bit address override */ | |
594 | ||
595 | acpi_tb_init_generic_address(address64, | |
596 | ACPI_ADR_SPACE_SYSTEM_IO, | |
597 | *ACPI_ADD_PTR | |
598 | (u8, | |
599 | &acpi_gbl_FADT, | |
600 | fadt_info_table | |
601 | [i]. | |
602 | length), | |
603 | (u64) | |
604 | address32, | |
21126b29 BM |
605 | name, |
606 | flags); | |
0249ed24 BM |
607 | } |
608 | } | |
609 | } | |
610 | ||
06f55419 BM |
611 | /* |
612 | * For each extended field, check for length mismatch between the | |
4b67a0e4 | 613 | * legacy length field and the corresponding 64-bit X length field. |
6d1490e2 LC |
614 | * Note: If the legacy length field is > 0xFF bits, ignore this |
615 | * check. (GPE registers can be larger than the 64-bit GAS structure | |
616 | * can accomodate, 0xFF bits). | |
06f55419 | 617 | */ |
aab61b67 | 618 | if (address64->address && |
6d1490e2 | 619 | (ACPI_MUL_8(length) <= ACPI_UINT8_MAX) && |
aab61b67 | 620 | (address64->bit_width != ACPI_MUL_8(length))) { |
3b3ea775 BM |
621 | ACPI_BIOS_WARNING((AE_INFO, |
622 | "32/64X length mismatch in FADT/%s: %u/%u", | |
623 | name, ACPI_MUL_8(length), | |
624 | address64->bit_width)); | |
06f55419 | 625 | } |
ea5d8ebc | 626 | |
21126b29 | 627 | if (fadt_info_table[i].flags & ACPI_FADT_REQUIRED) { |
ea5d8ebc | 628 | /* |
1d82980c | 629 | * Field is required (Pm1a_event, Pm1a_control). |
ea5d8ebc BM |
630 | * Both the address and length must be non-zero. |
631 | */ | |
632 | if (!address64->address || !length) { | |
3b3ea775 BM |
633 | ACPI_BIOS_ERROR((AE_INFO, |
634 | "Required FADT field %s has zero address and/or length: " | |
635 | "0x%8.8X%8.8X/0x%X", | |
636 | name, | |
637 | ACPI_FORMAT_UINT64(address64-> | |
638 | address), | |
639 | length)); | |
ea5d8ebc | 640 | } |
21126b29 | 641 | } else if (fadt_info_table[i].flags & ACPI_FADT_SEPARATE_LENGTH) { |
ea5d8ebc | 642 | /* |
ba494bee | 643 | * Field is optional (Pm2_control, GPE0, GPE1) AND has its own |
ec41f193 BM |
644 | * length field. If present, both the address and length must |
645 | * be valid. | |
ea5d8ebc | 646 | */ |
ec41f193 BM |
647 | if ((address64->address && !length) || |
648 | (!address64->address && length)) { | |
3b3ea775 | 649 | ACPI_BIOS_WARNING((AE_INFO, |
b94cd811 BM |
650 | "Optional FADT field %s has valid %s but zero %s: " |
651 | "0x%8.8X%8.8X/0x%X", name, | |
652 | (length ? "Length" : | |
653 | "Address"), | |
654 | (length ? "Address" : | |
655 | "Length"), | |
3b3ea775 BM |
656 | ACPI_FORMAT_UINT64 |
657 | (address64->address), | |
658 | length)); | |
ea5d8ebc BM |
659 | } |
660 | } | |
95befdb3 BM |
661 | } |
662 | } | |
531c633d | 663 | |
ec41f193 | 664 | /******************************************************************************* |
531c633d BM |
665 | * |
666 | * FUNCTION: acpi_tb_setup_fadt_registers | |
667 | * | |
668 | * PARAMETERS: None, uses acpi_gbl_FADT. | |
669 | * | |
670 | * RETURN: None | |
671 | * | |
672 | * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, | |
673 | * force FADT register definitions to their default lengths. | |
674 | * | |
675 | ******************************************************************************/ | |
676 | ||
677 | static void acpi_tb_setup_fadt_registers(void) | |
678 | { | |
679 | struct acpi_generic_address *target64; | |
680 | struct acpi_generic_address *source64; | |
681 | u8 pm1_register_byte_width; | |
682 | u32 i; | |
683 | ||
684 | /* | |
685 | * Optionally check all register lengths against the default values and | |
686 | * update them if they are incorrect. | |
687 | */ | |
688 | if (acpi_gbl_use_default_register_widths) { | |
689 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { | |
690 | target64 = | |
691 | ACPI_ADD_PTR(struct acpi_generic_address, | |
692 | &acpi_gbl_FADT, | |
693 | fadt_info_table[i].address64); | |
694 | ||
695 | /* | |
696 | * If a valid register (Address != 0) and the (default_length > 0) | |
697 | * (Not a GPE register), then check the width against the default. | |
698 | */ | |
699 | if ((target64->address) && | |
700 | (fadt_info_table[i].default_length > 0) && | |
701 | (fadt_info_table[i].default_length != | |
702 | target64->bit_width)) { | |
3b3ea775 BM |
703 | ACPI_BIOS_WARNING((AE_INFO, |
704 | "Invalid length for FADT/%s: %u, using default %u", | |
705 | fadt_info_table[i].name, | |
706 | target64->bit_width, | |
707 | fadt_info_table[i]. | |
708 | default_length)); | |
531c633d BM |
709 | |
710 | /* Incorrect size, set width to the default */ | |
711 | ||
712 | target64->bit_width = | |
713 | fadt_info_table[i].default_length; | |
714 | } | |
715 | } | |
716 | } | |
717 | ||
718 | /* | |
719 | * Get the length of the individual PM1 registers (enable and status). | |
720 | * Each register is defined to be (event block length / 2). Extra divide | |
721 | * by 8 converts bits to bytes. | |
722 | */ | |
ec41f193 BM |
723 | pm1_register_byte_width = (u8) |
724 | ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); | |
531c633d BM |
725 | |
726 | /* | |
727 | * Calculate separate GAS structs for the PM1x (A/B) Status and Enable | |
728 | * registers. These addresses do not appear (directly) in the FADT, so it | |
729 | * is useful to pre-calculate them from the PM1 Event Block definitions. | |
730 | * | |
731 | * The PM event blocks are split into two register blocks, first is the | |
732 | * PM Status Register block, followed immediately by the PM Enable | |
733 | * Register block. Each is of length (pm1_event_length/2) | |
734 | * | |
735 | * Note: The PM1A event block is required by the ACPI specification. | |
736 | * However, the PM1B event block is optional and is rarely, if ever, | |
737 | * used. | |
738 | */ | |
739 | ||
740 | for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) { | |
741 | source64 = | |
742 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, | |
743 | fadt_pm_info_table[i].source); | |
744 | ||
5e053e77 LM |
745 | if (source64->address) { |
746 | acpi_tb_init_generic_address(fadt_pm_info_table[i]. | |
747 | target, source64->space_id, | |
748 | pm1_register_byte_width, | |
749 | source64->address + | |
750 | (fadt_pm_info_table[i]. | |
751 | register_num * | |
66be71ff | 752 | pm1_register_byte_width), |
21126b29 | 753 | "PmRegisters", 0); |
5e053e77 | 754 | } |
531c633d BM |
755 | } |
756 | } |