Allow OS override of all ACPI tables.

Previously, the table override mechanism was implemented for the
DSDT only. Now, any table in the RSDT/XSDT can be replaced by the
host OS. (including the DSDT).
This commit is contained in:
Robert Moore 2008-12-09 09:37:48 -08:00
parent 7d19af2188
commit 2d8f95c694
8 changed files with 113 additions and 59 deletions

View File

@ -563,10 +563,6 @@ AcpiDbTerminate (
void)
{
if (AcpiGbl_DbTablePtr)
{
AcpiOsFree (AcpiGbl_DbTablePtr);
}
if (AcpiGbl_DbBuffer)
{
AcpiOsFree (AcpiGbl_DbBuffer);

View File

@ -320,7 +320,10 @@ AcpiTbChecksum (
*
* RETURN: None
*
* DESCRIPTION: Install an ACPI table into the global data structure.
* DESCRIPTION: Install an ACPI table into the global data structure. The
* table override mechanism is implemented here to allow the host
* OS to replace any table before it is installed in the root
* table array.
*
******************************************************************************/
@ -331,7 +334,10 @@ AcpiTbInstallTable (
char *Signature,
UINT32 TableIndex)
{
ACPI_TABLE_HEADER *Table;
ACPI_STATUS Status;
ACPI_TABLE_HEADER *TableToInstall;
ACPI_TABLE_HEADER *MappedTable;
ACPI_TABLE_HEADER *OverrideTable = NULL;
if (!Address)
@ -343,43 +349,68 @@ AcpiTbInstallTable (
/* Map just the table header */
Table = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
if (!Table)
MappedTable = AcpiOsMapMemory (Address, sizeof (ACPI_TABLE_HEADER));
if (!MappedTable)
{
return;
}
/* If a particular signature is expected, signature must match */
/* If a particular signature is expected (DSDT/FACS), it must match */
if (Signature &&
!ACPI_COMPARE_NAME (Table->Signature, Signature))
!ACPI_COMPARE_NAME (MappedTable->Signature, Signature))
{
ACPI_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table [%s]",
*ACPI_CAST_PTR (UINT32, Table->Signature), Signature));
ACPI_ERROR ((AE_INFO, "Invalid signature 0x%X for ACPI table, expected [%s]",
*ACPI_CAST_PTR (UINT32, MappedTable->Signature), Signature));
goto UnmapAndExit;
}
/*
* ACPI Table Override:
*
* Before we install the table, let the host OS override it with a new
* one if desired. Any table within the RSDT/XSDT can be replaced,
* including the DSDT which is pointed to by the FADT.
*/
Status = AcpiOsTableOverride (MappedTable, &OverrideTable);
if (ACPI_SUCCESS (Status) && OverrideTable)
{
ACPI_INFO ((AE_INFO,
"%4.4s @ 0x%p Table override, replaced with:",
MappedTable->Signature, ACPI_CAST_PTR (void, Address)));
AcpiGbl_RootTableList.Tables[TableIndex].Pointer = OverrideTable;
Flags = ACPI_TABLE_ORIGIN_OVERRIDE;
Address = ACPI_PTR_TO_PHYSADDR (OverrideTable);
TableToInstall = OverrideTable;
}
else
{
TableToInstall = MappedTable;
}
/* Initialize the table entry */
AcpiGbl_RootTableList.Tables[TableIndex].Address = Address;
AcpiGbl_RootTableList.Tables[TableIndex].Length = Table->Length;
AcpiGbl_RootTableList.Tables[TableIndex].Length = TableToInstall->Length;
AcpiGbl_RootTableList.Tables[TableIndex].Flags = Flags;
ACPI_MOVE_32_TO_32 (
&(AcpiGbl_RootTableList.Tables[TableIndex].Signature),
Table->Signature);
TableToInstall->Signature);
AcpiTbPrintTableHeader (Address, Table);
AcpiTbPrintTableHeader (Address, TableToInstall);
if (TableIndex == ACPI_TABLE_INDEX_DSDT)
{
/* Global integer width is based upon revision of the DSDT */
AcpiUtSetIntegerWidth (Table->Revision);
AcpiUtSetIntegerWidth (TableToInstall->Revision);
}
UnmapAndExit:
AcpiOsUnmapMemory (Table, sizeof (ACPI_TABLE_HEADER));
AcpiOsUnmapMemory (MappedTable, sizeof (ACPI_TABLE_HEADER));
}

