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