Go to most recent revision | Details | Last modification | View Log | RSS feed
Rev | Author | Line No. | Line |
---|---|---|---|
6595 | serge | 1 | /****************************************************************************** |
2 | * |
||
3 | * Module Name: tbfadt - FADT table utilities |
||
4 | * |
||
5 | *****************************************************************************/ |
||
6 | |||
7 | /* |
||
8 | * Copyright (C) 2000 - 2015, Intel Corp. |
||
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 |
||
45 | #include "accommon.h" |
||
46 | #include "actables.h" |
||
47 | |||
48 | #define _COMPONENT ACPI_TABLES |
||
49 | ACPI_MODULE_NAME("tbfadt") |
||
50 | |||
51 | /* Local prototypes */ |
||
52 | static void |
||
53 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
||
54 | u8 space_id, |
||
55 | u8 byte_width, |
||
56 | u64 address, char *register_name, u8 flags); |
||
57 | |||
58 | static void acpi_tb_convert_fadt(void); |
||
59 | |||
60 | static void acpi_tb_setup_fadt_registers(void); |
||
61 | |||
62 | static u64 |
||
63 | acpi_tb_select_address(char *register_name, u32 address32, u64 address64); |
||
64 | |||
65 | /* Table for conversion of FADT to common internal format and FADT validation */ |
||
66 | |||
67 | typedef struct acpi_fadt_info { |
||
68 | char *name; |
||
69 | u16 address64; |
||
70 | u16 address32; |
||
71 | u16 length; |
||
72 | u8 default_length; |
||
73 | u8 flags; |
||
74 | |||
75 | } acpi_fadt_info; |
||
76 | |||
77 | #define ACPI_FADT_OPTIONAL 0 |
||
78 | #define ACPI_FADT_REQUIRED 1 |
||
79 | #define ACPI_FADT_SEPARATE_LENGTH 2 |
||
80 | #define ACPI_FADT_GPE_REGISTER 4 |
||
81 | |||
82 | static struct acpi_fadt_info fadt_info_table[] = { |
||
83 | {"Pm1aEventBlock", |
||
84 | ACPI_FADT_OFFSET(xpm1a_event_block), |
||
85 | ACPI_FADT_OFFSET(pm1a_event_block), |
||
86 | ACPI_FADT_OFFSET(pm1_event_length), |
||
87 | ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ |
||
88 | ACPI_FADT_REQUIRED}, |
||
89 | |||
90 | {"Pm1bEventBlock", |
||
91 | ACPI_FADT_OFFSET(xpm1b_event_block), |
||
92 | ACPI_FADT_OFFSET(pm1b_event_block), |
||
93 | ACPI_FADT_OFFSET(pm1_event_length), |
||
94 | ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ |
||
95 | ACPI_FADT_OPTIONAL}, |
||
96 | |||
97 | {"Pm1aControlBlock", |
||
98 | ACPI_FADT_OFFSET(xpm1a_control_block), |
||
99 | ACPI_FADT_OFFSET(pm1a_control_block), |
||
100 | ACPI_FADT_OFFSET(pm1_control_length), |
||
101 | ACPI_PM1_REGISTER_WIDTH, |
||
102 | ACPI_FADT_REQUIRED}, |
||
103 | |||
104 | {"Pm1bControlBlock", |
||
105 | ACPI_FADT_OFFSET(xpm1b_control_block), |
||
106 | ACPI_FADT_OFFSET(pm1b_control_block), |
||
107 | ACPI_FADT_OFFSET(pm1_control_length), |
||
108 | ACPI_PM1_REGISTER_WIDTH, |
||
109 | ACPI_FADT_OPTIONAL}, |
||
110 | |||
111 | {"Pm2ControlBlock", |
||
112 | ACPI_FADT_OFFSET(xpm2_control_block), |
||
113 | ACPI_FADT_OFFSET(pm2_control_block), |
||
114 | ACPI_FADT_OFFSET(pm2_control_length), |
||
115 | ACPI_PM2_REGISTER_WIDTH, |
||
116 | ACPI_FADT_SEPARATE_LENGTH}, |
||
117 | |||
118 | {"PmTimerBlock", |
||
119 | ACPI_FADT_OFFSET(xpm_timer_block), |
||
120 | ACPI_FADT_OFFSET(pm_timer_block), |
||
121 | ACPI_FADT_OFFSET(pm_timer_length), |
||
122 | ACPI_PM_TIMER_WIDTH, |
||
123 | ACPI_FADT_SEPARATE_LENGTH}, /* ACPI 5.0A: Timer is optional */ |
||
124 | |||
125 | {"Gpe0Block", |
||
126 | ACPI_FADT_OFFSET(xgpe0_block), |
||
127 | ACPI_FADT_OFFSET(gpe0_block), |
||
128 | ACPI_FADT_OFFSET(gpe0_block_length), |
||
129 | 0, |
||
130 | ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, |
||
131 | |||
132 | {"Gpe1Block", |
||
133 | ACPI_FADT_OFFSET(xgpe1_block), |
||
134 | ACPI_FADT_OFFSET(gpe1_block), |
||
135 | ACPI_FADT_OFFSET(gpe1_block_length), |
||
136 | 0, |
||
137 | ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} |
||
138 | }; |
||
139 | |||
140 | #define ACPI_FADT_INFO_ENTRIES \ |
||
141 | (sizeof (fadt_info_table) / sizeof (struct acpi_fadt_info)) |
||
142 | |||
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; |
||
147 | u16 source; |
||
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 | |||
170 | #define ACPI_FADT_PM_INFO_ENTRIES \ |
||
171 | (sizeof (fadt_pm_info_table) / sizeof (struct acpi_fadt_pm_info)) |
||
172 | |||
173 | /******************************************************************************* |
||
174 | * |
||
175 | * FUNCTION: acpi_tb_init_generic_address |
||
176 | * |
||
177 | * PARAMETERS: generic_address - GAS struct to be initialized |
||
178 | * space_id - ACPI Space ID for this register |
||
179 | * byte_width - Width of this register |
||
180 | * address - Address of the register |
||
181 | * register_name - ASCII name of the ACPI register |
||
182 | * |
||
183 | * RETURN: None |
||
184 | * |
||
185 | * DESCRIPTION: Initialize a Generic Address Structure (GAS) |
||
186 | * See the ACPI specification for a full description and |
||
187 | * definition of this structure. |
||
188 | * |
||
189 | ******************************************************************************/ |
||
190 | |||
191 | static void |
||
192 | acpi_tb_init_generic_address(struct acpi_generic_address *generic_address, |
||
193 | u8 space_id, |
||
194 | u8 byte_width, |
||
195 | u64 address, char *register_name, u8 flags) |
||
196 | { |
||
197 | u8 bit_width; |
||
198 | |||
199 | /* |
||
200 | * Bit width field in the GAS is only one byte long, 255 max. |
||
201 | * Check for bit_width overflow in GAS. |
||
202 | */ |
||
203 | bit_width = (u8)(byte_width * 8); |
||
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 | } |
||
217 | |||
218 | bit_width = 255; |
||
219 | } |
||
220 | |||
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 | |||
229 | generic_address->space_id = space_id; |
||
230 | generic_address->bit_width = bit_width; |
||
231 | generic_address->bit_offset = 0; |
||
232 | generic_address->access_width = 0; /* Access width ANY */ |
||
233 | } |
||
234 | |||
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 | |||
297 | /******************************************************************************* |
||
298 | * |
||
299 | * FUNCTION: acpi_tb_parse_fadt |
||
300 | * |
||
301 | * PARAMETERS: None |
||
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 | |||
310 | void acpi_tb_parse_fadt(void) |
||
311 | { |
||
312 | u32 length; |
||
313 | struct acpi_table_header *table; |
||
314 | |||
315 | /* |
||
316 | * The FADT has multiple versions with different lengths, |
||
317 | * and it contains pointers to both the DSDT and FACS tables. |
||
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 | */ |
||
322 | length = acpi_gbl_root_table_list.tables[acpi_gbl_fadt_index].length; |
||
323 | |||
324 | table = |
||
325 | acpi_os_map_memory(acpi_gbl_root_table_list. |
||
326 | tables[acpi_gbl_fadt_index].address, length); |
||
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 | |||
337 | /* Create a local copy of the FADT in common ACPI 2.0+ format */ |
||
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 | |||
347 | acpi_tb_install_fixed_table((acpi_physical_address) acpi_gbl_FADT.Xdsdt, |
||
348 | ACPI_SIG_DSDT, &acpi_gbl_dsdt_index); |
||
349 | |||
350 | /* If Hardware Reduced flag is set, there is no FACS */ |
||
351 | |||
352 | if (!acpi_gbl_reduced_hardware) { |
||
353 | if (acpi_gbl_FADT.facs) { |
||
354 | acpi_tb_install_fixed_table((acpi_physical_address) |
||
355 | acpi_gbl_FADT.facs, |
||
356 | ACPI_SIG_FACS, |
||
357 | &acpi_gbl_facs_index); |
||
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, |
||
363 | &acpi_gbl_xfacs_index); |
||
364 | } |
||
365 | } |
||
366 | } |
||
367 | |||
368 | /******************************************************************************* |
||
369 | * |
||
370 | * FUNCTION: acpi_tb_create_local_fadt |
||
371 | * |
||
372 | * PARAMETERS: table - Pointer to BIOS FADT |
||
373 | * length - Length of the table |
||
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 | * |
||
380 | * NOTE: We create a local copy of the FADT regardless of the version. |
||
381 | * |
||
382 | ******************************************************************************/ |
||
383 | |||
384 | void acpi_tb_create_local_fadt(struct acpi_table_header *table, u32 length) |
||
385 | { |
||
386 | /* |
||
387 | * Check if the FADT is larger than the largest table that we expect |
||
388 | * (the ACPI 5.0 version). If so, truncate the table, and issue |
||
389 | * a warning. |
||
390 | */ |
||
391 | if (length > sizeof(struct acpi_table_fadt)) { |
||
392 | ACPI_BIOS_WARNING((AE_INFO, |
||
393 | "FADT (revision %u) is longer than ACPI 5.0 version, " |
||
394 | "truncating length %u to %u", |
||
395 | table->revision, length, |
||
396 | (u32)sizeof(struct acpi_table_fadt))); |
||
397 | } |
||
398 | |||
399 | /* Clear the entire local FADT */ |
||
400 | |||
401 | memset(&acpi_gbl_FADT, 0, sizeof(struct acpi_table_fadt)); |
||
402 | |||
403 | /* Copy the original FADT, up to sizeof (struct acpi_table_fadt) */ |
||
404 | |||
405 | memcpy(&acpi_gbl_FADT, table, |
||
406 | ACPI_MIN(length, sizeof(struct acpi_table_fadt))); |
||
407 | |||
408 | /* Take a copy of the Hardware Reduced flag */ |
||
409 | |||
410 | acpi_gbl_reduced_hardware = FALSE; |
||
411 | if (acpi_gbl_FADT.flags & ACPI_FADT_HW_REDUCED) { |
||
412 | acpi_gbl_reduced_hardware = TRUE; |
||
413 | } |
||
414 | |||
415 | /* Convert the local copy of the FADT to the common internal format */ |
||
416 | |||
417 | acpi_tb_convert_fadt(); |
||
418 | |||
419 | /* Initialize the global ACPI register structures */ |
||
420 | |||
421 | acpi_tb_setup_fadt_registers(); |
||
422 | } |
||
423 | |||
424 | /******************************************************************************* |
||
425 | * |
||
426 | * FUNCTION: acpi_tb_convert_fadt |
||
427 | * |
||
428 | * PARAMETERS: none - acpi_gbl_FADT is used. |
||
429 | * |
||
430 | * RETURN: None |
||
431 | * |
||
432 | * DESCRIPTION: Converts all versions of the FADT to a common internal format. |
||
433 | * Expand 32-bit addresses to 64-bit as necessary. Also validate |
||
434 | * important fields within the FADT. |
||
435 | * |
||
436 | * NOTE: acpi_gbl_FADT must be of size (struct acpi_table_fadt), and must |
||
437 | * contain a copy of the actual BIOS-provided FADT. |
||
438 | * |
||
439 | * Notes on 64-bit register addresses: |
||
440 | * |
||
441 | * After this FADT conversion, later ACPICA code will only use the 64-bit "X" |
||
442 | * fields of the FADT for all ACPI register addresses. |
||
443 | * |
||
444 | * The 64-bit X fields are optional extensions to the original 32-bit FADT |
||
445 | * V1.0 fields. Even if they are present in the FADT, they are optional and |
||
446 | * are unused if the BIOS sets them to zero. Therefore, we must copy/expand |
||
447 | * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is |
||
448 | * originally zero. |
||
449 | * |
||
450 | * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address |
||
451 | * fields are expanded to the corresponding 64-bit X fields in the internal |
||
452 | * common FADT. |
||
453 | * |
||
454 | * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded |
||
455 | * to the corresponding 64-bit X fields, if the 64-bit field is originally |
||
456 | * zero. Adhering to the ACPI specification, we completely ignore the 32-bit |
||
457 | * field if the 64-bit field is valid, regardless of whether the host OS is |
||
458 | * 32-bit or 64-bit. |
||
459 | * |
||
460 | * Possible additional checks: |
||
461 | * (acpi_gbl_FADT.pm1_event_length >= 4) |
||
462 | * (acpi_gbl_FADT.pm1_control_length >= 2) |
||
463 | * (acpi_gbl_FADT.pm_timer_length >= 4) |
||
464 | * Gpe block lengths must be multiple of 2 |
||
465 | * |
||
466 | ******************************************************************************/ |
||
467 | |||
468 | static void acpi_tb_convert_fadt(void) |
||
469 | { |
||
470 | char *name; |
||
471 | struct acpi_generic_address *address64; |
||
472 | u32 address32; |
||
473 | u8 length; |
||
474 | u8 flags; |
||
475 | u32 i; |
||
476 | |||
477 | /* |
||
478 | * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which |
||
479 | * should be zero are indeed zero. This will workaround BIOSs that |
||
480 | * inadvertently place values in these fields. |
||
481 | * |
||
482 | * The ACPI 1.0 reserved fields that will be zeroed are the bytes located |
||
483 | * at offset 45, 55, 95, and the word located at offset 109, 110. |
||
484 | * |
||
485 | * Note: The FADT revision value is unreliable. Only the length can be |
||
486 | * trusted. |
||
487 | */ |
||
488 | if (acpi_gbl_FADT.header.length <= ACPI_FADT_V2_SIZE) { |
||
489 | acpi_gbl_FADT.preferred_profile = 0; |
||
490 | acpi_gbl_FADT.pstate_control = 0; |
||
491 | acpi_gbl_FADT.cst_control = 0; |
||
492 | acpi_gbl_FADT.boot_flags = 0; |
||
493 | } |
||
494 | |||
495 | /* |
||
496 | * Now we can update the local FADT length to the length of the |
||
497 | * current FADT version as defined by the ACPI specification. |
||
498 | * Thus, we will have a common FADT internally. |
||
499 | */ |
||
500 | acpi_gbl_FADT.header.length = sizeof(struct acpi_table_fadt); |
||
501 | |||
502 | /* |
||
503 | * Expand the 32-bit DSDT addresses to 64-bit as necessary. |
||
504 | * Later ACPICA code will always use the X 64-bit field. |
||
505 | */ |
||
506 | acpi_gbl_FADT.Xdsdt = acpi_tb_select_address("DSDT", |
||
507 | acpi_gbl_FADT.dsdt, |
||
508 | acpi_gbl_FADT.Xdsdt); |
||
509 | |||
510 | /* If Hardware Reduced flag is set, we are all done */ |
||
511 | |||
512 | if (acpi_gbl_reduced_hardware) { |
||
513 | return; |
||
514 | } |
||
515 | |||
516 | /* Examine all of the 64-bit extended address fields (X fields) */ |
||
517 | |||
518 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
||
519 | /* |
||
520 | * Get the 32-bit and 64-bit addresses, as well as the register |
||
521 | * length and register name. |
||
522 | */ |
||
523 | address32 = *ACPI_ADD_PTR(u32, |
||
524 | &acpi_gbl_FADT, |
||
525 | fadt_info_table[i].address32); |
||
526 | |||
527 | address64 = ACPI_ADD_PTR(struct acpi_generic_address, |
||
528 | &acpi_gbl_FADT, |
||
529 | fadt_info_table[i].address64); |
||
530 | |||
531 | length = *ACPI_ADD_PTR(u8, |
||
532 | &acpi_gbl_FADT, |
||
533 | fadt_info_table[i].length); |
||
534 | |||
535 | name = fadt_info_table[i].name; |
||
536 | flags = fadt_info_table[i].flags; |
||
537 | |||
538 | /* |
||
539 | * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" |
||
540 | * generic address structures as necessary. Later code will always use |
||
541 | * the 64-bit address structures. |
||
542 | * |
||
543 | * November 2013: |
||
544 | * Now always use the 64-bit address if it is valid (non-zero), in |
||
545 | * accordance with the ACPI specification which states that a 64-bit |
||
546 | * address supersedes the 32-bit version. This behavior can be |
||
547 | * overridden by the acpi_gbl_use32_bit_fadt_addresses flag. |
||
548 | * |
||
549 | * During 64-bit address construction and verification, |
||
550 | * these cases are handled: |
||
551 | * |
||
552 | * Address32 zero, Address64 [don't care] - Use Address64 |
||
553 | * |
||
554 | * Address32 non-zero, Address64 zero - Copy/use Address32 |
||
555 | * Address32 non-zero == Address64 non-zero - Use Address64 |
||
556 | * Address32 non-zero != Address64 non-zero - Warning, use Address64 |
||
557 | * |
||
558 | * Override: if acpi_gbl_use32_bit_fadt_addresses is TRUE, and: |
||
559 | * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 |
||
560 | * |
||
561 | * Note: space_id is always I/O for 32-bit legacy address fields |
||
562 | */ |
||
563 | if (address32) { |
||
564 | if (!address64->address) { |
||
565 | |||
566 | /* 64-bit address is zero, use 32-bit address */ |
||
567 | |||
568 | acpi_tb_init_generic_address(address64, |
||
569 | ACPI_ADR_SPACE_SYSTEM_IO, |
||
570 | *ACPI_ADD_PTR(u8, |
||
571 | &acpi_gbl_FADT, |
||
572 | fadt_info_table |
||
573 | [i]. |
||
574 | length), |
||
575 | (u64)address32, |
||
576 | name, flags); |
||
577 | } else if (address64->address != (u64)address32) { |
||
578 | |||
579 | /* Address mismatch */ |
||
580 | |||
581 | ACPI_BIOS_WARNING((AE_INFO, |
||
582 | "32/64X address mismatch in FADT/%s: " |
||
583 | "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", |
||
584 | name, address32, |
||
585 | ACPI_FORMAT_UINT64 |
||
586 | (address64->address), |
||
587 | acpi_gbl_use32_bit_fadt_addresses |
||
588 | ? 32 : 64)); |
||
589 | |||
590 | if (acpi_gbl_use32_bit_fadt_addresses) { |
||
591 | |||
592 | /* 32-bit address override */ |
||
593 | |||
594 | acpi_tb_init_generic_address(address64, |
||
595 | ACPI_ADR_SPACE_SYSTEM_IO, |
||
596 | *ACPI_ADD_PTR |
||
597 | (u8, |
||
598 | &acpi_gbl_FADT, |
||
599 | fadt_info_table |
||
600 | [i]. |
||
601 | length), |
||
602 | (u64) |
||
603 | address32, |
||
604 | name, |
||
605 | flags); |
||
606 | } |
||
607 | } |
||
608 | } |
||
609 | |||
610 | /* |
||
611 | * For each extended field, check for length mismatch between the |
||
612 | * legacy length field and the corresponding 64-bit X length field. |
||
613 | * Note: If the legacy length field is > 0xFF bits, ignore this |
||
614 | * check. (GPE registers can be larger than the 64-bit GAS structure |
||
615 | * can accomodate, 0xFF bits). |
||
616 | */ |
||
617 | if (address64->address && |
||
618 | (ACPI_MUL_8(length) <= ACPI_UINT8_MAX) && |
||
619 | (address64->bit_width != ACPI_MUL_8(length))) { |
||
620 | ACPI_BIOS_WARNING((AE_INFO, |
||
621 | "32/64X length mismatch in FADT/%s: %u/%u", |
||
622 | name, ACPI_MUL_8(length), |
||
623 | address64->bit_width)); |
||
624 | } |
||
625 | |||
626 | if (fadt_info_table[i].flags & ACPI_FADT_REQUIRED) { |
||
627 | /* |
||
628 | * Field is required (Pm1a_event, Pm1a_control). |
||
629 | * Both the address and length must be non-zero. |
||
630 | */ |
||
631 | if (!address64->address || !length) { |
||
632 | ACPI_BIOS_ERROR((AE_INFO, |
||
633 | "Required FADT field %s has zero address and/or length: " |
||
634 | "0x%8.8X%8.8X/0x%X", |
||
635 | name, |
||
636 | ACPI_FORMAT_UINT64(address64-> |
||
637 | address), |
||
638 | length)); |
||
639 | } |
||
640 | } else if (fadt_info_table[i].flags & ACPI_FADT_SEPARATE_LENGTH) { |
||
641 | /* |
||
642 | * Field is optional (Pm2_control, GPE0, GPE1) AND has its own |
||
643 | * length field. If present, both the address and length must |
||
644 | * be valid. |
||
645 | */ |
||
646 | if ((address64->address && !length) || |
||
647 | (!address64->address && length)) { |
||
648 | ACPI_BIOS_WARNING((AE_INFO, |
||
649 | "Optional FADT field %s has zero address or length: " |
||
650 | "0x%8.8X%8.8X/0x%X", |
||
651 | name, |
||
652 | ACPI_FORMAT_UINT64 |
||
653 | (address64->address), |
||
654 | length)); |
||
655 | } |
||
656 | } |
||
657 | } |
||
658 | } |
||
659 | |||
660 | /******************************************************************************* |
||
661 | * |
||
662 | * FUNCTION: acpi_tb_setup_fadt_registers |
||
663 | * |
||
664 | * PARAMETERS: None, uses acpi_gbl_FADT. |
||
665 | * |
||
666 | * RETURN: None |
||
667 | * |
||
668 | * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, |
||
669 | * force FADT register definitions to their default lengths. |
||
670 | * |
||
671 | ******************************************************************************/ |
||
672 | |||
673 | static void acpi_tb_setup_fadt_registers(void) |
||
674 | { |
||
675 | struct acpi_generic_address *target64; |
||
676 | struct acpi_generic_address *source64; |
||
677 | u8 pm1_register_byte_width; |
||
678 | u32 i; |
||
679 | |||
680 | /* |
||
681 | * Optionally check all register lengths against the default values and |
||
682 | * update them if they are incorrect. |
||
683 | */ |
||
684 | if (acpi_gbl_use_default_register_widths) { |
||
685 | for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { |
||
686 | target64 = |
||
687 | ACPI_ADD_PTR(struct acpi_generic_address, |
||
688 | &acpi_gbl_FADT, |
||
689 | fadt_info_table[i].address64); |
||
690 | |||
691 | /* |
||
692 | * If a valid register (Address != 0) and the (default_length > 0) |
||
693 | * (Not a GPE register), then check the width against the default. |
||
694 | */ |
||
695 | if ((target64->address) && |
||
696 | (fadt_info_table[i].default_length > 0) && |
||
697 | (fadt_info_table[i].default_length != |
||
698 | target64->bit_width)) { |
||
699 | ACPI_BIOS_WARNING((AE_INFO, |
||
700 | "Invalid length for FADT/%s: %u, using default %u", |
||
701 | fadt_info_table[i].name, |
||
702 | target64->bit_width, |
||
703 | fadt_info_table[i]. |
||
704 | default_length)); |
||
705 | |||
706 | /* Incorrect size, set width to the default */ |
||
707 | |||
708 | target64->bit_width = |
||
709 | fadt_info_table[i].default_length; |
||
710 | } |
||
711 | } |
||
712 | } |
||
713 | |||
714 | /* |
||
715 | * Get the length of the individual PM1 registers (enable and status). |
||
716 | * Each register is defined to be (event block length / 2). Extra divide |
||
717 | * by 8 converts bits to bytes. |
||
718 | */ |
||
719 | pm1_register_byte_width = (u8) |
||
720 | ACPI_DIV_16(acpi_gbl_FADT.xpm1a_event_block.bit_width); |
||
721 | |||
722 | /* |
||
723 | * Calculate separate GAS structs for the PM1x (A/B) Status and Enable |
||
724 | * registers. These addresses do not appear (directly) in the FADT, so it |
||
725 | * is useful to pre-calculate them from the PM1 Event Block definitions. |
||
726 | * |
||
727 | * The PM event blocks are split into two register blocks, first is the |
||
728 | * PM Status Register block, followed immediately by the PM Enable |
||
729 | * Register block. Each is of length (pm1_event_length/2) |
||
730 | * |
||
731 | * Note: The PM1A event block is required by the ACPI specification. |
||
732 | * However, the PM1B event block is optional and is rarely, if ever, |
||
733 | * used. |
||
734 | */ |
||
735 | |||
736 | for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) { |
||
737 | source64 = |
||
738 | ACPI_ADD_PTR(struct acpi_generic_address, &acpi_gbl_FADT, |
||
739 | fadt_pm_info_table[i].source); |
||
740 | |||
741 | if (source64->address) { |
||
742 | acpi_tb_init_generic_address(fadt_pm_info_table[i]. |
||
743 | target, source64->space_id, |
||
744 | pm1_register_byte_width, |
||
745 | source64->address + |
||
746 | (fadt_pm_info_table[i]. |
||
747 | register_num * |
||
748 | pm1_register_byte_width), |
||
749 | "PmRegisters", 0); |
||
750 | } |
||
751 | } |
||
752 | }>>=>>=> |