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.
357 lines
8.6 KiB
357 lines
8.6 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:
|
|
|
|
|
|
--*/
|
|
#include "bootx86.h"
|
|
|
|
#include "stdlib.h"
|
|
#include "string.h"
|
|
|
|
VOID
|
|
BlPrint(
|
|
PCHAR cp,
|
|
...
|
|
);
|
|
|
|
|
|
#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"
|
|
|
|
PRSDP BlRsdp;
|
|
PRSDT BlRsdt;
|
|
PXSDT BlXsdt;
|
|
BOOLEAN BlLegacyFree = FALSE;
|
|
|
|
PDESCRIPTION_HEADER
|
|
BlFindACPITable(
|
|
IN PCHAR TableName,
|
|
IN ULONG TableLength
|
|
);
|
|
|
|
// 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
|
|
|
|
VOID
|
|
BlFindRsdp (
|
|
VOID
|
|
)
|
|
#define EBDA_SEGMENT_PTR 0x40e
|
|
{
|
|
ULONG romAddr = 0;
|
|
ULONG romEnd = 0;
|
|
PACPI_BIOS_INSTALLATION_CHECK header;
|
|
UCHAR sum;
|
|
USHORT i;
|
|
ULONG EbdaSegmentPtr;
|
|
ULONG EbdaPhysicalAdd = 0;
|
|
PUCHAR EbdaVirtualAdd = 0;
|
|
PHYSICAL_ADDRESS paddr;
|
|
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.
|
|
//
|
|
|
|
paddr.QuadPart = 0;
|
|
EbdaSegmentPtr = (ULONG) MmMapIoSpace( paddr,
|
|
PAGE_SIZE,
|
|
TRUE);
|
|
|
|
EbdaSegmentPtr += EBDA_SEGMENT_PTR;
|
|
EbdaPhysicalAdd = *((PUSHORT)EbdaSegmentPtr);
|
|
EbdaPhysicalAdd = EbdaPhysicalAdd << 4;
|
|
|
|
if (EbdaPhysicalAdd) {
|
|
paddr.HighPart = 0;
|
|
paddr.LowPart = EbdaPhysicalAdd;
|
|
EbdaVirtualAdd = MmMapIoSpace( paddr,
|
|
2 * PAGE_SIZE,
|
|
TRUE);
|
|
}
|
|
|
|
if (!EbdaVirtualAdd) {
|
|
continue;
|
|
}
|
|
|
|
romAddr = (ULONG)EbdaVirtualAdd;
|
|
romEnd = romAddr + 1024;
|
|
|
|
} else {
|
|
//
|
|
// On the second pass, we search (physical) memory 0xE0000
|
|
// to 0xF0000.
|
|
|
|
paddr.LowPart = ACPI_BIOS_START;
|
|
romAddr = (ULONG)MmMapIoSpace(paddr,
|
|
ACPI_BIOS_END - ACPI_BIOS_START,
|
|
TRUE);
|
|
|
|
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) {
|
|
BlRsdp = NULL;
|
|
BlRsdt = NULL;
|
|
return;
|
|
}
|
|
|
|
BlRsdp = (PRSDP)romAddr;
|
|
paddr.LowPart = BlRsdp->RsdtAddress;
|
|
BlRsdt = MmMapIoSpace(paddr, sizeof(RSDT), TRUE);
|
|
BlRsdt = MmMapIoSpace(paddr, BlRsdt->Header.Length, TRUE);
|
|
|
|
#ifdef ACPI_20_COMPLIANT
|
|
if (BlRsdp->Revision > 1) {
|
|
|
|
//
|
|
// ACPI 2.0 BIOS
|
|
//
|
|
|
|
BlXsdt = MmMapIoSpace(paddr, sizeof(XSDT), TRUE);
|
|
BlXsdt = MmMapIoSpace(paddr, BlXsdt->Header.Length, TRUE);
|
|
}
|
|
#endif
|
|
return;
|
|
}
|
|
|
|
|
|
//
|
|
// Make the FADT table global.
|
|
// It will be used when resetting legacy free machines.
|
|
//
|
|
PFADT fadt = NULL;
|
|
|
|
|
|
BOOLEAN
|
|
BlDetectLegacyFreeBios(
|
|
VOID
|
|
)
|
|
{
|
|
|
|
if (BlLegacyFree) {
|
|
return TRUE;
|
|
}
|
|
|
|
BlFindRsdp();
|
|
|
|
if (BlRsdt) {
|
|
|
|
fadt = (PFADT)BlFindACPITable("FACP", sizeof(FADT));
|
|
|
|
if (fadt == NULL) {
|
|
return FALSE;
|
|
}
|
|
|
|
if ((fadt->Header.Revision < 2) ||
|
|
(fadt->Header.Length <= 116)) {
|
|
|
|
//
|
|
// The BIOS is earlier than the legacy-free
|
|
// additions.
|
|
//
|
|
return FALSE;
|
|
}
|
|
|
|
if (!(fadt->boot_arch & I8042)) {
|
|
BlLegacyFree = TRUE;
|
|
return TRUE;
|
|
}
|
|
}
|
|
|
|
return FALSE;
|
|
}
|
|
|
|
PDESCRIPTION_HEADER
|
|
BlFindACPITable(
|
|
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;
|
|
PHYSICAL_ADDRESS paddr = {0};
|
|
|
|
Signature = *((ULONG UNALIGNED *)TableName);
|
|
if (Signature == RSDT_SIGNATURE) {
|
|
return(&BlRsdt->Header);
|
|
} else if (Signature == XSDT_SIGNATURE) {
|
|
return(&BlXsdt->Header);
|
|
} else if (Signature == DSDT_SIGNATURE) {
|
|
Fadt = (PFADT)BlFindACPITable("FACP", sizeof(PFADT));
|
|
if (Fadt == NULL) {
|
|
return(NULL);
|
|
}
|
|
if (BlXsdt) {
|
|
paddr = Fadt->x_dsdt;
|
|
} else {
|
|
#if defined(_X86_)
|
|
paddr.LowPart = Fadt->dsdt;
|
|
#else
|
|
paddr.QuadPart = Fadt->dsdt;
|
|
#endif
|
|
}
|
|
Header = MmMapIoSpace(paddr, TableLength, TRUE);
|
|
return(Header);
|
|
} else {
|
|
|
|
//
|
|
// Make sure...
|
|
//
|
|
if( !BlRsdt ) {
|
|
BlFindRsdp();
|
|
}
|
|
|
|
if( BlRsdt ) {
|
|
|
|
TableCount = BlXsdt ?
|
|
NumTableEntriesFromXSDTPointer(BlXsdt) :
|
|
NumTableEntriesFromRSDTPointer(BlRsdt);
|
|
|
|
//
|
|
// Sanity check.
|
|
//
|
|
if( TableCount > 0x100 ) {
|
|
return(NULL);
|
|
}
|
|
|
|
for (i=0;i<TableCount;i++) {
|
|
|
|
|
|
if (BlXsdt) {
|
|
|
|
paddr = BlXsdt->Tables[i];
|
|
|
|
} else {
|
|
|
|
#if defined(_X86_)
|
|
paddr.HighPart = 0;
|
|
paddr.LowPart = BlRsdt->Tables[i];
|
|
#else
|
|
paddr.QuadPart = BlRsdt->Tables[i];
|
|
#endif
|
|
}
|
|
|
|
Header = MmMapIoSpace(paddr, sizeof(DESCRIPTION_HEADER), TRUE);
|
|
if (Header == NULL) {
|
|
return(NULL);
|
|
}
|
|
if (Header->Signature == Signature) {
|
|
//
|
|
// if we need to map more than just the DESCRIPTION_HEADER, do that before
|
|
// returning. Check to see if the end of the table lies past the page
|
|
// boundary the header lies on. If so, we will have to map it.
|
|
//
|
|
if ( ((paddr.LowPart + TableLength) & ~(PAGE_SIZE - 1)) >
|
|
((paddr.LowPart + sizeof(DESCRIPTION_HEADER)) & ~(PAGE_SIZE - 1)) ) {
|
|
Header = MmMapIoSpace(paddr, TableLength, TRUE);
|
|
}
|
|
return(Header);
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
return(NULL);
|
|
}
|