You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
1555 lines
39 KiB
1555 lines
39 KiB
/*++
|
|
|
|
Copyright (c) 1997 Microsoft Corporation
|
|
All rights reserved
|
|
|
|
Module Name:
|
|
|
|
acpisetd.c
|
|
|
|
Abstract:
|
|
|
|
This module detects an ACPI system. It
|
|
is included into setup so that setup
|
|
can figure out which HAL to load
|
|
|
|
Author:
|
|
|
|
Jake Oshins (jakeo) - Feb. 7, 1997.
|
|
|
|
Environment:
|
|
|
|
Textmode setup.
|
|
|
|
Revision History:
|
|
|
|
|
|
--*/
|
|
VOID
|
|
BlPrint(
|
|
PCHAR cp,
|
|
...
|
|
);
|
|
|
|
ULONG
|
|
SlGetChar(
|
|
VOID
|
|
);
|
|
|
|
VOID
|
|
SlPrint(
|
|
IN PCHAR FormatString,
|
|
...
|
|
);
|
|
|
|
#define HalpBiosDbgPrint(_x_) if (HalpGoodBiosDebug) {SlPrint _x_; }
|
|
#define HalpGoodBiosPause() if (HalpGoodBiosDebug) {SlGetChar();}
|
|
|
|
|
|
#ifdef DEBUG
|
|
#undef DEBUG_PRINT
|
|
#define DEBUG_PRINT BlPrint
|
|
#else
|
|
#define DEBUG_PRINT
|
|
#endif
|
|
|
|
typedef struct _ACPI_BIOS_INSTALLATION_CHECK {
|
|
UCHAR Signature[8]; // "RSD PTR" (ascii)
|
|
UCHAR Checksum;
|
|
UCHAR OemId[6]; // An OEM-supplied string
|
|
UCHAR reserved; // must be 0
|
|
ULONG RsdtAddress; // 32-bit physical address of RSDT
|
|
} ACPI_BIOS_INSTALLATION_CHECK, *PACPI_BIOS_INSTALLATION_CHECK;
|
|
|
|
#include "acpitabl.h"
|
|
#include "halp.h"
|
|
|
|
typedef
|
|
BOOLEAN
|
|
(* PFN_RULE)(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
);
|
|
|
|
extern BOOLEAN DisableACPI;
|
|
|
|
BOOLEAN MatchAcpiOemIdRule(PCHAR Section, ULONG KeyIndex);
|
|
BOOLEAN MatchAcpiOemTableIdRule(PCHAR Section, ULONG KeyIndex);
|
|
BOOLEAN MatchAcpiOemRevisionRule(PCHAR Section, ULONG KeyIndex);
|
|
BOOLEAN MatchAcpiRevisionRule(PCHAR Section, ULONG KeyIndex);
|
|
BOOLEAN MatchAcpiCreatorRevisionRule(PCHAR Section, ULONG KeyIndex);
|
|
BOOLEAN MatchAcpiCreatorIdRule(PCHAR Section, ULONG KeyIndex);
|
|
|
|
typedef struct _INF_RULE {
|
|
PCHAR szRule;
|
|
PFN_RULE pRule;
|
|
} INF_RULE, *PINF_RULE;
|
|
|
|
INF_RULE InfRule[] =
|
|
{
|
|
{"AcpiOemId", MatchAcpiOemIdRule},
|
|
{"AcpiOemTableId", MatchAcpiOemTableIdRule},
|
|
{"AcpiOemRevision", MatchAcpiOemRevisionRule},
|
|
{"AcpiRevision", MatchAcpiRevisionRule},
|
|
{"AcpiCreatorRevision", MatchAcpiCreatorRevisionRule},
|
|
{"AcpiCreatorId", MatchAcpiCreatorIdRule},
|
|
{NULL, NULL}
|
|
};
|
|
|
|
ULONG
|
|
DetectMPACPI (
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
);
|
|
|
|
ULONG
|
|
DetectApicACPI (
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
);
|
|
|
|
ULONG
|
|
DetectPicACPI (
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
);
|
|
|
|
VOID
|
|
HalpFindRsdp (
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpValidateRsdp(
|
|
VOID
|
|
);
|
|
|
|
PVOID
|
|
HalpFindApic (
|
|
VOID
|
|
);
|
|
|
|
ULONG
|
|
HalpAcpiNumProcessors(
|
|
VOID
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpMatchInfList(
|
|
IN PCHAR Section
|
|
);
|
|
|
|
BOOLEAN
|
|
HalpMatchDescription(
|
|
PCHAR Section
|
|
);
|
|
|
|
PRSDP HalpRsdp = NULL;
|
|
PRSDT HalpRsdt = NULL;
|
|
PXSDT HalpXsdt = NULL;
|
|
BOOLEAN HalpSearchedForRsdp = FALSE;
|
|
PVOID HalpApic = NULL;
|
|
BOOLEAN HalpSearchedForApic = FALSE;
|
|
|
|
BOOLEAN HalpGoodBiosDebug = FALSE;
|
|
|
|
// from boot\detect\i386\acpibios.h
|
|
//
|
|
// Acpi BIOS Installation check
|
|
//
|
|
#define ACPI_BIOS_START 0xE0000
|
|
#define ACPI_BIOS_END 0xFFFFF
|
|
#define ACPI_BIOS_HEADER_INCREMENT 16
|
|
|
|
#ifndef SETUP
|
|
|
|
#ifdef ALLOC_PRAGMA
|
|
#pragma alloc_text(INIT,DetectMPACPI)
|
|
#pragma alloc_text(INIT,DetectApicACPI)
|
|
#pragma alloc_text(INIT,DetectPicACPI)
|
|
#endif // ALLOC_PRAGMA
|
|
#endif // SETUP
|
|
|
|
|
|
ULONG
|
|
DetectMPACPI(
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
)
|
|
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function looks for an ACPI Root System Description
|
|
table in the BIOS. If it exists, this is an ACPI machine.
|
|
|
|
Arguments:
|
|
|
|
IsConfiguredMp - TRUE if this machine is a MP instance of the ACPI spec, else FALSE.
|
|
|
|
Return Value:
|
|
0 - if not a ACPI
|
|
1 - if ACPI
|
|
|
|
*/
|
|
{
|
|
|
|
*IsConfiguredMp = FALSE;
|
|
|
|
DEBUG_PRINT("DetectMPACPI\n");
|
|
|
|
//
|
|
// Detect whether this is an ACPI machine.
|
|
//
|
|
if (HalpSearchedForRsdp == FALSE) {
|
|
PCHAR AcpiDebug;
|
|
|
|
//
|
|
// Check whether ACPI detection debugging is enabled
|
|
//
|
|
if ( InfFile ) {
|
|
AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
|
|
if (AcpiDebug[0] == '1') {
|
|
HalpGoodBiosDebug = TRUE;
|
|
SlPrint("Enabling GOOD BIOS DEBUG\n");
|
|
SlGetChar();
|
|
}
|
|
}
|
|
|
|
HalpFindRsdp();
|
|
|
|
HalpSearchedForRsdp = TRUE;
|
|
}
|
|
|
|
if (!HalpValidateRsdp()) {
|
|
return(FALSE);
|
|
}
|
|
|
|
DEBUG_PRINT("Found Rsdp: %x\n", HalpRsdp);
|
|
|
|
if (HalpSearchedForApic == FALSE) {
|
|
|
|
HalpApic = HalpFindApic();
|
|
|
|
HalpSearchedForApic = TRUE;
|
|
}
|
|
|
|
if (HalpAcpiNumProcessors() < 2) {
|
|
return FALSE;
|
|
}
|
|
|
|
*IsConfiguredMp = TRUE;
|
|
return TRUE;
|
|
}
|
|
|
|
|
|
ULONG
|
|
DetectApicACPI(
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by setup after DetectACPI has returned
|
|
false. During setup time DetectACPI will return false, if the
|
|
machine is an ACPI system, but only has one processor. This
|
|
function is used to detect such a machine at setup time.
|
|
|
|
Arguments:
|
|
|
|
IsConfiguredMp - FALSE
|
|
|
|
Return Value:
|
|
0 - if not a UP ACPI
|
|
1 - if UP ACPI
|
|
|
|
--*/
|
|
{
|
|
DEBUG_PRINT("DetectApicACPI\n");
|
|
|
|
if (HalpSearchedForRsdp == FALSE) {
|
|
PCHAR AcpiDebug;
|
|
|
|
//
|
|
// Check whether ACPI detection debugging is enabled
|
|
//
|
|
if ( InfFile ) {
|
|
AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
|
|
if (AcpiDebug[0] == '1') {
|
|
HalpGoodBiosDebug = TRUE;
|
|
} else {
|
|
HalpGoodBiosDebug = FALSE;
|
|
}
|
|
}
|
|
|
|
HalpFindRsdp();
|
|
|
|
HalpSearchedForRsdp = TRUE;
|
|
}
|
|
|
|
if (!HalpValidateRsdp()) {
|
|
return FALSE;
|
|
}
|
|
|
|
if (HalpSearchedForApic == FALSE) {
|
|
|
|
HalpApic = HalpFindApic();
|
|
|
|
HalpSearchedForApic = TRUE;
|
|
}
|
|
|
|
if (!HalpApic) {
|
|
return FALSE;
|
|
}
|
|
|
|
*IsConfiguredMp = FALSE;
|
|
return TRUE;
|
|
}
|
|
|
|
ULONG
|
|
DetectPicACPI(
|
|
OUT PBOOLEAN IsConfiguredMp
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function is called by setup after DetectACPI has returned
|
|
false. During setup time DetectACPI will return false, if the
|
|
machine is an ACPI system, but only has one processor. This
|
|
function is used to detect such a machine at setup time.
|
|
|
|
Arguments:
|
|
|
|
IsConfiguredMp - FALSE
|
|
|
|
Return Value:
|
|
0 - if not a PIC ACPI
|
|
1 - if PIC ACPI
|
|
|
|
--*/
|
|
{
|
|
*IsConfiguredMp = FALSE;
|
|
|
|
if (HalpSearchedForRsdp == FALSE) {
|
|
PCHAR AcpiDebug;
|
|
|
|
//
|
|
// Check whether ACPI detection debugging is enabled
|
|
//
|
|
if ( InfFile ) {
|
|
AcpiDebug = SlGetIniValue(InfFile, "ACPIOptions", "Debug", "0");
|
|
if (AcpiDebug[0] == '1') {
|
|
HalpGoodBiosDebug = TRUE;
|
|
} else {
|
|
HalpGoodBiosDebug = FALSE;
|
|
}
|
|
}
|
|
|
|
HalpFindRsdp();
|
|
|
|
HalpSearchedForRsdp = TRUE;
|
|
}
|
|
|
|
if (HalpValidateRsdp()) {
|
|
return TRUE;
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
#define EBDA_SEGMENT_PTR 0x40e
|
|
|
|
VOID
|
|
HalpFindRsdp (
|
|
VOID
|
|
)
|
|
{
|
|
ULONG romAddr = 0;
|
|
ULONG romEnd = 0;
|
|
PACPI_BIOS_INSTALLATION_CHECK header;
|
|
UCHAR sum;
|
|
USHORT i;
|
|
ULONG EbdaSegmentPtr;
|
|
ULONG EbdaPhysicalAdd = 0;
|
|
PUCHAR EbdaVirtualAdd = 0;
|
|
enum PASS { PASS1 = 0, PASS2, MAX_PASSES } pass;
|
|
|
|
//
|
|
// Search on 16 byte boundaries for the signature of the
|
|
// Root System Description Table structure.
|
|
//
|
|
for (pass = PASS1; pass < MAX_PASSES; pass++) {
|
|
|
|
if (pass == PASS1) {
|
|
|
|
//
|
|
// On the first pass, we search the first 1K of the
|
|
// Extended BIOS data area. The EBDA segment address
|
|
// is available at physical address 40:0E.
|
|
//
|
|
|
|
EbdaSegmentPtr = (ULONG) HalpMapPhysicalMemoryWriteThrough( (PVOID) 0, 1);
|
|
EbdaSegmentPtr += EBDA_SEGMENT_PTR;
|
|
EbdaPhysicalAdd = (ULONG)*((PUSHORT)EbdaSegmentPtr) << 4;
|
|
|
|
if (EbdaPhysicalAdd) {
|
|
EbdaVirtualAdd = HalpMapPhysicalMemoryWriteThrough( (PVOID)EbdaPhysicalAdd, 2);
|
|
}
|
|
|
|
if (!EbdaVirtualAdd) {
|
|
continue;
|
|
}
|
|
|
|
romAddr = (ULONG)EbdaVirtualAdd;
|
|
romEnd = romAddr + 1024;
|
|
|
|
} else {
|
|
//
|
|
// On the second pass, we search (physical) memory 0xE0000
|
|
// to 0xF0000.
|
|
|
|
romAddr = (ULONG)HalpMapPhysicalMemoryWriteThrough((PVOID)ACPI_BIOS_START,
|
|
ROUND_TO_PAGES(ACPI_BIOS_END - ACPI_BIOS_START) / PAGE_SIZE);
|
|
|
|
romEnd = romAddr + (ACPI_BIOS_END - ACPI_BIOS_START);
|
|
}
|
|
|
|
while (romAddr < romEnd) {
|
|
|
|
header = (PACPI_BIOS_INSTALLATION_CHECK)romAddr;
|
|
|
|
//
|
|
// Signature to match is the string "RSD PTR ".
|
|
//
|
|
if (header->Signature[0] == 'R' && header->Signature[1] == 'S' &&
|
|
header->Signature[2] == 'D' && header->Signature[3] == ' ' &&
|
|
header->Signature[4] == 'P' && header->Signature[5] == 'T' &&
|
|
header->Signature[6] == 'R' && header->Signature[7] == ' ' ) {
|
|
|
|
sum = 0;
|
|
for (i = 0; i < sizeof(ACPI_BIOS_INSTALLATION_CHECK); i++) {
|
|
sum = sum + ((PUCHAR)romAddr)[i];
|
|
}
|
|
if (sum == 0) {
|
|
pass = MAX_PASSES; // leave 'for' loop
|
|
break; // leave 'while' loop
|
|
}
|
|
}
|
|
|
|
romAddr += ACPI_BIOS_HEADER_INCREMENT;
|
|
}
|
|
}
|
|
|
|
if (romAddr >= romEnd) {
|
|
HalpRsdp = NULL;
|
|
HalpRsdt = NULL;
|
|
HalpXsdt = NULL;
|
|
HalpBiosDbgPrint(("NO ACPI BIOS FOUND!\n"));
|
|
HalpGoodBiosPause();
|
|
return;
|
|
}
|
|
|
|
HalpRsdp = (PRSDP)romAddr;
|
|
HalpRsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->RsdtAddress,
|
|
sizeof(RSDT));
|
|
HalpRsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->RsdtAddress,
|
|
HalpRsdt->Header.Length);
|
|
HalpBiosDbgPrint(("Found RSDP at %08lx, RSDT at %08lx\n", HalpRsdp, HalpRsdt));
|
|
|
|
#ifdef ACPI_20_COMPLIANT
|
|
if (HalpRsdp->Revision > 1) {
|
|
|
|
//
|
|
// ACPI 2.0 BIOS
|
|
//
|
|
|
|
HalpXsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->XsdtAddress.LowPart,
|
|
sizeof(XSDT));
|
|
HalpXsdt = HalpMapPhysicalRangeWriteThrough((PVOID)HalpRsdp->XsdtAddress.LowPart,
|
|
HalpXsdt->Header.Length);
|
|
HalpBiosDbgPrint(("Found XSDT at %08lx\n", HalpXsdt));
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
PVOID
|
|
HalpFindApic (
|
|
VOID
|
|
)
|
|
{
|
|
ULONG entry, rsdtEntries, rsdtLength;
|
|
PVOID physicalAddr;
|
|
PDESCRIPTION_HEADER header = NULL;
|
|
|
|
//
|
|
// Calculate the number of entries in the RSDT.
|
|
//
|
|
|
|
if (HalpXsdt) {
|
|
|
|
//
|
|
// ACPI 2.0 BIOS
|
|
//
|
|
|
|
rsdtLength = HalpXsdt->Header.Length;
|
|
rsdtEntries = NumTableEntriesFromXSDTPointer(HalpXsdt);
|
|
|
|
} else {
|
|
|
|
//
|
|
// ACPI 1.0 BIOS
|
|
//
|
|
|
|
rsdtLength = HalpRsdt->Header.Length;
|
|
rsdtEntries = NumTableEntriesFromRSDTPointer(HalpRsdt);
|
|
}
|
|
|
|
DEBUG_PRINT("rsdt length: %d\n", HalpRsdt->Header.Length);
|
|
DEBUG_PRINT("rsdtEntries: %d\n", rsdtEntries);
|
|
//
|
|
// Look down the pointer in each entry to see if it points to
|
|
// the table we are looking for.
|
|
//
|
|
for (entry = 0; entry < rsdtEntries; entry++) {
|
|
|
|
physicalAddr = HalpXsdt ?
|
|
(PVOID)HalpXsdt->Tables[entry].LowPart :
|
|
(PVOID)HalpRsdt->Tables[entry];
|
|
|
|
header = HalpMapPhysicalMemoryWriteThrough(physicalAddr, 2);
|
|
if (!header) {
|
|
return NULL;
|
|
}
|
|
|
|
DEBUG_PRINT("header: %x%x\n", ((ULONG)header) >> 16, (ULONG)header & 0xffff);
|
|
DEBUG_PRINT("entry: %d\n", header->Signature);
|
|
|
|
if (header->Signature == APIC_SIGNATURE) {
|
|
break;
|
|
}
|
|
}
|
|
|
|
//
|
|
// We didn't find an APIC table.
|
|
//
|
|
if (entry >= rsdtEntries) {
|
|
DEBUG_PRINT("Didn't find an APIC table\n");
|
|
return NULL;
|
|
}
|
|
|
|
DEBUG_PRINT("returning: %x\n", header);
|
|
return (PVOID)header;
|
|
}
|
|
|
|
ULONG
|
|
HalpAcpiNumProcessors(
|
|
VOID
|
|
)
|
|
{
|
|
PUCHAR TraversePtr;
|
|
UCHAR procCount = 0;
|
|
|
|
if (!HalpApic) {
|
|
return 1;
|
|
}
|
|
|
|
TraversePtr = (PUCHAR)((PMAPIC)HalpApic)->APICTables;
|
|
|
|
DEBUG_PRINT("APIC table header length %d\n", ((PMAPIC)HalpApic)->Header.Length);
|
|
DEBUG_PRINT("APIC table: %x%x TraversePtr: %x%x\n",
|
|
(ULONG)HalpApic >> 16,
|
|
(ULONG)HalpApic & 0xffff,
|
|
(ULONG)TraversePtr >> 16,
|
|
(ULONG)TraversePtr & 0xffff);
|
|
|
|
while (TraversePtr <= ((PUCHAR)HalpApic + ((PMAPIC)HalpApic)->Header.Length)) {
|
|
|
|
if ((((PPROCLOCALAPIC)(TraversePtr))->Type == PROCESSOR_LOCAL_APIC)
|
|
&& (((PPROCLOCALAPIC)(TraversePtr))->Length == PROCESSOR_LOCAL_APIC_LENGTH)) {
|
|
|
|
if(((PPROCLOCALAPIC)(TraversePtr))->Flags & PLAF_ENABLED) {
|
|
|
|
//
|
|
// This processor is enabled.
|
|
//
|
|
|
|
procCount++;
|
|
}
|
|
|
|
TraversePtr += ((PPROCLOCALAPIC)(TraversePtr))->Length;
|
|
|
|
} else if ((((PIOAPIC)(TraversePtr))->Type == IO_APIC) &&
|
|
(((PIOAPIC)(TraversePtr))->Length == IO_APIC_LENGTH)) {
|
|
|
|
//
|
|
// Found an I/O APIC entry. Skipping it.
|
|
//
|
|
|
|
TraversePtr += ((PIOAPIC)(TraversePtr))->Length;
|
|
|
|
} else if ((((PISA_VECTOR)(TraversePtr))->Type == ISA_VECTOR_OVERRIDE) &&
|
|
(((PISA_VECTOR)(TraversePtr))->Length == ISA_VECTOR_OVERRIDE_LENGTH)) {
|
|
|
|
//
|
|
// Found an Isa Vector Override entry. Skipping it.
|
|
//
|
|
|
|
TraversePtr += ISA_VECTOR_OVERRIDE_LENGTH;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Found random bits in the table. Try the next byte and
|
|
// see if we can make sense of it.
|
|
//
|
|
|
|
TraversePtr += 1;
|
|
}
|
|
}
|
|
|
|
DEBUG_PRINT("returning %d processors\n", procCount);
|
|
return procCount;
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
HalpValidateRsdp(
|
|
VOID
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a pointer to the RSDP, this function validates that it
|
|
is suitable for running NT. Currently this test includes:
|
|
Checking for a known good version of a known BIOS
|
|
OR Checking for a date of 1/1/99 or greater
|
|
|
|
Arguments:
|
|
|
|
Return Value:
|
|
|
|
TRUE - The ACPI BIOS on this machine is good and can be used by NT
|
|
|
|
FALSE - The ACPI BIOS on this machine is broken and will be ignored
|
|
by NT.
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG AcpiOptionValue = 2;
|
|
PCHAR AcpiOption;
|
|
PCHAR szMonth = "01", szDay = "01", szYear = "1999";
|
|
ULONG Month, Day, Year;
|
|
CHAR Temp[3];
|
|
ULONG BiosDate, CheckDate;
|
|
PUCHAR DateAddress;
|
|
|
|
if (HalpRsdp == NULL) {
|
|
HalpBiosDbgPrint(("Disabling ACPI since there is NO ACPI BIOS\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
}
|
|
|
|
//
|
|
// Check if the user has manually disabled ACPI with the F7 key
|
|
//
|
|
if (DisableACPI) {
|
|
HalpBiosDbgPrint(("Disabling ACPI due to user pressing F7\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
}
|
|
|
|
if (WinntSifHandle) {
|
|
|
|
AcpiOption = SlGetIniValue(WinntSifHandle, "Unattended", "ForceHALDetection", "no");
|
|
if (_stricmp(AcpiOption,"yes") == 0) {
|
|
|
|
HalpBiosDbgPrint(("Unattend Files specifies ForceHALDetection.\n"));
|
|
AcpiOptionValue = 2;
|
|
|
|
} else {
|
|
|
|
//
|
|
// Check the setting for ACPIEnable.
|
|
// 0 = Disable ACPI
|
|
// 1 = Enable ACPI
|
|
// 2 = Do normal good/bad BIOS detection
|
|
//
|
|
HalpBiosDbgPrint(("Unattend Files does not Contain ForceHALDetection.\n"));
|
|
AcpiOption = SlGetIniValue(WinntSifHandle, "Data", "AcpiHAL", "3");
|
|
if (AcpiOption[0] == '0' || AcpiOption[0] == '1') {
|
|
|
|
HalpBiosDbgPrint(("Got AcpiHal value from WINNT.SIF\n"));
|
|
AcpiOptionValue = AcpiOption[0] - '0';
|
|
|
|
} else if (InfFile) {
|
|
|
|
AcpiOption = SlGetIniValue(InfFile, "ACPIOptions", "ACPIEnable", "2");
|
|
if (AcpiOption[0] >= '0' && AcpiOption[0] <= '2') {
|
|
|
|
HalpBiosDbgPrint(("No AcpiHal value from WINNT.SIF\n"));
|
|
HalpBiosDbgPrint(("Got ACPIEnable from TXTSETUP.SIF\n"));
|
|
AcpiOptionValue = AcpiOption[0] - '0';
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
} else if (InfFile) {
|
|
|
|
AcpiOption = SlGetIniValue(InfFile, "ACPIOptions", "ACPIEnable", "2");
|
|
if (AcpiOption[0] >= '0' && AcpiOption[0] <= '2') {
|
|
|
|
HalpBiosDbgPrint(("No WINNT.SIF\n"));
|
|
HalpBiosDbgPrint(("Got ACPIEnable from TXTSETUP.SIF\n"));
|
|
AcpiOptionValue = AcpiOption[0] - '0';
|
|
|
|
}
|
|
|
|
}
|
|
if (AcpiOptionValue == 0) {
|
|
|
|
HalpBiosDbgPrint(("Force Disabling ACPI due to ACPIEnable == 0\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
|
|
} else if (AcpiOptionValue == 1) {
|
|
|
|
HalpBiosDbgPrint(("Force Enabling ACPI due to ACPIEnable == 1\n"));
|
|
HalpGoodBiosPause();
|
|
return(TRUE);
|
|
|
|
} else {
|
|
|
|
HalpBiosDbgPrint(("System will detect ACPI due to ACPIEnable == 2\n"));
|
|
HalpGoodBiosPause();
|
|
|
|
}
|
|
|
|
if ( InfFile ) {
|
|
|
|
//
|
|
// Check the Good BIOS list. If the BIOS is on this list, it is OK to
|
|
// enable ACPI.
|
|
//
|
|
if (HalpMatchInfList("GoodACPIBios")) {
|
|
HalpBiosDbgPrint(("Enabling ACPI since machine is on Good BIOS list\n"));
|
|
HalpGoodBiosPause();
|
|
return(TRUE);
|
|
}
|
|
|
|
//
|
|
// The BIOS is not on our Known Good list. Check the BIOS date and see
|
|
// if it is after our date at which we hope all BIOSes work.
|
|
//
|
|
|
|
szMonth = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 0);
|
|
szDay = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 1);
|
|
szYear = SlGetSectionKeyIndex(InfFile, "ACPIOptions", "ACPIBiosDate", 2);
|
|
}
|
|
|
|
|
|
if ((szMonth == NULL) ||
|
|
(szDay == NULL) ||
|
|
(szYear == NULL)) {
|
|
HalpBiosDbgPrint(("No Good BIOS date present in INF file\n"));
|
|
|
|
} else {
|
|
|
|
RtlCharToInteger(szMonth, 16, &Month);
|
|
RtlCharToInteger(szDay, 16, &Day);
|
|
RtlCharToInteger(szYear, 16, &Year);
|
|
CheckDate = (Year << 16) + (Month << 8) + Day;
|
|
|
|
DateAddress = HalpMapPhysicalRange((PVOID)0xFFFF5, 8);
|
|
Temp[2] = '\0';
|
|
RtlCopyMemory(Temp, DateAddress+6, 2);
|
|
RtlCharToInteger(Temp, 16, &Year);
|
|
if (Year < 0x80) {
|
|
Year += 0x2000;
|
|
} else {
|
|
Year += 0x1900;
|
|
}
|
|
|
|
RtlCopyMemory(Temp, DateAddress, 2);
|
|
RtlCharToInteger(Temp, 16, &Month);
|
|
|
|
RtlCopyMemory(Temp, DateAddress+3, 2);
|
|
RtlCharToInteger(Temp, 16, &Day);
|
|
|
|
BiosDate = (Year << 16) + (Month << 8) + Day;
|
|
|
|
HalpBiosDbgPrint(("\n Checking good date %08lx against BIOS date %08lx - ",CheckDate,BiosDate));
|
|
if (BiosDate >= CheckDate) {
|
|
HalpBiosDbgPrint(("GOOD!\n"));
|
|
|
|
//
|
|
// The date on the BIOS is new enough, now just make sure the machine
|
|
// is not on the BAD BIOS list.
|
|
//
|
|
if ( InfFile ) {
|
|
HalpBiosDbgPrint(("Checking BAD BIOS LIST\n"));
|
|
if (HalpMatchInfList("NWACL")) {
|
|
HalpBiosDbgPrint(("Disabling ACPI since machine is on BAD BIOS list\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
} else {
|
|
HalpBiosDbgPrint(("Enabling ACPI since BIOS is new enough to work\n"));
|
|
HalpGoodBiosPause();
|
|
return(TRUE);
|
|
}
|
|
} else {
|
|
return(TRUE);
|
|
}
|
|
} else {
|
|
HalpBiosDbgPrint(("BAD!\n"));
|
|
}
|
|
|
|
}
|
|
|
|
HalpBiosDbgPrint(("Disabling ACPI since machine is NOT on Good BIOS list\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
|
|
}
|
|
|
|
|
|
PDESCRIPTION_HEADER
|
|
HalpFindACPITable(
|
|
IN PCHAR TableName,
|
|
IN ULONG TableLength
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given a table name, finds that table in the ACPI BIOS
|
|
|
|
Arguments:
|
|
|
|
TableName - Supplies the table name
|
|
|
|
TableLength - Supplies the length of the table to map
|
|
|
|
Return Value:
|
|
|
|
Pointer to the table if found
|
|
|
|
NULL if the table is not found
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG Signature;
|
|
PFADT Fadt;
|
|
PDESCRIPTION_HEADER Header;
|
|
ULONG TableCount;
|
|
ULONG i;
|
|
ULONG TableAddr;
|
|
|
|
Signature = *((ULONG UNALIGNED *)TableName);
|
|
if (Signature == RSDT_SIGNATURE) {
|
|
return(&HalpRsdt->Header);
|
|
} else if (Signature == XSDT_SIGNATURE) {
|
|
return(&HalpXsdt->Header);
|
|
} else if (Signature == DSDT_SIGNATURE) {
|
|
Fadt = (PFADT)HalpFindACPITable("FACP", sizeof(FADT));
|
|
if (Fadt == NULL) {
|
|
return(NULL);
|
|
}
|
|
Header = HalpMapPhysicalRangeWriteThrough((PVOID)Fadt->dsdt, TableLength);
|
|
return(Header);
|
|
} else {
|
|
|
|
TableCount = HalpXsdt ?
|
|
NumTableEntriesFromXSDTPointer(HalpXsdt) :
|
|
NumTableEntriesFromRSDTPointer(HalpRsdt);
|
|
|
|
for (i=0;i<TableCount;i++) {
|
|
|
|
TableAddr = HalpXsdt ?
|
|
HalpXsdt->Tables[i].LowPart :
|
|
HalpRsdt->Tables[i];
|
|
|
|
Header = HalpMapPhysicalRangeWriteThrough((PVOID)TableAddr, sizeof(DESCRIPTION_HEADER));
|
|
if (Header->Signature == Signature) {
|
|
if (TableLength/PAGE_SIZE > sizeof(DESCRIPTION_HEADER)/PAGE_SIZE) {
|
|
//
|
|
// if we need to map more than just the DESCRIPTION_HEADER, do that before
|
|
// returning.
|
|
//
|
|
Header = HalpMapPhysicalRangeWriteThrough((PVOID)TableAddr, TableLength);
|
|
}
|
|
return(Header);
|
|
}
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
HalpMatchInfList(
|
|
IN PCHAR Section
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function determines if the computer matches any of the computer
|
|
descriptions in an INF file list.
|
|
|
|
Arguments:
|
|
|
|
Section - Section of INF that contains the list of descriptions
|
|
|
|
Return Value:
|
|
|
|
TRUE - The computer matches one of the descriptions
|
|
|
|
FALSE - The computer does not match any of the descriptions
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG i;
|
|
PCHAR ComputerName;
|
|
|
|
for (i=0; ; i++) {
|
|
ComputerName = SlGetKeyName(InfFile,
|
|
Section,
|
|
i);
|
|
if (ComputerName == NULL) {
|
|
break;
|
|
}
|
|
if (HalpMatchDescription(ComputerName)) {
|
|
return(TRUE);
|
|
}
|
|
}
|
|
|
|
return(FALSE);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
HalpMatchDescription(
|
|
PCHAR Section
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes an ACPI BIOS description to see if the
|
|
BIOS matches all of the rules in the section
|
|
|
|
Arguments:
|
|
|
|
Section - Supplies the section name of the INF to process
|
|
|
|
Return Value:
|
|
|
|
TRUE - The BIOS matches all the rules
|
|
|
|
FALSE - The BIOS failed one or more rules
|
|
|
|
--*/
|
|
|
|
{
|
|
ULONG RuleNumber;
|
|
PCHAR Rule;
|
|
ULONG i;
|
|
BOOLEAN Success;
|
|
|
|
HalpBiosDbgPrint(("Matching against %s\n", Section));
|
|
|
|
//
|
|
// Check to see if the specified section exists
|
|
//
|
|
if (!SpSearchINFSection(InfFile, Section)) {
|
|
HalpBiosDbgPrint(("\tERROR - no INF section %s\n", Section));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
}
|
|
|
|
for (RuleNumber=0; ;RuleNumber++) {
|
|
Rule = SlGetKeyName(InfFile, Section, RuleNumber);
|
|
if (Rule == NULL) {
|
|
break;
|
|
}
|
|
for (i=0; InfRule[i].szRule != NULL;i++) {
|
|
if (_stricmp(Rule, InfRule[i].szRule) == 0) {
|
|
HalpBiosDbgPrint(("\tTesting Rule %s\n",Rule));
|
|
Success = (*(InfRule[i].pRule))(Section, RuleNumber);
|
|
if (!Success) {
|
|
HalpBiosDbgPrint(("\tFAILED!\n"));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
}
|
|
HalpBiosDbgPrint(("\tSucceeded\n"));
|
|
break;
|
|
}
|
|
}
|
|
if (InfRule[i].szRule == NULL) {
|
|
//
|
|
// rule in the INF was not found
|
|
//
|
|
HalpBiosDbgPrint(("\tRULE %s not found!\n",Rule));
|
|
HalpGoodBiosPause();
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
HalpBiosDbgPrint(("Machine matches %s\n",Section));
|
|
HalpGoodBiosPause();
|
|
|
|
return(TRUE);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
HalpCheckOperator(
|
|
IN PCHAR Operator,
|
|
IN ULONG Arg1,
|
|
IN ULONG Arg2
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
Given an operator and two ULONG arguments, this function
|
|
returns the boolean result.
|
|
|
|
Arguments:
|
|
|
|
Operator = Supplies the logical operator: =, ==, <=, >=, !=, <, >
|
|
|
|
Arg1 - Supplies the first argument
|
|
|
|
Arg2 - Supplies the second argument
|
|
|
|
Return Value:
|
|
|
|
TRUE if Arg1 Operator Arg2
|
|
|
|
FALSE otherwise
|
|
|
|
--*/
|
|
|
|
{
|
|
BOOLEAN Success = FALSE;
|
|
|
|
HalpBiosDbgPrint(("\t\tChecking %lx %s %lx - ",Arg1, Operator, Arg2));
|
|
|
|
if ((strcmp(Operator, "=") == 0) ||
|
|
(strcmp(Operator, "==") == 0)) {
|
|
Success = (Arg1 == Arg2) ? TRUE : FALSE;
|
|
} else if (strcmp(Operator, "!=") == 0) {
|
|
Success = (Arg1 != Arg2) ? TRUE : FALSE;
|
|
} else if (strcmp(Operator, "<") == 0) {
|
|
Success = (Arg1 < Arg2) ? TRUE : FALSE;
|
|
} else if (strcmp(Operator, "<=") == 0) {
|
|
Success = (Arg1 <= Arg2) ? TRUE : FALSE;
|
|
} else if (strcmp(Operator, ">") == 0) {
|
|
Success = (Arg1 > Arg2) ? TRUE : FALSE;
|
|
} else if (strcmp(Operator, ">=") == 0) {
|
|
Success = (Arg1 >= Arg2) ? TRUE : FALSE;
|
|
} else {
|
|
//
|
|
// Invalid operator
|
|
//
|
|
}
|
|
if (Success) {
|
|
HalpBiosDbgPrint(("TRUE\n"));
|
|
} else {
|
|
HalpBiosDbgPrint(("FALSE\n"));
|
|
}
|
|
|
|
|
|
return(Success);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
MatchAcpiOemIdRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI OEM ID rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiOemId="RSDT", "123456"
|
|
|
|
is true if the RSDT has the OEM ID of 123456.
|
|
|
|
AcpiOemId="DSDT", "768000"
|
|
|
|
is true if the DSDT has the OEM ID of 768000.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR OemId;
|
|
PDESCRIPTION_HEADER Header;
|
|
CHAR ACPIOemId[6];
|
|
ULONG IdLength;
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
OemId = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
if ((TableName == NULL) || (OemId == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlZeroMemory(ACPIOemId, sizeof(ACPIOemId));
|
|
IdLength = strlen(OemId);
|
|
if (IdLength > sizeof(ACPIOemId)) {
|
|
IdLength = sizeof(ACPIOemId);
|
|
}
|
|
RtlCopyMemory(ACPIOemId, OemId, IdLength);
|
|
HalpBiosDbgPrint(("\t\tComparing OEM ID %s '%6.6s' with '%6.6s' - ",
|
|
TableName,
|
|
ACPIOemId,
|
|
Header->OEMID));
|
|
if (RtlEqualMemory(ACPIOemId, Header->OEMID, sizeof(Header->OEMID))) {
|
|
HalpBiosDbgPrint(("TRUE\n"));
|
|
return(TRUE);
|
|
} else {
|
|
HalpBiosDbgPrint(("FALSE\n"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
MatchAcpiOemTableIdRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI OEM Table ID rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiOemTableId="RSDT", "12345678"
|
|
|
|
is true if the RSDT has the Oem Table ID of 12345678.
|
|
|
|
AcpiOemTableId="DSDT", "87654321"
|
|
|
|
is true if the DSDT has the Oem Table ID of 87654321.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR OemTableId;
|
|
PDESCRIPTION_HEADER Header;
|
|
CHAR ACPIOemTableId[8];
|
|
ULONG IdLength;
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
OemTableId = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
if ((TableName == NULL) || (OemTableId == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlZeroMemory(ACPIOemTableId, sizeof(ACPIOemTableId));
|
|
IdLength = strlen(OemTableId);
|
|
if (IdLength > sizeof(ACPIOemTableId)) {
|
|
IdLength = sizeof(ACPIOemTableId);
|
|
}
|
|
RtlCopyMemory(ACPIOemTableId, OemTableId, IdLength);
|
|
HalpBiosDbgPrint(("\t\tComparing OEM TableID %s '%8.8s' with '%8.8s' - ",
|
|
TableName,
|
|
ACPIOemTableId,
|
|
Header->OEMTableID));
|
|
if (RtlEqualMemory(ACPIOemTableId,
|
|
Header->OEMTableID,
|
|
sizeof(Header->OEMTableID))) {
|
|
HalpBiosDbgPrint(("TRUE\n"));
|
|
return(TRUE);
|
|
} else {
|
|
HalpBiosDbgPrint(("FALSE\n"));
|
|
return(FALSE);
|
|
}
|
|
}
|
|
|
|
BOOLEAN
|
|
MatchAcpiOemRevisionRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI Oem Revision rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiOemRevision="=","RSDT", 1234
|
|
|
|
is true if the RSDT has the Oem Revision EQUAL to 1234.
|
|
|
|
AcpiOemRevision=">","DSDT", 4321
|
|
|
|
is true if the DSDT has the Oem Revision GREATER than 4321.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR szOemRevision;
|
|
ULONG OemRevision;
|
|
PCHAR Operator;
|
|
PDESCRIPTION_HEADER Header;
|
|
BOOLEAN Success;
|
|
|
|
Operator = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
szOemRevision = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
2);
|
|
if ((Operator == NULL) || (TableName == NULL) || (szOemRevision == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlCharToInteger(szOemRevision, 16, &OemRevision);
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
Success = HalpCheckOperator(Operator, Header->OEMRevision, OemRevision);
|
|
return(Success);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
MatchAcpiRevisionRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI Revision rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiRevision="=", "RSDT", 1234
|
|
|
|
is true if the RSDT ACPI Revision is EQUAL to 1234.
|
|
|
|
AcpiRevision=">", "DSDT", 4321
|
|
|
|
is true if the DSDT ACPI Revision is GREATER than 4321.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR szRevision;
|
|
ULONG Revision;
|
|
PCHAR Operator;
|
|
PDESCRIPTION_HEADER Header;
|
|
BOOLEAN Success;
|
|
|
|
Operator = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
szRevision = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
2);
|
|
if ((Operator == NULL) || (TableName == NULL) || (szRevision == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlCharToInteger(szRevision, 16, &Revision);
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
Success = HalpCheckOperator(Operator, Header->Revision, Revision);
|
|
return(Success);
|
|
}
|
|
|
|
|
|
BOOLEAN
|
|
MatchAcpiCreatorRevisionRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI Creator Revision rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiCreatorRevision="=", "RSDT", 1234
|
|
|
|
is true if the RSDT ACPI Creator Revision is EQUAL to 1234.
|
|
|
|
AcpiCreatorRevision=">", "DSDT", 4321
|
|
|
|
is true if the DSDT ACPI Creator Revision is GREATER than 4321.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR szCreatorRevision;
|
|
ULONG CreatorRevision;
|
|
PCHAR Operator;
|
|
PDESCRIPTION_HEADER Header;
|
|
BOOLEAN Success;
|
|
|
|
Operator = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
szCreatorRevision = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
2);
|
|
if ((Operator == NULL) || (TableName == NULL) || (szCreatorRevision == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlCharToInteger(szCreatorRevision, 16, &CreatorRevision);
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
Success = HalpCheckOperator(Operator, Header->CreatorRev, CreatorRevision);
|
|
return(Success);
|
|
}
|
|
|
|
BOOLEAN
|
|
MatchAcpiCreatorIdRule(
|
|
PCHAR Section,
|
|
ULONG KeyIndex
|
|
)
|
|
/*++
|
|
|
|
Routine Description:
|
|
|
|
This function processes a ACPI Creator ID rule from an INF file
|
|
|
|
Examples:
|
|
|
|
AcpiCreatorId="RSDT", "MSFT"
|
|
|
|
is true if the RSDT has the Creator ID of MSFT.
|
|
|
|
Arguments:
|
|
|
|
Section - Specifies the section name the rule is in
|
|
|
|
KeyIndex - Specifies the index of the rule in the section
|
|
|
|
Return Value:
|
|
|
|
TRUE - the computer has the specified ACPI OEM ID.
|
|
|
|
FALSE - the computer does not have the specified ACPI OEM ID.
|
|
|
|
--*/
|
|
|
|
{
|
|
PCHAR TableName;
|
|
PCHAR CreatorId;
|
|
PDESCRIPTION_HEADER Header;
|
|
CHAR ACPICreatorId[6];
|
|
ULONG IdLength;
|
|
|
|
TableName = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
0);
|
|
CreatorId = SlGetSectionLineIndex(InfFile,
|
|
Section,
|
|
KeyIndex,
|
|
1);
|
|
if ((TableName == NULL) || (CreatorId == NULL)) {
|
|
//
|
|
// the INF line is ill-formed
|
|
//
|
|
HalpBiosDbgPrint(("\t\tINF line is ill-formed\n"));
|
|
return(FALSE);
|
|
}
|
|
|
|
Header = HalpFindACPITable(TableName, sizeof(DESCRIPTION_HEADER));
|
|
if (Header == NULL) {
|
|
//
|
|
// The specified table was not found
|
|
//
|
|
HalpBiosDbgPrint(("\t\tTable %s was not found\n"));
|
|
return(FALSE);
|
|
}
|
|
RtlZeroMemory(ACPICreatorId, sizeof(ACPICreatorId));
|
|
IdLength = strlen(CreatorId);
|
|
if (IdLength > sizeof(ACPICreatorId)) {
|
|
IdLength = sizeof(ACPICreatorId);
|
|
}
|
|
RtlCopyMemory(ACPICreatorId, CreatorId, IdLength);
|
|
if (RtlEqualMemory(ACPICreatorId, Header->CreatorID, sizeof(Header->CreatorID))) {
|
|
return(TRUE);
|
|
} else {
|
|
return(FALSE);
|
|
}
|
|
}
|