1167802Sjkim/****************************************************************************** 2167802Sjkim * 3167802Sjkim * Module Name: tbfadt - FADT table utilities 4167802Sjkim * 5167802Sjkim *****************************************************************************/ 6167802Sjkim 7217365Sjkim/* 8306536Sjkim * Copyright (C) 2000 - 2016, Intel Corp. 9167802Sjkim * All rights reserved. 10167802Sjkim * 11217365Sjkim * Redistribution and use in source and binary forms, with or without 12217365Sjkim * modification, are permitted provided that the following conditions 13217365Sjkim * are met: 14217365Sjkim * 1. Redistributions of source code must retain the above copyright 15217365Sjkim * notice, this list of conditions, and the following disclaimer, 16217365Sjkim * without modification. 17217365Sjkim * 2. Redistributions in binary form must reproduce at minimum a disclaimer 18217365Sjkim * substantially similar to the "NO WARRANTY" disclaimer below 19217365Sjkim * ("Disclaimer") and any redistribution must be conditioned upon 20217365Sjkim * including a substantially similar Disclaimer requirement for further 21217365Sjkim * binary redistribution. 22217365Sjkim * 3. Neither the names of the above-listed copyright holders nor the names 23217365Sjkim * of any contributors may be used to endorse or promote products derived 24217365Sjkim * from this software without specific prior written permission. 25167802Sjkim * 26217365Sjkim * Alternatively, this software may be distributed under the terms of the 27217365Sjkim * GNU General Public License ("GPL") version 2 as published by the Free 28217365Sjkim * Software Foundation. 29167802Sjkim * 30217365Sjkim * NO WARRANTY 31217365Sjkim * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 32217365Sjkim * "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 33217365Sjkim * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTIBILITY AND FITNESS FOR 34217365Sjkim * A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT 35217365Sjkim * HOLDERS OR CONTRIBUTORS BE LIABLE FOR SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 36217365Sjkim * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 37217365Sjkim * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 38217365Sjkim * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, 39217365Sjkim * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING 40217365Sjkim * IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 41217365Sjkim * POSSIBILITY OF SUCH DAMAGES. 42217365Sjkim */ 43167802Sjkim 44193341Sjkim#include <contrib/dev/acpica/include/acpi.h> 45193341Sjkim#include <contrib/dev/acpica/include/accommon.h> 46193341Sjkim#include <contrib/dev/acpica/include/actables.h> 47167802Sjkim 48167802Sjkim#define _COMPONENT ACPI_TABLES 49167802Sjkim ACPI_MODULE_NAME ("tbfadt") 50167802Sjkim 51167802Sjkim/* Local prototypes */ 52167802Sjkim 53235945Sjkimstatic void 54167802SjkimAcpiTbInitGenericAddress ( 55167802Sjkim ACPI_GENERIC_ADDRESS *GenericAddress, 56193267Sjkim UINT8 SpaceId, 57193267Sjkim UINT8 ByteWidth, 58235945Sjkim UINT64 Address, 59306536Sjkim const char *RegisterName, 60281075Sdim UINT8 Flags); 61167802Sjkim 62167802Sjkimstatic void 63167802SjkimAcpiTbConvertFadt ( 64167802Sjkim void); 65167802Sjkim 66167802Sjkimstatic void 67193267SjkimAcpiTbSetupFadtRegisters ( 68193267Sjkim void); 69167802Sjkim 70281075Sdimstatic UINT64 71281075SdimAcpiTbSelectAddress ( 72281075Sdim char *RegisterName, 73281075Sdim UINT32 Address32, 74281075Sdim UINT64 Address64); 75193267Sjkim 76281075Sdim 77167802Sjkim/* Table for conversion of FADT to common internal format and FADT validation */ 78167802Sjkim 79167802Sjkimtypedef struct acpi_fadt_info 80167802Sjkim{ 81306536Sjkim const char *Name; 82229989Sjkim UINT16 Address64; 83229989Sjkim UINT16 Address32; 84229989Sjkim UINT16 Length; 85193267Sjkim UINT8 DefaultLength; 86281075Sdim UINT8 Flags; 87167802Sjkim 88167802Sjkim} ACPI_FADT_INFO; 89167802Sjkim 90229989Sjkim#define ACPI_FADT_OPTIONAL 0 91167802Sjkim#define ACPI_FADT_REQUIRED 1 92167802Sjkim#define ACPI_FADT_SEPARATE_LENGTH 2 93281075Sdim#define ACPI_FADT_GPE_REGISTER 4 94167802Sjkim 95167802Sjkimstatic ACPI_FADT_INFO FadtInfoTable[] = 96167802Sjkim{ 97193267Sjkim {"Pm1aEventBlock", 98193267Sjkim ACPI_FADT_OFFSET (XPm1aEventBlock), 99193267Sjkim ACPI_FADT_OFFSET (Pm1aEventBlock), 100193267Sjkim ACPI_FADT_OFFSET (Pm1EventLength), 101193267Sjkim ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ 102193267Sjkim ACPI_FADT_REQUIRED}, 103167802Sjkim 104193267Sjkim {"Pm1bEventBlock", 105193267Sjkim ACPI_FADT_OFFSET (XPm1bEventBlock), 106193267Sjkim ACPI_FADT_OFFSET (Pm1bEventBlock), 107193267Sjkim ACPI_FADT_OFFSET (Pm1EventLength), 108193267Sjkim ACPI_PM1_REGISTER_WIDTH * 2, /* Enable + Status register */ 109229989Sjkim ACPI_FADT_OPTIONAL}, 110167802Sjkim 111193267Sjkim {"Pm1aControlBlock", 112193267Sjkim ACPI_FADT_OFFSET (XPm1aControlBlock), 113193267Sjkim ACPI_FADT_OFFSET (Pm1aControlBlock), 114193267Sjkim ACPI_FADT_OFFSET (Pm1ControlLength), 115193267Sjkim ACPI_PM1_REGISTER_WIDTH, 116193267Sjkim ACPI_FADT_REQUIRED}, 117167802Sjkim 118193267Sjkim {"Pm1bControlBlock", 119193267Sjkim ACPI_FADT_OFFSET (XPm1bControlBlock), 120193267Sjkim ACPI_FADT_OFFSET (Pm1bControlBlock), 121193267Sjkim ACPI_FADT_OFFSET (Pm1ControlLength), 122193267Sjkim ACPI_PM1_REGISTER_WIDTH, 123229989Sjkim ACPI_FADT_OPTIONAL}, 124167802Sjkim 125193267Sjkim {"Pm2ControlBlock", 126193267Sjkim ACPI_FADT_OFFSET (XPm2ControlBlock), 127193267Sjkim ACPI_FADT_OFFSET (Pm2ControlBlock), 128193267Sjkim ACPI_FADT_OFFSET (Pm2ControlLength), 129193267Sjkim ACPI_PM2_REGISTER_WIDTH, 130193267Sjkim ACPI_FADT_SEPARATE_LENGTH}, 131167802Sjkim 132193267Sjkim {"PmTimerBlock", 133193267Sjkim ACPI_FADT_OFFSET (XPmTimerBlock), 134193267Sjkim ACPI_FADT_OFFSET (PmTimerBlock), 135193267Sjkim ACPI_FADT_OFFSET (PmTimerLength), 136193267Sjkim ACPI_PM_TIMER_WIDTH, 137253690Sjkim ACPI_FADT_SEPARATE_LENGTH}, /* ACPI 5.0A: Timer is optional */ 138167802Sjkim 139193267Sjkim {"Gpe0Block", 140193267Sjkim ACPI_FADT_OFFSET (XGpe0Block), 141193267Sjkim ACPI_FADT_OFFSET (Gpe0Block), 142193267Sjkim ACPI_FADT_OFFSET (Gpe0BlockLength), 143193267Sjkim 0, 144281075Sdim ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER}, 145167802Sjkim 146193267Sjkim {"Gpe1Block", 147193267Sjkim ACPI_FADT_OFFSET (XGpe1Block), 148193267Sjkim ACPI_FADT_OFFSET (Gpe1Block), 149193267Sjkim ACPI_FADT_OFFSET (Gpe1BlockLength), 150193267Sjkim 0, 151281075Sdim ACPI_FADT_SEPARATE_LENGTH | ACPI_FADT_GPE_REGISTER} 152167802Sjkim}; 153167802Sjkim 154193267Sjkim#define ACPI_FADT_INFO_ENTRIES \ 155193267Sjkim (sizeof (FadtInfoTable) / sizeof (ACPI_FADT_INFO)) 156167802Sjkim 157167802Sjkim 158193267Sjkim/* Table used to split Event Blocks into separate status/enable registers */ 159193267Sjkim 160193267Sjkimtypedef struct acpi_fadt_pm_info 161193267Sjkim{ 162193267Sjkim ACPI_GENERIC_ADDRESS *Target; 163229989Sjkim UINT16 Source; 164193267Sjkim UINT8 RegisterNum; 165193267Sjkim 166193267Sjkim} ACPI_FADT_PM_INFO; 167193267Sjkim 168193267Sjkimstatic ACPI_FADT_PM_INFO FadtPmInfoTable[] = 169193267Sjkim{ 170193267Sjkim {&AcpiGbl_XPm1aStatus, 171193267Sjkim ACPI_FADT_OFFSET (XPm1aEventBlock), 172193267Sjkim 0}, 173193267Sjkim 174193267Sjkim {&AcpiGbl_XPm1aEnable, 175193267Sjkim ACPI_FADT_OFFSET (XPm1aEventBlock), 176193267Sjkim 1}, 177193267Sjkim 178193267Sjkim {&AcpiGbl_XPm1bStatus, 179193267Sjkim ACPI_FADT_OFFSET (XPm1bEventBlock), 180193267Sjkim 0}, 181193267Sjkim 182193267Sjkim {&AcpiGbl_XPm1bEnable, 183193267Sjkim ACPI_FADT_OFFSET (XPm1bEventBlock), 184193267Sjkim 1} 185193267Sjkim}; 186193267Sjkim 187193267Sjkim#define ACPI_FADT_PM_INFO_ENTRIES \ 188193267Sjkim (sizeof (FadtPmInfoTable) / sizeof (ACPI_FADT_PM_INFO)) 189193267Sjkim 190193267Sjkim 191167802Sjkim/******************************************************************************* 192167802Sjkim * 193167802Sjkim * FUNCTION: AcpiTbInitGenericAddress 194167802Sjkim * 195167802Sjkim * PARAMETERS: GenericAddress - GAS struct to be initialized 196193267Sjkim * SpaceId - ACPI Space ID for this register 197238381Sjkim * ByteWidth - Width of this register 198167802Sjkim * Address - Address of the register 199281075Sdim * RegisterName - ASCII name of the ACPI register 200167802Sjkim * 201167802Sjkim * RETURN: None 202167802Sjkim * 203167802Sjkim * DESCRIPTION: Initialize a Generic Address Structure (GAS) 204167802Sjkim * See the ACPI specification for a full description and 205167802Sjkim * definition of this structure. 206167802Sjkim * 207167802Sjkim ******************************************************************************/ 208167802Sjkim 209235945Sjkimstatic void 210167802SjkimAcpiTbInitGenericAddress ( 211167802Sjkim ACPI_GENERIC_ADDRESS *GenericAddress, 212193267Sjkim UINT8 SpaceId, 213193267Sjkim UINT8 ByteWidth, 214235945Sjkim UINT64 Address, 215306536Sjkim const char *RegisterName, 216281075Sdim UINT8 Flags) 217167802Sjkim{ 218235945Sjkim UINT8 BitWidth; 219167802Sjkim 220235945Sjkim 221281075Sdim /* 222281075Sdim * Bit width field in the GAS is only one byte long, 255 max. 223281075Sdim * Check for BitWidth overflow in GAS. 224281075Sdim */ 225235945Sjkim BitWidth = (UINT8) (ByteWidth * 8); 226281075Sdim if (ByteWidth > 31) /* (31*8)=248, (32*8)=256 */ 227235945Sjkim { 228281075Sdim /* 229281075Sdim * No error for GPE blocks, because we do not use the BitWidth 230281075Sdim * for GPEs, the legacy length (ByteWidth) is used instead to 231281075Sdim * allow for a large number of GPEs. 232281075Sdim */ 233281075Sdim if (!(Flags & ACPI_FADT_GPE_REGISTER)) 234281075Sdim { 235281075Sdim ACPI_ERROR ((AE_INFO, 236281075Sdim "%s - 32-bit FADT register is too long (%u bytes, %u bits) " 237281075Sdim "to convert to GAS struct - 255 bits max, truncating", 238281075Sdim RegisterName, ByteWidth, (ByteWidth * 8))); 239281075Sdim } 240235945Sjkim 241235945Sjkim BitWidth = 255; 242235945Sjkim } 243235945Sjkim 244167802Sjkim /* 245167802Sjkim * The 64-bit Address field is non-aligned in the byte packed 246167802Sjkim * GAS struct. 247167802Sjkim */ 248167802Sjkim ACPI_MOVE_64_TO_64 (&GenericAddress->Address, &Address); 249167802Sjkim 250167802Sjkim /* All other fields are byte-wide */ 251167802Sjkim 252193267Sjkim GenericAddress->SpaceId = SpaceId; 253235945Sjkim GenericAddress->BitWidth = BitWidth; 254167802Sjkim GenericAddress->BitOffset = 0; 255193267Sjkim GenericAddress->AccessWidth = 0; /* Access width ANY */ 256167802Sjkim} 257167802Sjkim 258167802Sjkim 259167802Sjkim/******************************************************************************* 260167802Sjkim * 261281075Sdim * FUNCTION: AcpiTbSelectAddress 262281075Sdim * 263281075Sdim * PARAMETERS: RegisterName - ASCII name of the ACPI register 264281075Sdim * Address32 - 32-bit address of the register 265281075Sdim * Address64 - 64-bit address of the register 266281075Sdim * 267281075Sdim * RETURN: The resolved 64-bit address 268281075Sdim * 269281075Sdim * DESCRIPTION: Select between 32-bit and 64-bit versions of addresses within 270281075Sdim * the FADT. Used for the FACS and DSDT addresses. 271281075Sdim * 272281075Sdim * NOTES: 273281075Sdim * 274281075Sdim * Check for FACS and DSDT address mismatches. An address mismatch between 275281075Sdim * the 32-bit and 64-bit address fields (FIRMWARE_CTRL/X_FIRMWARE_CTRL and 276281075Sdim * DSDT/X_DSDT) could be a corrupted address field or it might indicate 277281075Sdim * the presence of two FACS or two DSDT tables. 278281075Sdim * 279281075Sdim * November 2013: 280281075Sdim * By default, as per the ACPICA specification, a valid 64-bit address is 281281075Sdim * used regardless of the value of the 32-bit address. However, this 282281075Sdim * behavior can be overridden via the AcpiGbl_Use32BitFadtAddresses flag. 283281075Sdim * 284281075Sdim ******************************************************************************/ 285281075Sdim 286281075Sdimstatic UINT64 287281075SdimAcpiTbSelectAddress ( 288281075Sdim char *RegisterName, 289281075Sdim UINT32 Address32, 290281075Sdim UINT64 Address64) 291281075Sdim{ 292281075Sdim 293281075Sdim if (!Address64) 294281075Sdim { 295281075Sdim /* 64-bit address is zero, use 32-bit address */ 296281075Sdim 297281075Sdim return ((UINT64) Address32); 298281075Sdim } 299281075Sdim 300281075Sdim if (Address32 && 301281075Sdim (Address64 != (UINT64) Address32)) 302281075Sdim { 303281075Sdim /* Address mismatch between 32-bit and 64-bit versions */ 304281075Sdim 305281075Sdim ACPI_BIOS_WARNING ((AE_INFO, 306281075Sdim "32/64X %s address mismatch in FADT: " 307281075Sdim "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", 308281075Sdim RegisterName, Address32, ACPI_FORMAT_UINT64 (Address64), 309281075Sdim AcpiGbl_Use32BitFadtAddresses ? 32 : 64)); 310281075Sdim 311281075Sdim /* 32-bit address override */ 312281075Sdim 313281075Sdim if (AcpiGbl_Use32BitFadtAddresses) 314281075Sdim { 315281075Sdim return ((UINT64) Address32); 316281075Sdim } 317281075Sdim } 318281075Sdim 319281075Sdim /* Default is to use the 64-bit address */ 320281075Sdim 321281075Sdim return (Address64); 322281075Sdim} 323281075Sdim 324281075Sdim 325281075Sdim/******************************************************************************* 326281075Sdim * 327167802Sjkim * FUNCTION: AcpiTbParseFadt 328167802Sjkim * 329306536Sjkim * PARAMETERS: None 330167802Sjkim * 331167802Sjkim * RETURN: None 332167802Sjkim * 333167802Sjkim * DESCRIPTION: Initialize the FADT, DSDT and FACS tables 334167802Sjkim * (FADT contains the addresses of the DSDT and FACS) 335167802Sjkim * 336167802Sjkim ******************************************************************************/ 337167802Sjkim 338167802Sjkimvoid 339167802SjkimAcpiTbParseFadt ( 340306536Sjkim void) 341167802Sjkim{ 342167802Sjkim UINT32 Length; 343167802Sjkim ACPI_TABLE_HEADER *Table; 344167802Sjkim 345167802Sjkim 346167802Sjkim /* 347167802Sjkim * The FADT has multiple versions with different lengths, 348167802Sjkim * and it contains pointers to both the DSDT and FACS tables. 349167802Sjkim * 350167802Sjkim * Get a local copy of the FADT and convert it to a common format 351167802Sjkim * Map entire FADT, assumed to be smaller than one page. 352167802Sjkim */ 353306536Sjkim Length = AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Length; 354167802Sjkim 355167802Sjkim Table = AcpiOsMapMemory ( 356306536Sjkim AcpiGbl_RootTableList.Tables[AcpiGbl_FadtIndex].Address, Length); 357167802Sjkim if (!Table) 358167802Sjkim { 359167802Sjkim return; 360167802Sjkim } 361167802Sjkim 362167802Sjkim /* 363167802Sjkim * Validate the FADT checksum before we copy the table. Ignore 364167802Sjkim * checksum error as we want to try to get the DSDT and FACS. 365167802Sjkim */ 366167802Sjkim (void) AcpiTbVerifyChecksum (Table, Length); 367167802Sjkim 368193267Sjkim /* Create a local copy of the FADT in common ACPI 2.0+ format */ 369167802Sjkim 370167802Sjkim AcpiTbCreateLocalFadt (Table, Length); 371167802Sjkim 372167802Sjkim /* All done with the real FADT, unmap it */ 373167802Sjkim 374167802Sjkim AcpiOsUnmapMemory (Table, Length); 375167802Sjkim 376167802Sjkim /* Obtain the DSDT and FACS tables via their addresses within the FADT */ 377167802Sjkim 378281075Sdim AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, 379306536Sjkim ACPI_SIG_DSDT, &AcpiGbl_DsdtIndex); 380167802Sjkim 381228110Sjkim /* If Hardware Reduced flag is set, there is no FACS */ 382228110Sjkim 383228110Sjkim if (!AcpiGbl_ReducedHardware) 384228110Sjkim { 385306536Sjkim if (AcpiGbl_FADT.Facs) 386306536Sjkim { 387306536Sjkim AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.Facs, 388306536Sjkim ACPI_SIG_FACS, &AcpiGbl_FacsIndex); 389306536Sjkim } 390306536Sjkim if (AcpiGbl_FADT.XFacs) 391306536Sjkim { 392306536Sjkim AcpiTbInstallFixedTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, 393306536Sjkim ACPI_SIG_FACS, &AcpiGbl_XFacsIndex); 394306536Sjkim } 395228110Sjkim } 396167802Sjkim} 397167802Sjkim 398167802Sjkim 399167802Sjkim/******************************************************************************* 400167802Sjkim * 401167802Sjkim * FUNCTION: AcpiTbCreateLocalFadt 402167802Sjkim * 403167802Sjkim * PARAMETERS: Table - Pointer to BIOS FADT 404167802Sjkim * Length - Length of the table 405167802Sjkim * 406167802Sjkim * RETURN: None 407167802Sjkim * 408167802Sjkim * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. 409167802Sjkim * Performs validation on some important FADT fields. 410167802Sjkim * 411193267Sjkim * NOTE: We create a local copy of the FADT regardless of the version. 412193267Sjkim * 413167802Sjkim ******************************************************************************/ 414167802Sjkim 415167802Sjkimvoid 416167802SjkimAcpiTbCreateLocalFadt ( 417167802Sjkim ACPI_TABLE_HEADER *Table, 418167802Sjkim UINT32 Length) 419167802Sjkim{ 420167802Sjkim 421167802Sjkim /* 422193267Sjkim * Check if the FADT is larger than the largest table that we expect 423306536Sjkim * (typically the current ACPI specification version). If so, truncate 424306536Sjkim * the table, and issue a warning. 425167802Sjkim */ 426167802Sjkim if (Length > sizeof (ACPI_TABLE_FADT)) 427167802Sjkim { 428238381Sjkim ACPI_BIOS_WARNING ((AE_INFO, 429306536Sjkim "FADT (revision %u) is longer than %s length, " 430204773Sjkim "truncating length %u to %u", 431306536Sjkim Table->Revision, ACPI_FADT_CONFORMANCE, Length, 432306536Sjkim (UINT32) sizeof (ACPI_TABLE_FADT))); 433167802Sjkim } 434167802Sjkim 435193267Sjkim /* Clear the entire local FADT */ 436167802Sjkim 437306536Sjkim memset (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); 438167802Sjkim 439193267Sjkim /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */ 440193267Sjkim 441306536Sjkim memcpy (&AcpiGbl_FADT, Table, 442167802Sjkim ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT))); 443167802Sjkim 444228110Sjkim /* Take a copy of the Hardware Reduced flag */ 445228110Sjkim 446228110Sjkim AcpiGbl_ReducedHardware = FALSE; 447228110Sjkim if (AcpiGbl_FADT.Flags & ACPI_FADT_HW_REDUCED) 448228110Sjkim { 449228110Sjkim AcpiGbl_ReducedHardware = TRUE; 450228110Sjkim } 451228110Sjkim 452193267Sjkim /* Convert the local copy of the FADT to the common internal format */ 453193267Sjkim 454167802Sjkim AcpiTbConvertFadt (); 455193267Sjkim 456193267Sjkim /* Initialize the global ACPI register structures */ 457193267Sjkim 458193267Sjkim AcpiTbSetupFadtRegisters (); 459167802Sjkim} 460167802Sjkim 461167802Sjkim 462167802Sjkim/******************************************************************************* 463167802Sjkim * 464167802Sjkim * FUNCTION: AcpiTbConvertFadt 465167802Sjkim * 466281075Sdim * PARAMETERS: None - AcpiGbl_FADT is used. 467167802Sjkim * 468167802Sjkim * RETURN: None 469167802Sjkim * 470167802Sjkim * DESCRIPTION: Converts all versions of the FADT to a common internal format. 471281075Sdim * Expand 32-bit addresses to 64-bit as necessary. Also validate 472281075Sdim * important fields within the FADT. 473167802Sjkim * 474281075Sdim * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), and must 475281075Sdim * contain a copy of the actual BIOS-provided FADT. 476167802Sjkim * 477193267Sjkim * Notes on 64-bit register addresses: 478167802Sjkim * 479193267Sjkim * After this FADT conversion, later ACPICA code will only use the 64-bit "X" 480193267Sjkim * fields of the FADT for all ACPI register addresses. 481167802Sjkim * 482281075Sdim * The 64-bit X fields are optional extensions to the original 32-bit FADT 483193267Sjkim * V1.0 fields. Even if they are present in the FADT, they are optional and 484193267Sjkim * are unused if the BIOS sets them to zero. Therefore, we must copy/expand 485281075Sdim * 32-bit V1.0 fields to the 64-bit X fields if the the 64-bit X field is 486281075Sdim * originally zero. 487167802Sjkim * 488281075Sdim * For ACPI 1.0 FADTs (that contain no 64-bit addresses), all 32-bit address 489281075Sdim * fields are expanded to the corresponding 64-bit X fields in the internal 490281075Sdim * common FADT. 491167802Sjkim * 492193267Sjkim * For ACPI 2.0+ FADTs, all valid (non-zero) 32-bit address fields are expanded 493281075Sdim * to the corresponding 64-bit X fields, if the 64-bit field is originally 494281075Sdim * zero. Adhering to the ACPI specification, we completely ignore the 32-bit 495281075Sdim * field if the 64-bit field is valid, regardless of whether the host OS is 496281075Sdim * 32-bit or 64-bit. 497193267Sjkim * 498281075Sdim * Possible additional checks: 499281075Sdim * (AcpiGbl_FADT.Pm1EventLength >= 4) 500281075Sdim * (AcpiGbl_FADT.Pm1ControlLength >= 2) 501281075Sdim * (AcpiGbl_FADT.PmTimerLength >= 4) 502281075Sdim * Gpe block lengths must be multiple of 2 503281075Sdim * 504167802Sjkim ******************************************************************************/ 505167802Sjkim 506167802Sjkimstatic void 507167802SjkimAcpiTbConvertFadt ( 508167802Sjkim void) 509167802Sjkim{ 510306536Sjkim const char *Name; 511193267Sjkim ACPI_GENERIC_ADDRESS *Address64; 512193267Sjkim UINT32 Address32; 513281075Sdim UINT8 Length; 514281075Sdim UINT8 Flags; 515193267Sjkim UINT32 i; 516167802Sjkim 517167802Sjkim 518193267Sjkim /* 519193267Sjkim * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which 520193267Sjkim * should be zero are indeed zero. This will workaround BIOSs that 521193267Sjkim * inadvertently place values in these fields. 522193267Sjkim * 523193267Sjkim * The ACPI 1.0 reserved fields that will be zeroed are the bytes located 524193267Sjkim * at offset 45, 55, 95, and the word located at offset 109, 110. 525218590Sjkim * 526218590Sjkim * Note: The FADT revision value is unreliable. Only the length can be 527218590Sjkim * trusted. 528167802Sjkim */ 529218590Sjkim if (AcpiGbl_FADT.Header.Length <= ACPI_FADT_V2_SIZE) 530167802Sjkim { 531193267Sjkim AcpiGbl_FADT.PreferredProfile = 0; 532193267Sjkim AcpiGbl_FADT.PstateControl = 0; 533193267Sjkim AcpiGbl_FADT.CstControl = 0; 534193267Sjkim AcpiGbl_FADT.BootFlags = 0; 535167802Sjkim } 536167802Sjkim 537167802Sjkim /* 538233250Sjkim * Now we can update the local FADT length to the length of the 539233250Sjkim * current FADT version as defined by the ACPI specification. 540233250Sjkim * Thus, we will have a common FADT internally. 541233250Sjkim */ 542233250Sjkim AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); 543233250Sjkim 544233250Sjkim /* 545306536Sjkim * Expand the 32-bit DSDT addresses to 64-bit as necessary. 546281075Sdim * Later ACPICA code will always use the X 64-bit field. 547167802Sjkim */ 548281075Sdim AcpiGbl_FADT.XDsdt = AcpiTbSelectAddress ("DSDT", 549281075Sdim AcpiGbl_FADT.Dsdt, AcpiGbl_FADT.XDsdt); 550167802Sjkim 551228110Sjkim /* If Hardware Reduced flag is set, we are all done */ 552228110Sjkim 553228110Sjkim if (AcpiGbl_ReducedHardware) 554228110Sjkim { 555228110Sjkim return; 556228110Sjkim } 557228110Sjkim 558167802Sjkim /* Examine all of the 64-bit extended address fields (X fields) */ 559167802Sjkim 560167802Sjkim for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) 561167802Sjkim { 562193267Sjkim /* 563281075Sdim * Get the 32-bit and 64-bit addresses, as well as the register 564281075Sdim * length and register name. 565193267Sjkim */ 566281075Sdim Address32 = *ACPI_ADD_PTR (UINT32, 567281075Sdim &AcpiGbl_FADT, FadtInfoTable[i].Address32); 568281075Sdim 569193267Sjkim Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, 570281075Sdim &AcpiGbl_FADT, FadtInfoTable[i].Address64); 571281075Sdim 572193267Sjkim Length = *ACPI_ADD_PTR (UINT8, 573281075Sdim &AcpiGbl_FADT, FadtInfoTable[i].Length); 574281075Sdim 575193267Sjkim Name = FadtInfoTable[i].Name; 576281075Sdim Flags = FadtInfoTable[i].Flags; 577167802Sjkim 578193267Sjkim /* 579281075Sdim * Expand the ACPI 1.0 32-bit addresses to the ACPI 2.0 64-bit "X" 580281075Sdim * generic address structures as necessary. Later code will always use 581281075Sdim * the 64-bit address structures. 582281075Sdim * 583281075Sdim * November 2013: 584281075Sdim * Now always use the 64-bit address if it is valid (non-zero), in 585281075Sdim * accordance with the ACPI specification which states that a 64-bit 586281075Sdim * address supersedes the 32-bit version. This behavior can be 587281075Sdim * overridden by the AcpiGbl_Use32BitFadtAddresses flag. 588281075Sdim * 589281075Sdim * During 64-bit address construction and verification, 590281075Sdim * these cases are handled: 591281075Sdim * 592281075Sdim * Address32 zero, Address64 [don't care] - Use Address64 593281075Sdim * 594281075Sdim * Address32 non-zero, Address64 zero - Copy/use Address32 595281075Sdim * Address32 non-zero == Address64 non-zero - Use Address64 596281075Sdim * Address32 non-zero != Address64 non-zero - Warning, use Address64 597281075Sdim * 598281075Sdim * Override: if AcpiGbl_Use32BitFadtAddresses is TRUE, and: 599281075Sdim * Address32 non-zero != Address64 non-zero - Warning, copy/use Address32 600281075Sdim * 601281075Sdim * Note: SpaceId is always I/O for 32-bit legacy address fields 602281075Sdim */ 603281075Sdim if (Address32) 604281075Sdim { 605281075Sdim if (!Address64->Address) 606281075Sdim { 607281075Sdim /* 64-bit address is zero, use 32-bit address */ 608281075Sdim 609281075Sdim AcpiTbInitGenericAddress (Address64, 610281075Sdim ACPI_ADR_SPACE_SYSTEM_IO, 611281075Sdim *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, 612281075Sdim FadtInfoTable[i].Length), 613281075Sdim (UINT64) Address32, Name, Flags); 614281075Sdim } 615281075Sdim else if (Address64->Address != (UINT64) Address32) 616281075Sdim { 617281075Sdim /* Address mismatch */ 618281075Sdim 619281075Sdim ACPI_BIOS_WARNING ((AE_INFO, 620281075Sdim "32/64X address mismatch in FADT/%s: " 621281075Sdim "0x%8.8X/0x%8.8X%8.8X, using %u-bit address", 622281075Sdim Name, Address32, 623281075Sdim ACPI_FORMAT_UINT64 (Address64->Address), 624281075Sdim AcpiGbl_Use32BitFadtAddresses ? 32 : 64)); 625281075Sdim 626281075Sdim if (AcpiGbl_Use32BitFadtAddresses) 627281075Sdim { 628281075Sdim /* 32-bit address override */ 629281075Sdim 630281075Sdim AcpiTbInitGenericAddress (Address64, 631281075Sdim ACPI_ADR_SPACE_SYSTEM_IO, 632281075Sdim *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, 633281075Sdim FadtInfoTable[i].Length), 634281075Sdim (UINT64) Address32, Name, Flags); 635281075Sdim } 636281075Sdim } 637281075Sdim } 638281075Sdim 639281075Sdim /* 640193267Sjkim * For each extended field, check for length mismatch between the 641193267Sjkim * legacy length field and the corresponding 64-bit X length field. 642249112Sjkim * Note: If the legacy length field is > 0xFF bits, ignore this 643249112Sjkim * check. (GPE registers can be larger than the 64-bit GAS structure 644249112Sjkim * can accomodate, 0xFF bits). 645193267Sjkim */ 646193267Sjkim if (Address64->Address && 647249112Sjkim (ACPI_MUL_8 (Length) <= ACPI_UINT8_MAX) && 648193267Sjkim (Address64->BitWidth != ACPI_MUL_8 (Length))) 649193267Sjkim { 650238381Sjkim ACPI_BIOS_WARNING ((AE_INFO, 651238381Sjkim "32/64X length mismatch in FADT/%s: %u/%u", 652193267Sjkim Name, ACPI_MUL_8 (Length), Address64->BitWidth)); 653193267Sjkim } 654167802Sjkim 655281075Sdim if (FadtInfoTable[i].Flags & ACPI_FADT_REQUIRED) 656167802Sjkim { 657167802Sjkim /* 658253690Sjkim * Field is required (PM1aEvent, PM1aControl). 659167802Sjkim * Both the address and length must be non-zero. 660167802Sjkim */ 661167802Sjkim if (!Address64->Address || !Length) 662167802Sjkim { 663238381Sjkim ACPI_BIOS_ERROR ((AE_INFO, 664238381Sjkim "Required FADT field %s has zero address and/or length: " 665238381Sjkim "0x%8.8X%8.8X/0x%X", 666193267Sjkim Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); 667167802Sjkim } 668167802Sjkim } 669281075Sdim else if (FadtInfoTable[i].Flags & ACPI_FADT_SEPARATE_LENGTH) 670167802Sjkim { 671167802Sjkim /* 672167802Sjkim * Field is optional (PM2Control, GPE0, GPE1) AND has its own 673193267Sjkim * length field. If present, both the address and length must 674193267Sjkim * be valid. 675167802Sjkim */ 676193267Sjkim if ((Address64->Address && !Length) || 677193267Sjkim (!Address64->Address && Length)) 678167802Sjkim { 679238381Sjkim ACPI_BIOS_WARNING ((AE_INFO, 680306536Sjkim "Optional FADT field %s has valid %s but zero %s: " 681306536Sjkim "0x%8.8X%8.8X/0x%X", Name, 682306536Sjkim (Length ? "Length" : "Address"), 683306536Sjkim (Length ? "Address": "Length"), 684306536Sjkim ACPI_FORMAT_UINT64 (Address64->Address), Length)); 685167802Sjkim } 686167802Sjkim } 687193267Sjkim } 688193267Sjkim} 689167802Sjkim 690167802Sjkim 691193267Sjkim/******************************************************************************* 692193267Sjkim * 693193267Sjkim * FUNCTION: AcpiTbSetupFadtRegisters 694193267Sjkim * 695193267Sjkim * PARAMETERS: None, uses AcpiGbl_FADT. 696193267Sjkim * 697193267Sjkim * RETURN: None 698193267Sjkim * 699193267Sjkim * DESCRIPTION: Initialize global ACPI PM1 register definitions. Optionally, 700193267Sjkim * force FADT register definitions to their default lengths. 701193267Sjkim * 702193267Sjkim ******************************************************************************/ 703193267Sjkim 704193267Sjkimstatic void 705193267SjkimAcpiTbSetupFadtRegisters ( 706193267Sjkim void) 707193267Sjkim{ 708193267Sjkim ACPI_GENERIC_ADDRESS *Target64; 709193267Sjkim ACPI_GENERIC_ADDRESS *Source64; 710193267Sjkim UINT8 Pm1RegisterByteWidth; 711193267Sjkim UINT32 i; 712193267Sjkim 713193267Sjkim 714193267Sjkim /* 715193267Sjkim * Optionally check all register lengths against the default values and 716193267Sjkim * update them if they are incorrect. 717193267Sjkim */ 718193267Sjkim if (AcpiGbl_UseDefaultRegisterWidths) 719193267Sjkim { 720193267Sjkim for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) 721167802Sjkim { 722193267Sjkim Target64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, 723193267Sjkim FadtInfoTable[i].Address64); 724193267Sjkim 725193267Sjkim /* 726193267Sjkim * If a valid register (Address != 0) and the (DefaultLength > 0) 727193267Sjkim * (Not a GPE register), then check the width against the default. 728193267Sjkim */ 729193267Sjkim if ((Target64->Address) && 730193267Sjkim (FadtInfoTable[i].DefaultLength > 0) && 731193267Sjkim (FadtInfoTable[i].DefaultLength != Target64->BitWidth)) 732193267Sjkim { 733238381Sjkim ACPI_BIOS_WARNING ((AE_INFO, 734238381Sjkim "Invalid length for FADT/%s: %u, using default %u", 735193267Sjkim FadtInfoTable[i].Name, Target64->BitWidth, 736193267Sjkim FadtInfoTable[i].DefaultLength)); 737193267Sjkim 738193267Sjkim /* Incorrect size, set width to the default */ 739193267Sjkim 740193267Sjkim Target64->BitWidth = FadtInfoTable[i].DefaultLength; 741193267Sjkim } 742167802Sjkim } 743167802Sjkim } 744193267Sjkim 745193267Sjkim /* 746193267Sjkim * Get the length of the individual PM1 registers (enable and status). 747193267Sjkim * Each register is defined to be (event block length / 2). Extra divide 748193267Sjkim * by 8 converts bits to bytes. 749193267Sjkim */ 750193267Sjkim Pm1RegisterByteWidth = (UINT8) 751193267Sjkim ACPI_DIV_16 (AcpiGbl_FADT.XPm1aEventBlock.BitWidth); 752193267Sjkim 753193267Sjkim /* 754193267Sjkim * Calculate separate GAS structs for the PM1x (A/B) Status and Enable 755193267Sjkim * registers. These addresses do not appear (directly) in the FADT, so it 756193267Sjkim * is useful to pre-calculate them from the PM1 Event Block definitions. 757193267Sjkim * 758193267Sjkim * The PM event blocks are split into two register blocks, first is the 759193267Sjkim * PM Status Register block, followed immediately by the PM Enable 760193267Sjkim * Register block. Each is of length (Pm1EventLength/2) 761193267Sjkim * 762193267Sjkim * Note: The PM1A event block is required by the ACPI specification. 763193267Sjkim * However, the PM1B event block is optional and is rarely, if ever, 764193267Sjkim * used. 765193267Sjkim */ 766193267Sjkim 767193267Sjkim for (i = 0; i < ACPI_FADT_PM_INFO_ENTRIES; i++) 768193267Sjkim { 769193267Sjkim Source64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, 770193267Sjkim FadtPmInfoTable[i].Source); 771193267Sjkim 772193267Sjkim if (Source64->Address) 773193267Sjkim { 774193267Sjkim AcpiTbInitGenericAddress (FadtPmInfoTable[i].Target, 775193267Sjkim Source64->SpaceId, Pm1RegisterByteWidth, 776193267Sjkim Source64->Address + 777235945Sjkim (FadtPmInfoTable[i].RegisterNum * Pm1RegisterByteWidth), 778281075Sdim "PmRegisters", 0); 779193267Sjkim } 780193267Sjkim } 781167802Sjkim} 782