View File

@ -534,7 +534,6 @@ AcpiTbLoadNamespace (
void)
{
ACPI_STATUS Status;
ACPI_TABLE_HEADER *Table;
UINT32 i;
@ -556,30 +555,11 @@ AcpiTbLoadNamespace (
goto UnlockAndExit;
}
/*
* Find DSDT table
*/
Status = AcpiOsTableOverride (
AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer, &Table);
if (ACPI_SUCCESS (Status) && Table)
{
/*
* DSDT table has been found
*/
AcpiTbDeleteTable (&AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]);
AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Pointer = Table;
AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Length = Table->Length;
AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT].Flags = ACPI_TABLE_ORIGIN_UNKNOWN;
ACPI_INFO ((AE_INFO, "Table DSDT replaced by host OS"));
AcpiTbPrintTableHeader (0, Table);
}
/* A valid DSDT is required */
Status = AcpiTbVerifyTable (&AcpiGbl_RootTableList.Tables[ACPI_TABLE_INDEX_DSDT]);
if (ACPI_FAILURE (Status))
{
/* A valid DSDT is required */
Status = AE_NO_ACPI_TABLES;
goto UnlockAndExit;
}

View File

@ -459,7 +459,6 @@ ACPI_EXTERN char *AcpiGbl_DbBuffer;
ACPI_EXTERN char *AcpiGbl_DbFilename;
ACPI_EXTERN UINT32 AcpiGbl_DbDebugLevel;
ACPI_EXTERN UINT32 AcpiGbl_DbConsoleDebugLevel;
ACPI_EXTERN ACPI_TABLE_HEADER *AcpiGbl_DbTablePtr;
ACPI_EXTERN ACPI_NAMESPACE_NODE *AcpiGbl_DbScopeNode;
/*

View File

@ -409,8 +409,9 @@ typedef struct acpi_table_desc
#define ACPI_TABLE_ORIGIN_UNKNOWN (0)
#define ACPI_TABLE_ORIGIN_MAPPED (1)
#define ACPI_TABLE_ORIGIN_ALLOCATED (2)
#define ACPI_TABLE_ORIGIN_MASK (3)
#define ACPI_TABLE_IS_LOADED (4)
#define ACPI_TABLE_ORIGIN_OVERRIDE (4)
#define ACPI_TABLE_ORIGIN_MASK (7)
#define ACPI_TABLE_IS_LOADED (8)
/*

View File

@ -140,10 +140,18 @@
extern FILE *AcpiGbl_DebugFile;
FILE *AcpiGbl_OutputFile;
/* Upcalls to AcpiExec */
ACPI_PHYSICAL_ADDRESS
AeLocalGetRootPointer (
void);
void
AeTableOverride (
ACPI_TABLE_HEADER *ExistingTable,
ACPI_TABLE_HEADER **NewTable);
typedef void* (*PTHREAD_CALLBACK) (void *);
/******************************************************************************
@ -254,14 +262,7 @@ AcpiOsTableOverride (
#ifdef ACPI_EXEC_APP
/* This code exercises the table override mechanism in the core */
if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT))
{
/* override DSDT with itself */
*NewTable = AcpiGbl_DbTablePtr;
}
AeTableOverride (ExistingTable, NewTable);
return (AE_OK);
#else
return AE_NO_ACPI_TABLES;

View File

