1/******************************************************************************
2 *
3 * Module Name: tbfadt   - FADT table utilities
4 *
5 *****************************************************************************/
6
7/******************************************************************************
8 *
9 * 1. Copyright Notice
10 *
11 * Some or all of this work - Copyright (c) 1999 - 2012, Intel Corp.
12 * All rights reserved.
13 *
14 * 2. License
15 *
16 * 2.1. This is your license from Intel Corp. under its intellectual property
17 * rights. You may have additional license terms from the party that provided
18 * you this software, covering your right to use that party's intellectual
19 * property rights.
20 *
21 * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
22 * copy of the source code appearing in this file ("Covered Code") an
23 * irrevocable, perpetual, worldwide license under Intel's copyrights in the
24 * base code distributed originally by Intel ("Original Intel Code") to copy,
25 * make derivatives, distribute, use and display any portion of the Covered
26 * Code in any form, with the right to sublicense such rights; and
27 *
28 * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
29 * license (with the right to sublicense), under only those claims of Intel
30 * patents that are infringed by the Original Intel Code, to make, use, sell,
31 * offer to sell, and import the Covered Code and derivative works thereof
32 * solely to the minimum extent necessary to exercise the above copyright
33 * license, and in no event shall the patent license extend to any additions
34 * to or modifications of the Original Intel Code. No other license or right
35 * is granted directly or by implication, estoppel or otherwise;
36 *
37 * The above copyright and patent license is granted only if the following
38 * conditions are met:
39 *
40 * 3. Conditions
41 *
42 * 3.1. Redistribution of Source with Rights to Further Distribute Source.
43 * Redistribution of source code of any substantial portion of the Covered
44 * Code or modification with rights to further distribute source must include
45 * the above Copyright Notice, the above License, this list of Conditions,
46 * and the following Disclaimer and Export Compliance provision. In addition,
47 * Licensee must cause all Covered Code to which Licensee contributes to
48 * contain a file documenting the changes Licensee made to create that Covered
49 * Code and the date of any change. Licensee must include in that file the
50 * documentation of any changes made by any predecessor Licensee. Licensee
51 * must include a prominent statement that the modification is derived,
52 * directly or indirectly, from Original Intel Code.
53 *
54 * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
55 * Redistribution of source code of any substantial portion of the Covered
56 * Code or modification without rights to further distribute source must
57 * include the following Disclaimer and Export Compliance provision in the
58 * documentation and/or other materials provided with distribution. In
59 * addition, Licensee may not authorize further sublicense of source of any
60 * portion of the Covered Code, and must include terms to the effect that the
61 * license from Licensee to its licensee is limited to the intellectual
62 * property embodied in the software Licensee provides to its licensee, and
63 * not to intellectual property embodied in modifications its licensee may
64 * make.
65 *
66 * 3.3. Redistribution of Executable. Redistribution in executable form of any
67 * substantial portion of the Covered Code or modification must reproduce the
68 * above Copyright Notice, and the following Disclaimer and Export Compliance
69 * provision in the documentation and/or other materials provided with the
70 * distribution.
71 *
72 * 3.4. Intel retains all right, title, and interest in and to the Original
73 * Intel Code.
74 *
75 * 3.5. Neither the name Intel nor any other trademark owned or controlled by
76 * Intel shall be used in advertising or otherwise to promote the sale, use or
77 * other dealings in products derived from or relating to the Covered Code
78 * without prior written authorization from Intel.
79 *
80 * 4. Disclaimer and Export Compliance
81 *
82 * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
83 * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
84 * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
85 * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
86 * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
87 * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
88 * PARTICULAR PURPOSE.
89 *
90 * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
91 * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
92 * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
93 * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
94 * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
95 * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
96 * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
97 * LIMITED REMEDY.
98 *
99 * 4.3. Licensee shall not export, either directly or indirectly, any of this
100 * software or system incorporating such software without first obtaining any
101 * required license or other approval from the U. S. Department of Commerce or
102 * any other agency or department of the United States Government. In the
103 * event Licensee exports any such software from the United States or
104 * re-exports any such software from a foreign destination, Licensee shall
105 * ensure that the distribution and export/re-export of the software is in
106 * compliance with all laws, regulations, orders, or other restrictions of the
107 * U.S. Export Administration Regulations. Licensee agrees that neither it nor
108 * any of its subsidiaries will export/re-export any technical data, process,
109 * software, or service, directly or indirectly, to any country for which the
110 * United States government or any agency thereof requires an export license,
111 * other governmental approval, or letter of assurance, without first obtaining
112 * such license, approval or letter.
113 *
114 *****************************************************************************/
115
116#define __TBFADT_C__
117
118#include "acpi.h"
119#include "accommon.h"
120#include "actables.h"
121
122#define _COMPONENT          ACPI_TABLES
123        ACPI_MODULE_NAME    ("tbfadt")
124
125/* Local prototypes */
126
127static void
128AcpiTbInitGenericAddress (
129    ACPI_GENERIC_ADDRESS    *GenericAddress,
130    UINT8                   SpaceId,
131    UINT8                   ByteWidth,
132    UINT64                  Address,
133    char                    *RegisterName);
134
135static void
136AcpiTbConvertFadt (
137    void);
138
139static void
140AcpiTbValidateFadt (
141    void);
142
143static void
144AcpiTbSetupFadtRegisters (
145    void);
146
147
148/* Table for conversion of FADT to common internal format and FADT validation */
149
150typedef struct acpi_fadt_info
151{
152    char                    *Name;
153    UINT16                  Address64;
154    UINT16                  Address32;
155    UINT16                  Length;
156    UINT8                   DefaultLength;
157    UINT8                   Type;
158
159} ACPI_FADT_INFO;
160
161#define ACPI_FADT_OPTIONAL          0
162#define ACPI_FADT_REQUIRED          1
163#define ACPI_FADT_SEPARATE_LENGTH   2
164
165static ACPI_FADT_INFO     FadtInfoTable[] =
166{
167    {"Pm1aEventBlock",
168        ACPI_FADT_OFFSET (XPm1aEventBlock),
169        ACPI_FADT_OFFSET (Pm1aEventBlock),
170        ACPI_FADT_OFFSET (Pm1EventLength),
171        ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
172        ACPI_FADT_REQUIRED},
173
174    {"Pm1bEventBlock",
175        ACPI_FADT_OFFSET (XPm1bEventBlock),
176        ACPI_FADT_OFFSET (Pm1bEventBlock),
177        ACPI_FADT_OFFSET (Pm1EventLength),
178        ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
179        ACPI_FADT_OPTIONAL},
180
181    {"Pm1aControlBlock",
182        ACPI_FADT_OFFSET (XPm1aControlBlock),
183        ACPI_FADT_OFFSET (Pm1aControlBlock),
184        ACPI_FADT_OFFSET (Pm1ControlLength),
185        ACPI_PM1_REGISTER_WIDTH,
186        ACPI_FADT_REQUIRED},
187
188    {"Pm1bControlBlock",
189        ACPI_FADT_OFFSET (XPm1bControlBlock),
190        ACPI_FADT_OFFSET (Pm1bControlBlock),
191        ACPI_FADT_OFFSET (Pm1ControlLength),
192        ACPI_PM1_REGISTER_WIDTH,
193        ACPI_FADT_OPTIONAL},
194
195    {"Pm2ControlBlock",
196        ACPI_FADT_OFFSET (XPm2ControlBlock),
197        ACPI_FADT_OFFSET (Pm2ControlBlock),
198        ACPI_FADT_OFFSET (Pm2ControlLength),
199        ACPI_PM2_REGISTER_WIDTH,
200        ACPI_FADT_SEPARATE_LENGTH},
201
202    {"PmTimerBlock",
203        ACPI_FADT_OFFSET (XPmTimerBlock),
204        ACPI_FADT_OFFSET (PmTimerBlock),
205        ACPI_FADT_OFFSET (PmTimerLength),
206        ACPI_PM_TIMER_WIDTH,
207        ACPI_FADT_REQUIRED},
208
209    {"Gpe0Block",
210        ACPI_FADT_OFFSET (XGpe0Block),
211        ACPI_FADT_OFFSET (Gpe0Block),
212        ACPI_FADT_OFFSET (Gpe0BlockLength),
213        0,
214        ACPI_FADT_SEPARATE_LENGTH},
215
216    {"Gpe1Block",
217        ACPI_FADT_OFFSET (XGpe1Block),
218        ACPI_FADT_OFFSET (Gpe1Block),
219        ACPI_FADT_OFFSET (Gpe1BlockLength),
220        0,
221        ACPI_FADT_SEPARATE_LENGTH}
222};
223
224#define ACPI_FADT_INFO_ENTRIES \
225            (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO))
226
227
228/* Table used to split Event Blocks into separate status/enable registers */
229
230typedef struct acpi_fadt_pm_info
231{
232    ACPI_GENERIC_ADDRESS    *Target;
233    UINT16                  Source;
234    UINT8                   RegisterNum;
235
236} ACPI_FADT_PM_INFO;
237
238static ACPI_FADT_PM_INFO    FadtPmInfoTable[] =
239{
240    {&AcpiGbl_XPm1aStatus,
241        ACPI_FADT_OFFSET (XPm1aEventBlock),
242        0},
243
244    {&AcpiGbl_XPm1aEnable,
245        ACPI_FADT_OFFSET (XPm1aEventBlock),
246        1},
247
248    {&AcpiGbl_XPm1bStatus,
249        ACPI_FADT_OFFSET (XPm1bEventBlock),
250        0},
251
252    {&AcpiGbl_XPm1bEnable,
253        ACPI_FADT_OFFSET (XPm1bEventBlock),
254        1}
255};
256
257#define ACPI_FADT_PM_INFO_ENTRIES \
258            (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO))
259
260
261/*******************************************************************************
262 *
263 * FUNCTION:    AcpiTbInitGenericAddress
264 *
265 * PARAMETERS:  GenericAddress      - GAS struct to be initialized
266 *              SpaceId             - ACPI Space ID for this register
267 *              ByteWidth           - Width of this register
268 *              Address             - Address of the register
269 *
270 * RETURN:      None
271 *
272 * DESCRIPTION: Initialize a Generic Address Structure (GAS)
273 *              See the ACPI specification for a full description and
274 *              definition of this structure.
275 *
276 ******************************************************************************/
277
278static void
279AcpiTbInitGenericAddress (
280    ACPI_GENERIC_ADDRESS    *GenericAddress,
281    UINT8                   SpaceId,
282    UINT8                   ByteWidth,
283    UINT64                  Address,
284    char                    *RegisterName)
285{
286    UINT8                   BitWidth;
287
288
289    /* Bit width field in the GAS is only one byte long, 255 max */
290
291    BitWidth = (UINT8) (ByteWidth * 8);
292
293    if (ByteWidth > 31) /* (31*8)=248 */
294    {
295        ACPI_ERROR ((AE_INFO,
296            "%s - 32-bit FADT register is too long (%u bytes, %u bits) "
297            "to convert to GAS struct - 255 bits max, truncating",
298            RegisterName, ByteWidth, (ByteWidth * 8)));
299
300        BitWidth = 255;
301    }
302
303    /*
304     * The 64-bit Address field is non-aligned in the byte packed
305     * GAS struct.
306     */
307    ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address);
308
309    /* All other fields are byte-wide */
310
311    GenericAddress->SpaceId = SpaceId;
312    GenericAddress->BitWidth = BitWidth;
313    GenericAddress->BitOffset = 0;
314    GenericAddress->AccessWidth = 0; /* Access width ANY */
315}
316
317
318/*******************************************************************************
319 *
320 * FUNCTION:    AcpiTbParseFadt
321 *
322 * PARAMETERS:  TableIndex          - Index for the FADT
323 *
324 * RETURN:      None
325 *
326 * DESCRIPTION: Initialize the FADT, DSDT and FACS tables
327 *              (FADT contains the addresses of the DSDT and FACS)
328 *
329 ******************************************************************************/
330
331void
332AcpiTbParseFadt (
333    UINT32                  TableIndex)
334{
335    UINT32                  Length;
336    ACPI_TABLE_HEADER       *Table;
337
338
339    /*
340     * The FADT has multiple versions with different lengths,
341     * and it contains pointers to both the DSDT and FACS tables.
342     *
343     * Get a local copy of the FADT and convert it to a common format
344     * Map entire FADT, assumed to be smaller than one page.
345     */
346    Length = AcpiGbl_RootTableList.Tables[TableIndex].Length;
347
348    Table = AcpiOsMapMemory (
349                AcpiGbl_RootTableList.Tables[TableIndex].Address, Length);
350    if (!Table)
351    {
352        return;
353    }
354
355    /*
356     * Validate the FADT checksum before we copy the table. Ignore
357     * checksum error as we want to try to get the DSDT and FACS.
358     */
359    (void) AcpiTbVerifyChecksum (Table, Length);
360
361    /* Create a local copy of the FADT in common ACPI 2.0+ format */
362
363    AcpiTbCreateLocalFadt (Table, Length);
364
365    /* All done with the real FADT, unmap it */
366
367    AcpiOsUnmapMemory (Table, Length);
368
369    /* Obtain the DSDT and FACS tables via their addresses within the FADT */
370
371    AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt,
372        ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT);
373
374    /* If Hardware Reduced flag is set, there is no FACS */
375
376    if (!AcpiGbl_ReducedHardware)
377    {
378        AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs,
379            ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);
380    }
381}
382
383
384/*******************************************************************************
385 *
386 * FUNCTION:    AcpiTbCreateLocalFadt
387 *
388 * PARAMETERS:  Table               - Pointer to BIOS FADT
389 *              Length              - Length of the table
390 *
391 * RETURN:      None
392 *
393 * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
394 *              Performs validation on some important FADT fields.
395 *
396 * NOTE:        We create a local copy of the FADT regardless of the version.
397 *
398 ******************************************************************************/
399
400void
401AcpiTbCreateLocalFadt (
402    ACPI_TABLE_HEADER       *Table,
403    UINT32                  Length)
404{
405
406    /*
407     * Check if the FADT is larger than the largest table that we expect
408     * (the ACPI 5.0 version). If so, truncate the table, and issue
409     * a warning.
410     */
411    if (Length > sizeof (ACPI_TABLE_FADT))
412    {
413        ACPI_BIOS_WARNING ((AE_INFO,
414            "FADT (revision %u) is longer than ACPI 5.0 version, "
415            "truncating length %u to %u",
416            Table->Revision, Length, (UINT32) sizeof (ACPI_TABLE_FADT)));
417    }
418
419    /* Clear the entire local FADT */
420
421    ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));
422
423    /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */
424
425    ACPI_MEMCPY (&AcpiGbl_FADT, Table,
426        ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));
427
428    /* Take a copy of the Hardware Reduced flag */
429
430    AcpiGbl_ReducedHardware = FALSE;
431    if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
432    {
433        AcpiGbl_ReducedHardware = TRUE;
434    }
435
436    /* Convert the local copy of the FADT to the common internal format */
437
438    AcpiTbConvertFadt ();
439
440    /* Validate FADT values now, before we make any changes */
441
442    AcpiTbValidateFadt ();
443
444    /* Initialize the global ACPI register structures */
445
446    AcpiTbSetupFadtRegisters ();
447}
448
449
450/*******************************************************************************
451 *
452 * FUNCTION:    AcpiTbConvertFadt
453 *
454 * PARAMETERS:  None, uses AcpiGbl_FADT
455 *
456 * RETURN:      None
457 *
458 * DESCRIPTION: Converts all versions of the FADT to a common internal format.
459 *              Expand 32-bit addresses to 64-bit as necessary.
460 *
461 * NOTE:        AcpiGbl_FADT must be of size (ACPI_TABLE_FADT),
462 *              and must contain a copy of the actual FADT.
463 *
464 * Notes on 64-bit register addresses:
465 *
466 * After this FADT conversion, later ACPICA code will only use the 64-bit "X"
467 * fields of the FADT for all ACPI register addresses.
468 *
469 * The 64-bit "X" fields are optional extensions to the original 32-bit FADT
470 * V1.0 fields. Even if they are present in the FADT, they are optional and
471 * are unused if the BIOS sets them to zero. Therefore, we must copy/expand
472 * 32-bit V1.0 fields if the corresponding X field is zero.
473 *
474 * For ACPI 1.0 FADTs, all 32-bit address fields are expanded to the
475 * corresponding "X" fields in the internal FADT.
476 *
477 * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
478 * to the corresponding 64-bit X fields. For compatibility with other ACPI
479 * implementations, we ignore the 64-bit field if the 32-bit field is valid,
480 * regardless of whether the host OS is 32-bit or 64-bit.
481 *
482 ******************************************************************************/
483
484static void
485AcpiTbConvertFadt (
486    void)
487{
488    ACPI_GENERIC_ADDRESS    *Address64;
489    UINT32                  Address32;
490    UINT32                  i;
491
492
493    /*
494     * Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary.
495     * Later code will always use the X 64-bit field.
496     */
497    if (!AcpiGbl_FADT.XFacs)
498    {
499        AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
500    }
501    if (!AcpiGbl_FADT.XDsdt)
502    {
503        AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
504    }
505
506    /*
507     * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
508     * should be zero are indeed zero. This will workaround BIOSs that
509     * inadvertently place values in these fields.
510     *
511     * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
512     * at offset 45, 55, 95, and the word located at offset 109, 110.
513     *
514     * Note: The FADT revision value is unreliable. Only the length can be
515     * trusted.
516     */
517    if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
518    {
519        AcpiGbl_FADT.PreferredProfile = 0;
520        AcpiGbl_FADT.PstateControl = 0;
521        AcpiGbl_FADT.CstControl = 0;
522        AcpiGbl_FADT.BootFlags = 0;
523    }
524
525    /*
526     * Now we can update the local FADT length to the length of the
527     * current FADT version as defined by the ACPI specification.
528     * Thus, we will have a common FADT internally.
529     */
530    AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
531
532    /*
533     * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
534     * generic address structures as necessary. Later code will always use
535     * the 64-bit address structures.
536     *
537     * March 2009:
538     * We now always use the 32-bit address if it is valid (non-null). This
539     * is not in accordance with the ACPI specification which states that
540     * the 64-bit address supersedes the 32-bit version, but we do this for
541     * compatibility with other ACPI implementations. Most notably, in the
542     * case where both the 32 and 64 versions are non-null, we use the 32-bit
543     * version. This is the only address that is guaranteed to have been
544     * tested by the BIOS manufacturer.
545     */
546    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
547    {
548        Address32 = *ACPI_ADD_PTR (UINT32,
549            &AcpiGbl_FADT, FadtInfoTable[i].Address32);
550
551        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
552            &AcpiGbl_FADT, FadtInfoTable[i].Address64);
553
554        /*
555         * If both 32- and 64-bit addresses are valid (non-zero),
556         * they must match.
557         */
558        if (Address64->Address && Address32 &&
559           (Address64->Address != (UINT64) Address32))
560        {
561            ACPI_BIOS_ERROR ((AE_INFO,
562                "32/64X address mismatch in FADT/%s: "
563                "0x%8.8X/0x%8.8X%8.8X, using 32",
564                FadtInfoTable[i].Name, Address32,
565                ACPI_FORMAT_UINT64 (Address64->Address)));
566        }
567
568        /* Always use 32-bit address if it is valid (non-null) */
569
570        if (Address32)
571        {
572            /*
573             * Copy the 32-bit address to the 64-bit GAS structure. The
574             * Space ID is always I/O for 32-bit legacy address fields
575             */
576            AcpiTbInitGenericAddress (Address64, ACPI_ADR_SPACE_SYSTEM_IO,
577                *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length),
578                (UINT64) Address32, FadtInfoTable[i].Name);
579        }
580    }
581}
582
583
584/*******************************************************************************
585 *
586 * FUNCTION:    AcpiTbValidateFadt
587 *
588 * PARAMETERS:  Table           - Pointer to the FADT to be validated
589 *
590 * RETURN:      None
591 *
592 * DESCRIPTION: Validate various important fields within the FADT. If a problem
593 *              is found, issue a message, but no status is returned.
594 *              Used by both the table manager and the disassembler.
595 *
596 * Possible additional checks:
597 * (AcpiGbl_FADT.Pm1EventLength >= 4)
598 * (AcpiGbl_FADT.Pm1ControlLength >= 2)
599 * (AcpiGbl_FADT.PmTimerLength >= 4)
600 * Gpe block lengths must be multiple of 2
601 *
602 ******************************************************************************/
603
604static void
605AcpiTbValidateFadt (
606    void)
607{
608    char                    *Name;
609    ACPI_GENERIC_ADDRESS    *Address64;
610    UINT8                   Length;
611    UINT32                  i;
612
613
614    /*
615     * Check for FACS and DSDT address mismatches. An address mismatch between
616     * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
617     * DSDT/X_DSDT) would indicate the presence of two FACS or two DSDT tables.
618     */
619    if (AcpiGbl_FADT.Facs &&
620        (AcpiGbl_FADT.XFacs != (UINT64) AcpiGbl_FADT.Facs))
621    {
622        ACPI_BIOS_WARNING ((AE_INFO,
623            "32/64X FACS address mismatch in FADT - "
624            "0x%8.8X/0x%8.8X%8.8X, using 32",
625            AcpiGbl_FADT.Facs, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XFacs)));
626
627        AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs;
628    }
629
630    if (AcpiGbl_FADT.Dsdt &&
631        (AcpiGbl_FADT.XDsdt != (UINT64) AcpiGbl_FADT.Dsdt))
632    {
633        ACPI_BIOS_WARNING ((AE_INFO,
634            "32/64X DSDT address mismatch in FADT - "
635            "0x%8.8X/0x%8.8X%8.8X, using 32",
636            AcpiGbl_FADT.Dsdt, ACPI_FORMAT_UINT64 (AcpiGbl_FADT.XDsdt)));
637
638        AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt;
639    }
640
641    /* If Hardware Reduced flag is set, we are all done */
642
643    if (AcpiGbl_ReducedHardware)
644    {
645        return;
646    }
647
648    /* Examine all of the 64-bit extended address fields (X fields) */
649
650    for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
651    {
652        /*
653         * Generate pointer to the 64-bit address, get the register
654         * length (width) and the register name
655         */
656        Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
657                        &AcpiGbl_FADT, FadtInfoTable[i].Address64);
658        Length = *ACPI_ADD_PTR (UINT8,
659                        &AcpiGbl_FADT, FadtInfoTable[i].Length);
660        Name = FadtInfoTable[i].Name;
661
662        /*
663         * For each extended field, check for length mismatch between the
664         * legacy length field and the corresponding 64-bit X length field.
665         */
666        if (Address64->Address &&
667           (Address64->BitWidth != ACPI_MUL_8 (Length)))
668        {
669            ACPI_BIOS_WARNING ((AE_INFO,
670                "32/64X length mismatch in FADT/%s: %u/%u",
671                Name, ACPI_MUL_8 (Length), Address64->BitWidth));
672        }
673
674        if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED)
675        {
676            /*
677             * Field is required (PM1aEvent, PM1aControl, PmTimer).
678             * Both the address and length must be non-zero.
679             */
680            if (!Address64->Address || !Length)
681            {
682                ACPI_BIOS_ERROR ((AE_INFO,
683                    "Required FADT field %s has zero address and/or length: "
684                    "0x%8.8X%8.8X/0x%X",
685                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
686            }
687        }
688        else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH)
689        {
690            /*
691             * Field is optional (PM2Control, GPE0, GPE1) AND has its own
692             * length field. If present, both the address and length must
693             * be valid.
694             */
695            if ((Address64->Address && !Length) ||
696                (!Address64->Address && Length))
697            {
698                ACPI_BIOS_WARNING ((AE_INFO,
699                    "Optional FADT field %s has zero address or length: "
700                    "0x%8.8X%8.8X/0x%X",
701                    Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
702            }
703        }
704    }
705}
706
707
708/*******************************************************************************
709 *
710 * FUNCTION:    AcpiTbSetupFadtRegisters
711 *
712 * PARAMETERS:  None, uses AcpiGbl_FADT.
713 *
714 * RETURN:      None
715 *
716 * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
717 *              force FADT register definitions to their default lengths.
718 *
719 ******************************************************************************/
720
721static void
722AcpiTbSetupFadtRegisters (
723    void)
724{
725    ACPI_GENERIC_ADDRESS    *Target64;
726    ACPI_GENERIC_ADDRESS    *Source64;
727    UINT8                   Pm1RegisterByteWidth;
728    UINT32                  i;
729
730
731    /*
732     * Optionally check all register lengths against the default values and
733     * update them if they are incorrect.
734     */
735    if (AcpiGbl_UseDefaultRegisterWidths)
736    {
737        for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
738        {
739            Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
740                FadtInfoTable[i].Address64);
741
742            /*
743             * If a valid register (Address != 0) and the (DefaultLength > 0)
744             * (Not a GPE register), then check the width against the default.
745             */
746            if ((Target64->Address) &&
747                (FadtInfoTable[i].DefaultLength > 0) &&
748                (FadtInfoTable[i].DefaultLength != Target64->BitWidth))
749            {
750                ACPI_BIOS_WARNING ((AE_INFO,
751                    "Invalid length for FADT/%s: %u, using default %u",
752                    FadtInfoTable[i].Name, Target64->BitWidth,
753                    FadtInfoTable[i].DefaultLength));
754
755                /* Incorrect size, set width to the default */
756
757                Target64->BitWidth = FadtInfoTable[i].DefaultLength;
758            }
759        }
760    }
761
762    /*
763     * Get the length of the individual PM1 registers (enable and status).
764     * Each register is defined to be (event block length / 2). Extra divide
765     * by 8 converts bits to bytes.
766     */
767    Pm1RegisterByteWidth = (UINT8)
768        ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth);
769
770    /*
771     * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
772     * registers. These addresses do not appear (directly) in the FADT, so it
773     * is useful to pre-calculate them from the PM1 Event Block definitions.
774     *
775     * The PM event blocks are split into two register blocks, first is the
776     * PM Status Register block, followed immediately by the PM Enable
777     * Register block. Each is of length (Pm1EventLength/2)
778     *
779     * Note: The PM1A event block is required by the ACPI specification.
780     * However, the PM1B event block is optional and is rarely, if ever,
781     * used.
782     */
783
784    for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++)
785    {
786        Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
787            FadtPmInfoTable[i].Source);
788
789        if (Source64->Address)
790        {
791            AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target,
792                Source64->SpaceId, Pm1RegisterByteWidth,
793                Source64->Address +
794                    (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth),
795                "PmRegisters");
796        }
797    }
798}
799