Back to home page

LXR

 
 

    


File indexing completed on 2025-05-11 08:24:03

0001 /******************************************************************************
0002  *
0003  * Module Name: tbfadt   - FADT table utilities
0004  *
0005  *****************************************************************************/
0006 
0007 /******************************************************************************
0008  *
0009  * 1. Copyright Notice
0010  *
0011  * Some or all of this work - Copyright (c) 1999 - 2024, Intel Corp.
0012  * All rights reserved.
0013  *
0014  * 2. License
0015  *
0016  * 2.1. This is your license from Intel Corp. under its intellectual property
0017  * rights. You may have additional license terms from the party that provided
0018  * you this software, covering your right to use that party's intellectual
0019  * property rights.
0020  *
0021  * 2.2. Intel grants, free of charge, to any person ("Licensee") obtaining a
0022  * copy of the source code appearing in this file ("Covered Code") an
0023  * irrevocable, perpetual, worldwide license under Intel's copyrights in the
0024  * base code distributed originally by Intel ("Original Intel Code") to copy,
0025  * make derivatives, distribute, use and display any portion of the Covered
0026  * Code in any form, with the right to sublicense such rights; and
0027  *
0028  * 2.3. Intel grants Licensee a non-exclusive and non-transferable patent
0029  * license (with the right to sublicense), under only those claims of Intel
0030  * patents that are infringed by the Original Intel Code, to make, use, sell,
0031  * offer to sell, and import the Covered Code and derivative works thereof
0032  * solely to the minimum extent necessary to exercise the above copyright
0033  * license, and in no event shall the patent license extend to any additions
0034  * to or modifications of the Original Intel Code. No other license or right
0035  * is granted directly or by implication, estoppel or otherwise;
0036  *
0037  * The above copyright and patent license is granted only if the following
0038  * conditions are met:
0039  *
0040  * 3. Conditions
0041  *
0042  * 3.1. Redistribution of Source with Rights to Further Distribute Source.
0043  * Redistribution of source code of any substantial portion of the Covered
0044  * Code or modification with rights to further distribute source must include
0045  * the above Copyright Notice, the above License, this list of Conditions,
0046  * and the following Disclaimer and Export Compliance provision. In addition,
0047  * Licensee must cause all Covered Code to which Licensee contributes to
0048  * contain a file documenting the changes Licensee made to create that Covered
0049  * Code and the date of any change. Licensee must include in that file the
0050  * documentation of any changes made by any predecessor Licensee. Licensee
0051  * must include a prominent statement that the modification is derived,
0052  * directly or indirectly, from Original Intel Code.
0053  *
0054  * 3.2. Redistribution of Source with no Rights to Further Distribute Source.
0055  * Redistribution of source code of any substantial portion of the Covered
0056  * Code or modification without rights to further distribute source must
0057  * include the following Disclaimer and Export Compliance provision in the
0058  * documentation and/or other materials provided with distribution. In
0059  * addition, Licensee may not authorize further sublicense of source of any
0060  * portion of the Covered Code, and must include terms to the effect that the
0061  * license from Licensee to its licensee is limited to the intellectual
0062  * property embodied in the software Licensee provides to its licensee, and
0063  * not to intellectual property embodied in modifications its licensee may
0064  * make.
0065  *
0066  * 3.3. Redistribution of Executable. Redistribution in executable form of any
0067  * substantial portion of the Covered Code or modification must reproduce the
0068  * above Copyright Notice, and the following Disclaimer and Export Compliance
0069  * provision in the documentation and/or other materials provided with the
0070  * distribution.
0071  *
0072  * 3.4. Intel retains all right, title, and interest in and to the Original
0073  * Intel Code.
0074  *
0075  * 3.5. Neither the name Intel nor any other trademark owned or controlled by
0076  * Intel shall be used in advertising or otherwise to promote the sale, use or
0077  * other dealings in products derived from or relating to the Covered Code
0078  * without prior written authorization from Intel.
0079  *
0080  * 4. Disclaimer and Export Compliance
0081  *
0082  * 4.1. INTEL MAKES NO WARRANTY OF ANY KIND REGARDING ANY SOFTWARE PROVIDED
0083  * HERE. ANY SOFTWARE ORIGINATING FROM INTEL OR DERIVED FROM INTEL SOFTWARE
0084  * IS PROVIDED "AS IS," AND INTEL WILL NOT PROVIDE ANY SUPPORT, ASSISTANCE,
0085  * INSTALLATION, TRAINING OR OTHER SERVICES. INTEL WILL NOT PROVIDE ANY
0086  * UPDATES, ENHANCEMENTS OR EXTENSIONS. INTEL SPECIFICALLY DISCLAIMS ANY
0087  * IMPLIED WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT AND FITNESS FOR A
0088  * PARTICULAR PURPOSE.
0089  *
0090  * 4.2. IN NO EVENT SHALL INTEL HAVE ANY LIABILITY TO LICENSEE, ITS LICENSEES
0091  * OR ANY OTHER THIRD PARTY, FOR ANY LOST PROFITS, LOST DATA, LOSS OF USE OR
0092  * COSTS OF PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES, OR FOR ANY INDIRECT,
0093  * SPECIAL OR CONSEQUENTIAL DAMAGES ARISING OUT OF THIS AGREEMENT, UNDER ANY
0094  * CAUSE OF ACTION OR THEORY OF LIABILITY, AND IRRESPECTIVE OF WHETHER INTEL
0095  * HAS ADVANCE NOTICE OF THE POSSIBILITY OF SUCH DAMAGES. THESE LIMITATIONS
0096  * SHALL APPLY NOTWITHSTANDING THE FAILURE OF THE ESSENTIAL PURPOSE OF ANY
0097  * LIMITED REMEDY.
0098  *
0099  * 4.3. Licensee shall not export, either directly or indirectly, any of this
0100  * software or system incorporating such software without first obtaining any
0101  * required license or other approval from the U. S. Department of Commerce or
0102  * any other agency or department of the United States Government. In the
0103  * event Licensee exports any such software from the United States or
0104  * re-exports any such software from a foreign destination, Licensee shall
0105  * ensure that the distribution and export/re-export of the software is in
0106  * compliance with all laws, regulations, orders, or other restrictions of the
0107  * U.S. Export Administration Regulations. Licensee agrees that neither it nor
0108  * any of its subsidiaries will export/re-export any technical data, process,
0109  * software, or service, directly or indirectly, to any country for which the
0110  * United States government or any agency thereof requires an export license,
0111  * other governmental approval, or letter of assurance, without first obtaining
0112  * such license, approval or letter.
0113  *
0114  *****************************************************************************
0115  *
0116  * Alternatively, you may choose to be licensed under the terms of the
0117  * following license:
0118  *
0119  * Redistribution and use in source and binary forms, with or without
0120  * modification, are permitted provided that the following conditions
0121  * are met:
0122  * 1. Redistributions of source code must retain the above copyright
0123  *    notice, this list of conditions, and the following disclaimer,
0124  *    without modification.
0125  * 2. Redistributions in binary form must reproduce at minimum a disclaimer
0126  *    substantially similar to the "NO WARRANTY" disclaimer below
0127  *    ("Disclaimer") and any redistribution must be conditioned upon
0128  *    including a substantially similar Disclaimer requirement for further
0129  *    binary redistribution.
0130  * 3. Neither the names of the above-listed copyright holders nor the names
0131  *    of any contributors may be used to endorse or promote products derived
0132  *    from this software without specific prior written permission.
0133  *
0134  * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
0135  * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
0136  * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR
0137  * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT
0138  * OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
0139  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
0140  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
0141  * DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
0142  * THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
0143  * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
0144  * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
0145  *
0146  * Alternatively, you may choose to be licensed under the terms of the
0147  * GNU General Public License ("GPL") version 2 as published by the Free
0148  * Software Foundation.
0149  *
0150  *****************************************************************************/
0151 
0152 #include "acpi.h"
0153 #include "accommon.h"
0154 #include "actables.h"
0155 
0156 #define _COMPONENT          ACPI_TABLES
0157         ACPI_MODULE_NAME    ("tbfadt")
0158 
0159 /* Local prototypes */
0160 
0161 static void
0162 AcpiTbInitGenericAddress (
0163     ACPI_GENERIC_ADDRESS    *GenericAddress,
0164     UINT8                   SpaceId,
0165     UINT8                   ByteWidth,
0166     UINT64                  Address,
0167     const char              *RegisterName,
0168     UINT8                   Flags);
0169 
0170 static void
0171 AcpiTbConvertFadt (
0172     void);
0173 
0174 static void
0175 AcpiTbSetupFadtRegisters (
0176     void);
0177 
0178 static UINT64
0179 AcpiTbSelectAddress (
0180     char                    *RegisterName,
0181     UINT32                  Address32,
0182     UINT64                  Address64);
0183 
0184 
0185 /* Table for conversion of FADT to common internal format and FADT validation */
0186 
0187 typedef struct acpi_fadt_info
0188 {
0189     const char              *Name;
0190     UINT16                  Address64;
0191     UINT16                  Address32;
0192     UINT16                  Length;
0193     UINT8                   DefaultLength;
0194     UINT8                   Flags;
0195 
0196 } ACPI_FADT_INFO;
0197 
0198 #define ACPI_FADT_OPTIONAL          0
0199 #define ACPI_FADT_REQUIRED          1
0200 #define ACPI_FADT_SEPARATE_LENGTH   2
0201 #define ACPI_FADT_GPE_REGISTER      4
0202 
0203 static ACPI_FADT_INFO     FadtInfoTable[] =
0204 {
0205     {"Pm1aEventBlock",
0206         ACPI_FADT_OFFSET (XPm1aEventBlock),
0207         ACPI_FADT_OFFSET (Pm1aEventBlock),
0208         ACPI_FADT_OFFSET (Pm1EventLength),
0209         ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
0210         ACPI_FADT_REQUIRED},
0211 
0212     {"Pm1bEventBlock",
0213         ACPI_FADT_OFFSET (XPm1bEventBlock),
0214         ACPI_FADT_OFFSET (Pm1bEventBlock),
0215         ACPI_FADT_OFFSET (Pm1EventLength),
0216         ACPI_PM1_REGISTER_WIDTH * 2,        /* Enable + Status register */
0217         ACPI_FADT_OPTIONAL},
0218 
0219     {"Pm1aControlBlock",
0220         ACPI_FADT_OFFSET (XPm1aControlBlock),
0221         ACPI_FADT_OFFSET (Pm1aControlBlock),
0222         ACPI_FADT_OFFSET (Pm1ControlLength),
0223         ACPI_PM1_REGISTER_WIDTH,
0224         ACPI_FADT_REQUIRED},
0225 
0226     {"Pm1bControlBlock",
0227         ACPI_FADT_OFFSET (XPm1bControlBlock),
0228         ACPI_FADT_OFFSET (Pm1bControlBlock),
0229         ACPI_FADT_OFFSET (Pm1ControlLength),
0230         ACPI_PM1_REGISTER_WIDTH,
0231         ACPI_FADT_OPTIONAL},
0232 
0233     {"Pm2ControlBlock",
0234         ACPI_FADT_OFFSET (XPm2ControlBlock),
0235         ACPI_FADT_OFFSET (Pm2ControlBlock),
0236         ACPI_FADT_OFFSET (Pm2ControlLength),
0237         ACPI_PM2_REGISTER_WIDTH,
0238         ACPI_FADT_SEPARATE_LENGTH},
0239 
0240     {"PmTimerBlock",
0241         ACPI_FADT_OFFSET (XPmTimerBlock),
0242         ACPI_FADT_OFFSET (PmTimerBlock),
0243         ACPI_FADT_OFFSET (PmTimerLength),
0244         ACPI_PM_TIMER_WIDTH,
0245         ACPI_FADT_SEPARATE_LENGTH},         /* ACPI 5.0A: Timer is optional */
0246 
0247     {"Gpe0Block",
0248         ACPI_FADT_OFFSET (XGpe0Block),
0249         ACPI_FADT_OFFSET (Gpe0Block),
0250         ACPI_FADT_OFFSET (Gpe0BlockLength),
0251         0,
0252         ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER},
0253 
0254     {"Gpe1Block",
0255         ACPI_FADT_OFFSET (XGpe1Block),
0256         ACPI_FADT_OFFSET (Gpe1Block),
0257         ACPI_FADT_OFFSET (Gpe1BlockLength),
0258         0,
0259         ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}
0260 };
0261 
0262 #define ACPI_FADT_INFO_ENTRIES \
0263             (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO))
0264 
0265 
0266 /* Table used to split Event Blocks into separate status/enable registers */
0267 
0268 typedef struct acpi_fadt_pm_info
0269 {
0270     ACPI_GENERIC_ADDRESS    *Target;
0271     UINT16                  Source;
0272     UINT8                   RegisterNum;
0273 
0274 } ACPI_FADT_PM_INFO;
0275 
0276 static ACPI_FADT_PM_INFO    FadtPmInfoTable[] =
0277 {
0278     {&AcpiGbl_XPm1aStatus,
0279         ACPI_FADT_OFFSET (XPm1aEventBlock),
0280         0},
0281 
0282     {&AcpiGbl_XPm1aEnable,
0283         ACPI_FADT_OFFSET (XPm1aEventBlock),
0284         1},
0285 
0286     {&AcpiGbl_XPm1bStatus,
0287         ACPI_FADT_OFFSET (XPm1bEventBlock),
0288         0},
0289 
0290     {&AcpiGbl_XPm1bEnable,
0291         ACPI_FADT_OFFSET (XPm1bEventBlock),
0292         1}
0293 };
0294 
0295 #define ACPI_FADT_PM_INFO_ENTRIES \
0296             (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO))
0297 
0298 
0299 /*******************************************************************************
0300  *
0301  * FUNCTION:    AcpiTbInitGenericAddress
0302  *
0303  * PARAMETERS:  GenericAddress      - GAS struct to be initialized
0304  *              SpaceId             - ACPI Space ID for this register
0305  *              ByteWidth           - Width of this register
0306  *              Address             - Address of the register
0307  *              RegisterName        - ASCII name of the ACPI register
0308  *
0309  * RETURN:      None
0310  *
0311  * DESCRIPTION: Initialize a Generic Address Structure (GAS)
0312  *              See the ACPI specification for a full description and
0313  *              definition of this structure.
0314  *
0315  ******************************************************************************/
0316 
0317 static void
0318 AcpiTbInitGenericAddress (
0319     ACPI_GENERIC_ADDRESS    *GenericAddress,
0320     UINT8                   SpaceId,
0321     UINT8                   ByteWidth,
0322     UINT64                  Address,
0323     const char              *RegisterName,
0324     UINT8                   Flags)
0325 {
0326     UINT8                   BitWidth;
0327 
0328 
0329     /*
0330      * Bit width field in the GAS is only one byte long, 255 max.
0331      * Check for BitWidth overflow in GAS.
0332      */
0333     BitWidth = (UINT8) (ByteWidth * 8);
0334     if (ByteWidth > 31)     /* (31*8)=248, (32*8)=256 */
0335     {
0336         /*
0337          * No error for GPE blocks, because we do not use the BitWidth
0338          * for GPEs, the legacy length (ByteWidth) is used instead to
0339          * allow for a large number of GPEs.
0340          */
0341         if (!(Flags & ACPI_FADT_GPE_REGISTER))
0342         {
0343             ACPI_ERROR ((AE_INFO,
0344                 "%s - 32-bit FADT register is too long (%u bytes, %u bits) "
0345                 "to convert to GAS struct - 255 bits max, truncating",
0346                 RegisterName, ByteWidth, (ByteWidth * 8)));
0347         }
0348 
0349         BitWidth = 255;
0350     }
0351 
0352     /*
0353      * The 64-bit Address field is non-aligned in the byte packed
0354      * GAS struct.
0355      */
0356     ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address);
0357 
0358     /* All other fields are byte-wide */
0359 
0360     GenericAddress->SpaceId = SpaceId;
0361     GenericAddress->BitWidth = BitWidth;
0362     GenericAddress->BitOffset = 0;
0363     GenericAddress->AccessWidth = 0; /* Access width ANY */
0364 }
0365 
0366 
0367 /*******************************************************************************
0368  *
0369  * FUNCTION:    AcpiTbSelectAddress
0370  *
0371  * PARAMETERS:  RegisterName        - ASCII name of the ACPI register
0372  *              Address32           - 32-bit address of the register
0373  *              Address64           - 64-bit address of the register
0374  *
0375  * RETURN:      The resolved 64-bit address
0376  *
0377  * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within
0378  *              the FADT. Used for the FACS and DSDT addresses.
0379  *
0380  * NOTES:
0381  *
0382  * Check for FACS and DSDT address mismatches. An address mismatch between
0383  * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and
0384  * DSDT/X_DSDT) could be a corrupted address field or it might indicate
0385  * the presence of two FACS or two DSDT tables.
0386  *
0387  * November 2013:
0388  * By default, as per the ACPICA specification, a valid 64-bit address is
0389  * used regardless of the value of the 32-bit address. However, this
0390  * behavior can be overridden via the AcpiGbl_Use32BitFadtAddresses flag.
0391  *
0392  ******************************************************************************/
0393 
0394 static UINT64
0395 AcpiTbSelectAddress (
0396     char                    *RegisterName,
0397     UINT32                  Address32,
0398     UINT64                  Address64)
0399 {
0400 
0401     if (!Address64)
0402     {
0403         /* 64-bit address is zero, use 32-bit address */
0404 
0405         return ((UINT64) Address32);
0406     }
0407 
0408     if (Address32 &&
0409        (Address64 != (UINT64) Address32))
0410     {
0411         /* Address mismatch between 32-bit and 64-bit versions */
0412 
0413         ACPI_BIOS_WARNING ((AE_INFO,
0414             "32/64X %s address mismatch in FADT: "
0415             "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
0416             RegisterName, Address32, ACPI_FORMAT_UINT64 (Address64),
0417             AcpiGbl_Use32BitFadtAddresses ? 32 : 64));
0418 
0419         /* 32-bit address override */
0420 
0421         if (AcpiGbl_Use32BitFadtAddresses)
0422         {
0423             return ((UINT64) Address32);
0424         }
0425     }
0426 
0427     /* Default is to use the 64-bit address */
0428 
0429     return (Address64);
0430 }
0431 
0432 
0433 /*******************************************************************************
0434  *
0435  * FUNCTION:    AcpiTbParseFadt
0436  *
0437  * PARAMETERS:  None
0438  *
0439  * RETURN:      None
0440  *
0441  * DESCRIPTION: Initialize the FADT, DSDT and FACS tables
0442  *              (FADT contains the addresses of the DSDT and FACS)
0443  *
0444  ******************************************************************************/
0445 
0446 void
0447 AcpiTbParseFadt (
0448     void)
0449 {
0450     UINT32                  Length;
0451     ACPI_TABLE_HEADER       *Table;
0452     ACPI_TABLE_DESC         *FadtDesc;
0453     ACPI_STATUS             Status;
0454 
0455 
0456     /*
0457      * The FADT has multiple versions with different lengths,
0458      * and it contains pointers to both the DSDT and FACS tables.
0459      *
0460      * Get a local copy of the FADT and convert it to a common format
0461      * Map entire FADT, assumed to be smaller than one page.
0462      */
0463     FadtDesc = &AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex];
0464     Status = AcpiTbGetTable (FadtDesc, &Table);
0465     if (ACPI_FAILURE (Status))
0466     {
0467         return;
0468     }
0469     Length = FadtDesc->Length;
0470 
0471     /*
0472      * Validate the FADT checksum before we copy the table. Ignore
0473      * checksum error as we want to try to get the DSDT and FACS.
0474      */
0475     (void) AcpiUtVerifyChecksum (Table, Length);
0476 
0477     /* Create a local copy of the FADT in common ACPI 2.0+ format */
0478 
0479     AcpiTbCreateLocalFadt (Table, Length);
0480 
0481     /* All done with the real FADT, unmap it */
0482 
0483     AcpiTbPutTable (FadtDesc);
0484 
0485     /* Obtain the DSDT and FACS tables via their addresses within the FADT */
0486 
0487     AcpiTbInstallStandardTable (
0488         (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt,
0489         ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE,
0490         &AcpiGbl_DsdtIndex);
0491 
0492     if (AcpiGbl_FADT.Facs)
0493     {
0494         AcpiTbInstallStandardTable (
0495             (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.Facs,
0496             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE,
0497             &AcpiGbl_FacsIndex);
0498     }
0499     if (AcpiGbl_FADT.XFacs)
0500     {
0501         AcpiTbInstallStandardTable (
0502             (ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs,
0503             ACPI_TABLE_ORIGIN_INTERNAL_PHYSICAL, NULL, FALSE, TRUE,
0504             &AcpiGbl_XFacsIndex);
0505     }
0506 }
0507 
0508 
0509 /*******************************************************************************
0510  *
0511  * FUNCTION:    AcpiTbCreateLocalFadt
0512  *
0513  * PARAMETERS:  Table               - Pointer to BIOS FADT
0514  *              Length              - Length of the table
0515  *
0516  * RETURN:      None
0517  *
0518  * DESCRIPTION: Get a local copy of the FADT and convert it to a common format.
0519  *              Performs validation on some important FADT fields.
0520  *
0521  * NOTE:        We create a local copy of the FADT regardless of the version.
0522  *
0523  ******************************************************************************/
0524 
0525 void
0526 AcpiTbCreateLocalFadt (
0527     ACPI_TABLE_HEADER       *Table,
0528     UINT32                  Length)
0529 {
0530 
0531     /*
0532      * Check if the FADT is larger than the largest table that we expect
0533      * (typically the current ACPI specification version). If so, truncate
0534      * the table, and issue a warning.
0535      */
0536     if (Length > sizeof (ACPI_TABLE_FADT))
0537     {
0538         ACPI_BIOS_WARNING ((AE_INFO,
0539             "FADT (revision %u) is longer than %s length, "
0540             "truncating length %u to %u",
0541             Table->Revision, ACPI_FADT_CONFORMANCE, Length,
0542             (UINT32) sizeof (ACPI_TABLE_FADT)));
0543     }
0544 
0545     /* Clear the entire local FADT */
0546 
0547     memset (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT));
0548 
0549     /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */
0550 
0551     memcpy (&AcpiGbl_FADT, Table,
0552         ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT)));
0553 
0554     /* Take a copy of the Hardware Reduced flag */
0555 
0556     AcpiGbl_ReducedHardware = FALSE;
0557     if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED)
0558     {
0559         AcpiGbl_ReducedHardware = TRUE;
0560     }
0561 
0562     /* Convert the local copy of the FADT to the common internal format */
0563 
0564     AcpiTbConvertFadt ();
0565 
0566     /* Initialize the global ACPI register structures */
0567 
0568     AcpiTbSetupFadtRegisters ();
0569 }
0570 
0571 
0572 /*******************************************************************************
0573  *
0574  * FUNCTION:    AcpiTbConvertFadt
0575  *
0576  * PARAMETERS:  None - AcpiGbl_FADT is used.
0577  *
0578  * RETURN:      None
0579  *
0580  * DESCRIPTION: Converts all versions of the FADT to a common internal format.
0581  *              Expand 32-bit addresses to 64-bit as necessary. Also validate
0582  *              important fields within the FADT.
0583  *
0584  * NOTE:        AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), and must
0585  *              contain a copy of the actual BIOS-provided FADT.
0586  *
0587  * Notes on 64-bit register addresses:
0588  *
0589  * After this FADT conversion, later ACPICA code will only use the 64-bit "X"
0590  * fields of the FADT for all ACPI register addresses.
0591  *
0592  * The 64-bit X fields are optional extensions to the original 32-bit FADT
0593  * V1.0 fields. Even if they are present in the FADT, they are optional and
0594  * are unused if the BIOS sets them to zero. Therefore, we must copy/expand
0595  * 32-bit V1.0 fields to the 64-bit X fields if the 64-bit X field is originally
0596  * zero.
0597  *
0598  * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address
0599  * fields are expanded to the corresponding 64-bit X fields in the internal
0600  * common FADT.
0601  *
0602  * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded
0603  * to the corresponding 64-bit X fields, if the 64-bit field is originally
0604  * zero. Adhering to the ACPI specification, we completely ignore the 32-bit
0605  * field if the 64-bit field is valid, regardless of whether the host OS is
0606  * 32-bit or 64-bit.
0607  *
0608  * Possible additional checks:
0609  *  (AcpiGbl_FADT.Pm1EventLength >= 4)
0610  *  (AcpiGbl_FADT.Pm1ControlLength >= 2)
0611  *  (AcpiGbl_FADT.PmTimerLength >= 4)
0612  *  Gpe block lengths must be multiple of 2
0613  *
0614  ******************************************************************************/
0615 
0616 static void
0617 AcpiTbConvertFadt (
0618     void)
0619 {
0620     const char              *Name;
0621     ACPI_GENERIC_ADDRESS    *Address64;
0622     UINT32                  Address32;
0623     UINT8                   Length;
0624     UINT8                   Flags;
0625     UINT32                  i;
0626 
0627 
0628     /*
0629      * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which
0630      * should be zero are indeed zero. This will workaround BIOSs that
0631      * inadvertently place values in these fields.
0632      *
0633      * The ACPI 1.0 reserved fields that will be zeroed are the bytes located
0634      * at offset 45, 55, 95, and the word located at offset 109, 110.
0635      *
0636      * Note: The FADT revision value is unreliable. Only the length can be
0637      * trusted.
0638      */
0639     if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE)
0640     {
0641         AcpiGbl_FADT.PreferredProfile = 0;
0642         AcpiGbl_FADT.PstateControl = 0;
0643         AcpiGbl_FADT.CstControl = 0;
0644         AcpiGbl_FADT.BootFlags = 0;
0645     }
0646 
0647     /*
0648      * Now we can update the local FADT length to the length of the
0649      * current FADT version as defined by the ACPI specification.
0650      * Thus, we will have a common FADT internally.
0651      */
0652     AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT);
0653 
0654     /*
0655      * Expand the 32-bit DSDT addresses to 64-bit as necessary.
0656      * Later ACPICA code will always use the X 64-bit field.
0657      */
0658     AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT",
0659         AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt);
0660 
0661     /* If Hardware Reduced flag is set, we are all done */
0662 
0663     if (AcpiGbl_ReducedHardware)
0664     {
0665         return;
0666     }
0667 
0668     /* Examine all of the 64-bit extended address fields (X fields) */
0669 
0670     for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
0671     {
0672         /*
0673          * Get the 32-bit and 64-bit addresses, as well as the register
0674          * length and register name.
0675          */
0676         Address32 = *ACPI_ADD_PTR (UINT32,
0677             &AcpiGbl_FADT, FadtInfoTable[i].Address32);
0678 
0679         Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS,
0680             &AcpiGbl_FADT, FadtInfoTable[i].Address64);
0681 
0682         Length = *ACPI_ADD_PTR (UINT8,
0683             &AcpiGbl_FADT, FadtInfoTable[i].Length);
0684 
0685         Name = FadtInfoTable[i].Name;
0686         Flags = FadtInfoTable[i].Flags;
0687 
0688         /*
0689          * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X"
0690          * generic address structures as necessary. Later code will always use
0691          * the 64-bit address structures.
0692          *
0693          * November 2013:
0694          * Now always use the 64-bit address if it is valid (non-zero), in
0695          * accordance with the ACPI specification which states that a 64-bit
0696          * address supersedes the 32-bit version. This behavior can be
0697          * overridden by the AcpiGbl_Use32BitFadtAddresses flag.
0698          *
0699          * During 64-bit address construction and verification,
0700          * these cases are handled:
0701          *
0702          * Address32 zero, Address64 [don't care]   - Use Address64
0703          *
0704          * No override: if AcpiGbl_Use32BitFadtAddresses is FALSE, and:
0705          * Address32 non-zero, Address64 zero       - Copy/use Address32
0706          * Address32 non-zero == Address64 non-zero - Use Address64
0707          * Address32 non-zero != Address64 non-zero - Warning, use Address64
0708          *
0709          * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and:
0710          * Address32 non-zero, Address64 zero       - Copy/use Address32
0711          * Address32 non-zero == Address64 non-zero - Copy/use Address32
0712          * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32
0713          *
0714          * Note: SpaceId is always I/O for 32-bit legacy address fields
0715          */
0716         if (Address32)
0717         {
0718             if (Address64->Address)
0719             {
0720                 if (Address64->Address != (UINT64) Address32)
0721                 {
0722                     /* Address mismatch */
0723 
0724                     ACPI_BIOS_WARNING ((AE_INFO,
0725                         "32/64X address mismatch in FADT/%s: "
0726                         "0x%8.8X/0x%8.8X%8.8X, using %u-bit address",
0727                         Name, Address32,
0728                         ACPI_FORMAT_UINT64 (Address64->Address),
0729                         AcpiGbl_Use32BitFadtAddresses ? 32 : 64));
0730                 }
0731 
0732                 /*
0733                  * For each extended field, check for length mismatch
0734                  * between the legacy length field and the corresponding
0735                  * 64-bit X length field.
0736                  * Note: If the legacy length field is > 0xFF bits, ignore
0737                  * this check. (GPE registers can be larger than the
0738                  * 64-bit GAS structure can accommodate, 0xFF bits).
0739                  */
0740                 if ((ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) &&
0741                     (Address64->BitWidth != ACPI_MUL_8 (Length)))
0742                 {
0743                     ACPI_BIOS_WARNING ((AE_INFO,
0744                         "32/64X length mismatch in FADT/%s: %u/%u",
0745                         Name, ACPI_MUL_8 (Length), Address64->BitWidth));
0746                 }
0747             }
0748 
0749             /*
0750              * Hardware register access code always uses the 64-bit fields.
0751              * So if the 64-bit field is zero or is to be overridden,
0752              * initialize it with the 32-bit fields.
0753              * Note that when the 32-bit address favor is specified, the
0754              * 64-bit fields are always re-initialized so that
0755              * AccessSize/BitWidth/BitOffset fields can be correctly
0756              * configured to the values to trigger a 32-bit compatible
0757              * access mode in the hardware register access code.
0758              */
0759             if (!Address64->Address || AcpiGbl_Use32BitFadtAddresses)
0760             {
0761                 AcpiTbInitGenericAddress (Address64,
0762                     ACPI_ADR_SPACE_SYSTEM_IO, Length,
0763                     (UINT64) Address32, Name, Flags);
0764             }
0765         }
0766 
0767         if (FadtInfoTable[i].Flags & ACPI_FADT_REQUIRED)
0768         {
0769             /*
0770              * Field is required (PM1aEvent, PM1aControl).
0771              * Both the address and length must be non-zero.
0772              */
0773             if (!Address64->Address || !Length)
0774             {
0775                 ACPI_BIOS_ERROR ((AE_INFO,
0776                     "Required FADT field %s has zero address and/or length: "
0777                     "0x%8.8X%8.8X/0x%X",
0778                     Name, ACPI_FORMAT_UINT64 (Address64->Address), Length));
0779             }
0780         }
0781         else if (FadtInfoTable[i].Flags & ACPI_FADT_SEPARATE_LENGTH)
0782         {
0783             /*
0784              * Field is optional (PM2Control, GPE0, GPE1) AND has its own
0785              * length field. If present, both the address and length must
0786              * be valid.
0787              */
0788             if ((Address64->Address && !Length) ||
0789                 (!Address64->Address && Length))
0790             {
0791                 ACPI_BIOS_WARNING ((AE_INFO,
0792                     "Optional FADT field %s has valid %s but zero %s: "
0793                     "0x%8.8X%8.8X/0x%X", Name,
0794                     (Length ? "Length" : "Address"),
0795                     (Length ? "Address": "Length"),
0796                     ACPI_FORMAT_UINT64 (Address64->Address), Length));
0797             }
0798         }
0799     }
0800 }
0801 
0802 
0803 /*******************************************************************************
0804  *
0805  * FUNCTION:    AcpiTbSetupFadtRegisters
0806  *
0807  * PARAMETERS:  None, uses AcpiGbl_FADT.
0808  *
0809  * RETURN:      None
0810  *
0811  * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally,
0812  *              force FADT register definitions to their default lengths.
0813  *
0814  ******************************************************************************/
0815 
0816 static void
0817 AcpiTbSetupFadtRegisters (
0818     void)
0819 {
0820     ACPI_GENERIC_ADDRESS    *Target64;
0821     ACPI_GENERIC_ADDRESS    *Source64;
0822     UINT8                   Pm1RegisterByteWidth;
0823     UINT32                  i;
0824 
0825 
0826     /*
0827      * Optionally check all register lengths against the default values and
0828      * update them if they are incorrect.
0829      */
0830     if (AcpiGbl_UseDefaultRegisterWidths)
0831     {
0832         for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++)
0833         {
0834             Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
0835                 FadtInfoTable[i].Address64);
0836 
0837             /*
0838              * If a valid register (Address != 0) and the (DefaultLength > 0)
0839              * (Not a GPE register), then check the width against the default.
0840              */
0841             if ((Target64->Address) &&
0842                 (FadtInfoTable[i].DefaultLength > 0) &&
0843                 (FadtInfoTable[i].DefaultLength != Target64->BitWidth))
0844             {
0845                 ACPI_BIOS_WARNING ((AE_INFO,
0846                     "Invalid length for FADT/%s: %u, using default %u",
0847                     FadtInfoTable[i].Name, Target64->BitWidth,
0848                     FadtInfoTable[i].DefaultLength));
0849 
0850                 /* Incorrect size, set width to the default */
0851 
0852                 Target64->BitWidth = FadtInfoTable[i].DefaultLength;
0853             }
0854         }
0855     }
0856 
0857     /*
0858      * Get the length of the individual PM1 registers (enable and status).
0859      * Each register is defined to be (event block length / 2). Extra divide
0860      * by 8 converts bits to bytes.
0861      */
0862     Pm1RegisterByteWidth = (UINT8)
0863         ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth);
0864 
0865     /*
0866      * Calculate separate GAS structs for the PM1x (A/B) Status and Enable
0867      * registers. These addresses do not appear (directly) in the FADT, so it
0868      * is useful to pre-calculate them from the PM1 Event Block definitions.
0869      *
0870      * The PM event blocks are split into two register blocks, first is the
0871      * PM Status Register block, followed immediately by the PM Enable
0872      * Register block. Each is of length (Pm1EventLength/2)
0873      *
0874      * Note: The PM1A event block is required by the ACPI specification.
0875      * However, the PM1B event block is optional and is rarely, if ever,
0876      * used.
0877      */
0878 
0879     for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++)
0880     {
0881         Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT,
0882             FadtPmInfoTable[i].Source);
0883 
0884         if (Source64->Address)
0885         {
0886             AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target,
0887                 Source64->SpaceId, Pm1RegisterByteWidth,
0888                 Source64->Address +
0889                     (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth),
0890                 "PmRegisters", 0);
0891         }
0892     }
0893 }