@ -158,10 +158,18 @@ typedef struct semaphore_entry
SEMAPHORE_ENTRY AcpiGbl_Semaphores[NUM_SEMAPHORES];
extern FILE *AcpiGbl_DebugFile;
/* Upcalls to AcpiExec */
ACPI_PHYSICAL_ADDRESS
AeLocalGetRootPointer (
void);
void
AeTableOverride (
ACPI_TABLE_HEADER *ExistingTable,
ACPI_TABLE_HEADER **NewTable);
FILE *AcpiGbl_OutputFile;
UINT64 TimerFrequency;
@ -450,15 +458,7 @@ AcpiOsTableOverride (
#ifndef ACPI_BIN_APP
#ifdef ACPI_EXEC_APP
/* This code exercises the table override mechanism in the core */
if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT))
{
/* override DSDT with itself */
*NewTable = AcpiGbl_DbTablePtr;
}
AeTableOverride (ExistingTable, NewTable);
#else
/* Construct a null-terminated string from table signature */

View File

@ -131,6 +131,20 @@ ACPI_TABLE_RSDP LocalRsdp;
/*
* Misc ACPI tables to be installed
*/
/* Default DSDT. This will be replaced with the input DSDT */
unsigned char DsdtCode[] =
{
0x44,0x53,0x44,0x54,0x24,0x00,0x00,0x00, /* 00000000 "DSDT$..." */
0x02,0x6F,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 ".oIntel." */
0x4E,0x75,0x6C,0x6C,0x44,0x53,0x44,0x54, /* 00000010 "NullDSDT" */
0x01,0x00,0x00,0x00,0x49,0x4E,0x54,0x4C, /* 00000018 "....INTL" */
0x04,0x12,0x08,0x20,
};
/* Several example SSDTs */
unsigned char Ssdt1Code[] = /* Has method _T98 */
{
0x53,0x53,0x44,0x54,0x30,0x00,0x00,0x00, /* 00000000 "SSDT0..." */
@ -161,6 +175,8 @@ unsigned char Ssdt3Code[] = /* Has method _T97 */
0x39,0x37,0x00,0x70,0x0A,0x04,0x60,0xA4, /* 00000028 "97.p..`." */
};
/* Example OEM table */
unsigned char Oem1Code[] =
{
0x4F,0x45,0x4D,0x31,0x38,0x00,0x00,0x00, /* 00000000 "OEM18..." */
@ -177,6 +193,7 @@ unsigned char Oem1Code[] =
* even though the underlying OSD HW access functions don't do
* anything.
*/
ACPI_TABLE_HEADER *DsdtToInstallOverride;
ACPI_TABLE_RSDP LocalRSDP;
ACPI_TABLE_FADT LocalFADT;
ACPI_TABLE_FACS LocalFACS;
@ -194,6 +211,33 @@ static ACPI_TABLE_DESC Tables[ACPI_MAX_INIT_TABLES];
UINT32 SigintCount = 0;
/******************************************************************************
*
* FUNCTION: AeTableOverride
*
* DESCRIPTION: Local implementation of AcpiOsTableOverride.
*
* Exercise the override mechanism
*
*****************************************************************************/
void
AeTableOverride (
ACPI_TABLE_HEADER *ExistingTable,
ACPI_TABLE_HEADER **NewTable)
{
/* This code exercises the table override mechanism in the core */
if (ACPI_COMPARE_NAME (ExistingTable->Signature, ACPI_SIG_DSDT))
{
*NewTable = DsdtToInstallOverride;
}
}
/******************************************************************************
*
* FUNCTION: AeCtrlCHandler
@ -293,7 +337,8 @@ AeBuildLocalTables (
{
/* The incoming user table is a DSDT */
DsdtAddress = ACPI_PTR_TO_PHYSADDR (UserTable);
DsdtAddress = ACPI_PTR_TO_PHYSADDR (&DsdtCode);
DsdtToInstallOverride = UserTable;
}
else
{
@ -309,6 +354,7 @@ AeBuildLocalTables (
LocalRSDT->TableOffsetEntry[3] = ACPI_PTR_TO_PHYSADDR (UserTable);
DsdtAddress = ACPI_PTR_TO_PHYSADDR (&LocalDSDT);
DsdtToInstallOverride = &LocalDSDT;
}
/* Set checksums for both RSDT and RSDP */