📄 tbfadt.c
字号:
/* * Validate the FADT checksum before we copy the table. Ignore * checksum error as we want to try to get the DSDT and FACS. */ (void) AcpiTbVerifyChecksum (Table, Length); /* Obtain a local copy of the FADT in common ACPI 2.0+ format */ AcpiTbCreateLocalFadt (Table, Length); /* All done with the real FADT, unmap it */ AcpiOsUnmapMemory (Table, Length); /* Obtain the DSDT and FACS tables via their addresses within the FADT */ AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XDsdt, Flags, ACPI_SIG_DSDT, ACPI_TABLE_INDEX_DSDT); AcpiTbInstallTable ((ACPI_PHYSICAL_ADDRESS) AcpiGbl_FADT.XFacs, Flags, ACPI_SIG_FACS, ACPI_TABLE_INDEX_FACS);}/******************************************************************************* * * FUNCTION: AcpiTbCreateLocalFadt * * PARAMETERS: Table - Pointer to BIOS FADT * Length - Length of the table * * RETURN: None * * DESCRIPTION: Get a local copy of the FADT and convert it to a common format. * Performs validation on some important FADT fields. * * NOTE: We create a local copy of the FADT regardless of the version. * ******************************************************************************/voidAcpiTbCreateLocalFadt ( ACPI_TABLE_HEADER *Table, UINT32 Length){ /* * Check if the FADT is larger than the largest table that we expect * (the ACPI 2.0/3.0 version). If so, truncate the table, and issue * a warning. */ if (Length > sizeof (ACPI_TABLE_FADT)) { ACPI_WARNING ((AE_INFO, "FADT (revision %u) is longer than ACPI 2.0 version, truncating length 0x%X to 0x%X", Table->Revision, Length, sizeof (ACPI_TABLE_FADT))); } /* Clear the entire local FADT */ ACPI_MEMSET (&AcpiGbl_FADT, 0, sizeof (ACPI_TABLE_FADT)); /* Copy the original FADT, up to sizeof (ACPI_TABLE_FADT) */ ACPI_MEMCPY (&AcpiGbl_FADT, Table, ACPI_MIN (Length, sizeof (ACPI_TABLE_FADT))); /* * 1) Convert the local copy of the FADT to the common internal format * 2) Validate some of the important values within the FADT */ AcpiTbConvertFadt (); AcpiTbValidateFadt ();}/******************************************************************************* * * FUNCTION: AcpiTbConvertFadt * * PARAMETERS: None, uses AcpiGbl_FADT * * RETURN: None * * DESCRIPTION: Converts all versions of the FADT to a common internal format. * Expand all 32-bit addresses to 64-bit. * * NOTE: AcpiGbl_FADT must be of size (ACPI_TABLE_FADT), * and must contain a copy of the actual FADT. * * ACPICA will use the "X" fields of the FADT for all addresses. * * "X" fields are optional extensions to the original V1.0 fields. Even if * they are present in the structure, they can be optionally not used by * setting them to zero. Therefore, we must selectively expand V1.0 fields * if the corresponding X field is zero. * * For ACPI 1.0 FADTs, all address fields are expanded to the corresponding * "X" fields. * * For ACPI 2.0 FADTs, any "X" fields that are NULL are filled in by * expanding the corresponding ACPI 1.0 field. * ******************************************************************************/static voidAcpiTbConvertFadt ( void){ UINT8 Pm1RegisterLength; ACPI_GENERIC_ADDRESS *Target; ACPI_NATIVE_UINT i; /* Update the local FADT table header length */ AcpiGbl_FADT.Header.Length = sizeof (ACPI_TABLE_FADT); /* Expand the 32-bit FACS and DSDT addresses to 64-bit as necessary */ if (!AcpiGbl_FADT.XFacs) { AcpiGbl_FADT.XFacs = (UINT64) AcpiGbl_FADT.Facs; } if (!AcpiGbl_FADT.XDsdt) { AcpiGbl_FADT.XDsdt = (UINT64) AcpiGbl_FADT.Dsdt; } /* * For ACPI 1.0 FADTs (revision 1 or 2), ensure that reserved fields which * should be zero are indeed zero. This will workaround BIOSs that * inadvertently place values in these fields. * * The ACPI 1.0 reserved fields that will be zeroed are the bytes located at * offset 45, 55, 95, and the word located at offset 109, 110. */ if (AcpiGbl_FADT.Header.Revision < 3) { AcpiGbl_FADT.PreferredProfile = 0; AcpiGbl_FADT.PstateControl = 0; AcpiGbl_FADT.CstControl = 0; AcpiGbl_FADT.BootFlags = 0; } /* * Expand the ACPI 1.0 32-bit V1.0 addresses to the ACPI 2.0 64-bit "X" * generic address structures as necessary. */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { Target = ACPI_ADD_PTR ( ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, FadtInfoTable[i].Target); /* Expand only if the X target is null */ if (!Target->Address) { AcpiTbInitGenericAddress (Target, *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length), (UINT64) *ACPI_ADD_PTR (UINT32, &AcpiGbl_FADT, FadtInfoTable[i].Source)); } } /* * Calculate separate GAS structs for the PM1 Enable registers. * These addresses do not appear (directly) in the FADT, so it is * useful to calculate them once, here. * * The PM event blocks are split into two register blocks, first is the * PM Status Register block, followed immediately by the PM Enable Register * block. Each is of length (Pm1EventLength/2) */ Pm1RegisterLength = (UINT8) ACPI_DIV_2 (AcpiGbl_FADT.Pm1EventLength); /* The PM1A register block is required */ AcpiTbInitGenericAddress (&AcpiGbl_XPm1aEnable, Pm1RegisterLength, (AcpiGbl_FADT.XPm1aEventBlock.Address + Pm1RegisterLength)); /* The PM1B register block is optional, ignore if not present */ if (AcpiGbl_FADT.XPm1bEventBlock.Address) { AcpiTbInitGenericAddress (&AcpiGbl_XPm1bEnable, Pm1RegisterLength, (AcpiGbl_FADT.XPm1bEventBlock.Address + Pm1RegisterLength)); }}/****************************************************************************** * * FUNCTION: AcpiTbValidateFadt * * PARAMETERS: Table - Pointer to the FADT to be validated * * RETURN: None * * DESCRIPTION: Validate various important fields within the FADT. If a problem * is found, issue a message, but no status is returned. * Used by both the table manager and the disassembler. * * Possible additional checks: * (AcpiGbl_FADT.Pm1EventLength >= 4) * (AcpiGbl_FADT.Pm1ControlLength >= 2) * (AcpiGbl_FADT.PmTimerLength >= 4) * Gpe block lengths must be multiple of 2 * ******************************************************************************/static voidAcpiTbValidateFadt ( void){ UINT32 *Address32; ACPI_GENERIC_ADDRESS *Address64; UINT8 Length; ACPI_NATIVE_UINT i; /* Examine all of the 64-bit extended address fields (X fields) */ for (i = 0; i < ACPI_FADT_INFO_ENTRIES; i++) { /* Generate pointers to the 32-bit and 64-bit addresses and get the length */ Address64 = ACPI_ADD_PTR (ACPI_GENERIC_ADDRESS, &AcpiGbl_FADT, FadtInfoTable[i].Target); Address32 = ACPI_ADD_PTR (UINT32, &AcpiGbl_FADT, FadtInfoTable[i].Source); Length = *ACPI_ADD_PTR (UINT8, &AcpiGbl_FADT, FadtInfoTable[i].Length); if (FadtInfoTable[i].Type & ACPI_FADT_REQUIRED) { /* * Field is required (PM1aEvent, PM1aControl, PmTimer). * Both the address and length must be non-zero. */ if (!Address64->Address || !Length) { ACPI_ERROR ((AE_INFO, "Required field \"%s\" has zero address and/or length: %8.8X%8.8X/%X", FadtInfoTable[i].Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } else if (FadtInfoTable[i].Type & ACPI_FADT_SEPARATE_LENGTH) { /* * Field is optional (PM2Control, GPE0, GPE1) AND has its own * length field. If present, both the address and length must be valid. */ if ((Address64->Address && !Length) || (!Address64->Address && Length)) { ACPI_WARNING ((AE_INFO, "Optional field \"%s\" has zero address or length: %8.8X%8.8X/%X", FadtInfoTable[i].Name, ACPI_FORMAT_UINT64 (Address64->Address), Length)); } } /* If both 32- and 64-bit addresses are valid (non-zero), they must match */ if (Address64->Address && *Address32 && (Address64->Address != (UINT64) *Address32)) { ACPI_ERROR ((AE_INFO, "32/64X address mismatch in \"%s\": [%8.8X] [%8.8X%8.8X], using 64X", FadtInfoTable[i].Name, *Address32, ACPI_FORMAT_UINT64 (Address64->Address))); } }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -