mirror of
https://github.com/acpica/acpica/
synced 2025-01-13 12:59:18 +03:00
New: AcpiInstallMethod - install a single control method.
This interface enables the override or creation of a single control method. Useful to repair a bug or install a missing method.
This commit is contained in:
parent
43cfa272f6
commit
7abcc2ea10
@ -614,7 +614,7 @@ AcpiExCreateMethod (
|
||||
* ACPI 2.0: SyncLevel = SyncLevel in method declaration
|
||||
*/
|
||||
ObjDesc->Method.SyncLevel = (UINT8)
|
||||
((MethodFlags & AML_METHOD_SYNCH_LEVEL) >> 4);
|
||||
((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
|
||||
}
|
||||
|
||||
/* Attach the new object to the method Node */
|
||||
|
@ -213,10 +213,11 @@ static ACPI_EXDUMP_INFO AcpiExDumpEvent[2] =
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Event.OsSemaphore), "OsSemaphore"}
|
||||
};
|
||||
|
||||
static ACPI_EXDUMP_INFO AcpiExDumpMethod[8] =
|
||||
static ACPI_EXDUMP_INFO AcpiExDumpMethod[9] =
|
||||
{
|
||||
{ACPI_EXD_INIT, ACPI_EXD_TABLE_SIZE (AcpiExDumpMethod), NULL},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ParamCount), "ParamCount"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.MethodFlags), "Method Flags"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.ParamCount), "Parameter Count"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.SyncLevel), "Sync Level"},
|
||||
{ACPI_EXD_POINTER, ACPI_EXD_OFFSET (Method.Mutex), "Mutex"},
|
||||
{ACPI_EXD_UINT8, ACPI_EXD_OFFSET (Method.OwnerId), "Owner Id"},
|
||||
|
@ -309,6 +309,16 @@ AcpiNsDetachObject (
|
||||
return_VOID;
|
||||
}
|
||||
|
||||
if (Node->Flags & ANOBJ_ALLOCATED_BUFFER)
|
||||
{
|
||||
/* Free the dynamic aml buffer */
|
||||
|
||||
if (ObjDesc->Common.Type == ACPI_TYPE_METHOD)
|
||||
{
|
||||
ACPI_FREE (ObjDesc->Method.AmlStart);
|
||||
}
|
||||
}
|
||||
|
||||
/* Clear the entry in all cases */
|
||||
|
||||
Node->Object = NULL;
|
||||
|
@ -119,6 +119,8 @@
|
||||
#include "acpi.h"
|
||||
#include "accommon.h"
|
||||
#include "acnamesp.h"
|
||||
#include "acparser.h"
|
||||
#include "amlcode.h"
|
||||
|
||||
|
||||
#define _COMPONENT ACPI_NAMESPACE
|
||||
@ -478,3 +480,165 @@ Cleanup:
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiGetObjectInfo)
|
||||
|
||||
|
||||
/******************************************************************************
|
||||
*
|
||||
* FUNCTION: AcpiInstallMethod
|
||||
*
|
||||
* PARAMETERS: Buffer - An ACPI table containing one control method
|
||||
*
|
||||
* RETURN: Status
|
||||
*
|
||||
* DESCRIPTION: Install a control method into the namespace. If the method
|
||||
* name already exists in the namespace, it is overwritten. The
|
||||
* input buffer must contain a valid DSDT or SSDT containing a
|
||||
* single control method.
|
||||
*
|
||||
******************************************************************************/
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallMethod (
|
||||
UINT8 *Buffer)
|
||||
{
|
||||
ACPI_TABLE_HEADER *Table = ACPI_CAST_PTR (ACPI_TABLE_HEADER, Buffer);
|
||||
UINT8 *AmlBuffer;
|
||||
UINT8 *AmlStart;
|
||||
char *Path;
|
||||
ACPI_NAMESPACE_NODE *Node;
|
||||
ACPI_OPERAND_OBJECT *MethodObj;
|
||||
ACPI_PARSE_STATE ParserState;
|
||||
UINT32 AmlLength;
|
||||
UINT16 Opcode;
|
||||
UINT8 MethodFlags;
|
||||
ACPI_STATUS Status;
|
||||
|
||||
|
||||
/* Parameter validation */
|
||||
|
||||
if (!Buffer)
|
||||
{
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Table must be a DSDT or SSDT */
|
||||
|
||||
if (!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_DSDT) &&
|
||||
!ACPI_COMPARE_NAME (Table->Signature, ACPI_SIG_SSDT))
|
||||
{
|
||||
return (AE_BAD_HEADER);
|
||||
}
|
||||
|
||||
/* First AML opcode in the table must be a control method */
|
||||
|
||||
ParserState.Aml = Buffer + sizeof (ACPI_TABLE_HEADER);
|
||||
Opcode = AcpiPsPeekOpcode (&ParserState);
|
||||
if (Opcode != AML_METHOD_OP)
|
||||
{
|
||||
return (AE_BAD_PARAMETER);
|
||||
}
|
||||
|
||||
/* Extract method information from the raw AML */
|
||||
|
||||
ParserState.Aml += AcpiPsGetOpcodeSize (Opcode);
|
||||
ParserState.PkgEnd = AcpiPsGetNextPackageEnd (&ParserState);
|
||||
Path = AcpiPsGetNextNamestring (&ParserState);
|
||||
MethodFlags = *ParserState.Aml++;
|
||||
AmlStart = ParserState.Aml;
|
||||
AmlLength = ACPI_PTR_DIFF (ParserState.PkgEnd, AmlStart);
|
||||
|
||||
/*
|
||||
* Allocate resources up-front. We don't want to have to delete a new
|
||||
* node from the namespace if we cannot allocate memory.
|
||||
*/
|
||||
AmlBuffer = ACPI_ALLOCATE (AmlLength);
|
||||
if (!AmlBuffer)
|
||||
{
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
MethodObj = AcpiUtCreateInternalObject (ACPI_TYPE_METHOD);
|
||||
if (!MethodObj)
|
||||
{
|
||||
ACPI_FREE (AmlBuffer);
|
||||
return (AE_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* Lock namespace for AcpiNsLookup, we may be creating a new node */
|
||||
|
||||
Status = AcpiUtAcquireMutex (ACPI_MTX_NAMESPACE);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* The lookup either returns an existing node or creates a new one */
|
||||
|
||||
Status = AcpiNsLookup (NULL, Path, ACPI_TYPE_METHOD, ACPI_IMODE_LOAD_PASS1,
|
||||
ACPI_NS_DONT_OPEN_SCOPE | ACPI_NS_ERROR_IF_FOUND, NULL, &Node);
|
||||
|
||||
(void) AcpiUtReleaseMutex (ACPI_MTX_NAMESPACE);
|
||||
|
||||
if (ACPI_FAILURE (Status)) /* NsLookup */
|
||||
{
|
||||
if (Status != AE_ALREADY_EXISTS)
|
||||
{
|
||||
goto ErrorExit;
|
||||
}
|
||||
|
||||
/* Node existed previously, make sure it is a method node */
|
||||
|
||||
if (Node->Type != ACPI_TYPE_METHOD)
|
||||
{
|
||||
Status = AE_TYPE;
|
||||
goto ErrorExit;
|
||||
}
|
||||
}
|
||||
|
||||
/* Copy the method AML to the local buffer */
|
||||
|
||||
ACPI_MEMCPY (AmlBuffer, AmlStart, AmlLength);
|
||||
|
||||
/* Initialize the method object with the new method's information */
|
||||
|
||||
MethodObj->Method.AmlStart = AmlBuffer;
|
||||
MethodObj->Method.AmlLength = AmlLength;
|
||||
|
||||
MethodObj->Method.ParamCount = (UINT8)
|
||||
(MethodFlags & AML_METHOD_ARG_COUNT);
|
||||
|
||||
MethodObj->Method.MethodFlags = (UINT8)
|
||||
(MethodFlags & ~AML_METHOD_ARG_COUNT);
|
||||
|
||||
if (MethodFlags & AML_METHOD_SERIALIZED)
|
||||
{
|
||||
MethodObj->Method.SyncLevel = (UINT8)
|
||||
((MethodFlags & AML_METHOD_SYNC_LEVEL) >> 4);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now that it is complete, we can attach the new method object to
|
||||
* the method Node (detaches/deletes any existing object)
|
||||
*/
|
||||
Status = AcpiNsAttachObject (Node, MethodObj,
|
||||
ACPI_TYPE_METHOD);
|
||||
|
||||
/*
|
||||
* Flag indicates AML buffer is dynamic, must be deleted later.
|
||||
* Must be set only after attach above.
|
||||
*/
|
||||
Node->Flags |= ANOBJ_ALLOCATED_BUFFER;
|
||||
|
||||
/* Remove local reference to the method object */
|
||||
|
||||
AcpiUtRemoveReference (MethodObj);
|
||||
return (Status);
|
||||
|
||||
|
||||
ErrorExit:
|
||||
|
||||
ACPI_FREE (AmlBuffer);
|
||||
ACPI_FREE (MethodObj);
|
||||
return (Status);
|
||||
}
|
||||
|
||||
ACPI_EXPORT_SYMBOL (AcpiInstallMethod)
|
||||
|
@ -298,6 +298,7 @@ typedef struct acpi_namespace_node
|
||||
#define ANOBJ_METHOD_LOCAL 0x08 /* Node is a method local */
|
||||
#define ANOBJ_SUBTREE_HAS_INI 0x10 /* Used to optimize device initialization */
|
||||
#define ANOBJ_EVALUATED 0x20 /* Set on first evaluation of node */
|
||||
#define ANOBJ_ALLOCATED_BUFFER 0x40 /* Method AML buffer is dynamic (InstallMethod) */
|
||||
|
||||
#define ANOBJ_IS_EXTERNAL 0x08 /* iASL only: This object created via External() */
|
||||
#define ANOBJ_METHOD_NO_RETVAL 0x10 /* iASL only: Method has no return value */
|
||||
|
@ -334,6 +334,10 @@ AcpiGetObjectInfo (
|
||||
ACPI_HANDLE Handle,
|
||||
ACPI_BUFFER *ReturnBuffer);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiInstallMethod (
|
||||
UINT8 *Buffer);
|
||||
|
||||
ACPI_STATUS
|
||||
AcpiGetNextObject (
|
||||
ACPI_OBJECT_TYPE Type,
|
||||
|
@ -582,7 +582,7 @@ typedef enum
|
||||
|
||||
#define AML_METHOD_ARG_COUNT 0x07
|
||||
#define AML_METHOD_SERIALIZED 0x08
|
||||
#define AML_METHOD_SYNCH_LEVEL 0xF0
|
||||
#define AML_METHOD_SYNC_LEVEL 0xF0
|
||||
|
||||
/* METHOD_FLAGS_ARG_COUNT is not used internally, define additional flags */
|
||||
|
||||
|
@ -189,6 +189,36 @@ unsigned char Oem1Code[] =
|
||||
0x31,0x00,0x70,0x01,0x5F,0x58,0x54,0x32, /* 00000030 "1.p._XT2" */
|
||||
};
|
||||
|
||||
/*
|
||||
* Example installable control method
|
||||
*
|
||||
* DefinitionBlock ("", "DSDT", 2, "Intel", "MTHDTEST", 0x20090512)
|
||||
* {
|
||||
* Method (\_SI_._T97, 1, Serialized)
|
||||
* {
|
||||
* Store ("Example installed method", Debug)
|
||||
* Store (Arg0, Debug)
|
||||
* Return ()
|
||||
* }
|
||||
* }
|
||||
*
|
||||
* Compiled byte code below.
|
||||
*/
|
||||
unsigned char MethodCode[] =
|
||||
{
|
||||
0x44,0x53,0x44,0x54,0x53,0x00,0x00,0x00, /* 00000000 "DSDTS..." */
|
||||
0x02,0xF9,0x49,0x6E,0x74,0x65,0x6C,0x00, /* 00000008 "..Intel." */
|
||||
0x4D,0x54,0x48,0x44,0x54,0x45,0x53,0x54, /* 00000010 "MTHDTEST" */
|
||||
0x12,0x05,0x09,0x20,0x49,0x4E,0x54,0x4C, /* 00000018 "... INTL" */
|
||||
0x22,0x04,0x09,0x20,0x14,0x2E,0x2E,0x5F, /* 00000020 "".. ..._" */
|
||||
0x54,0x49,0x5F,0x5F,0x54,0x39,0x37,0x09, /* 00000028 "SI__T97." */
|
||||
0x70,0x0D,0x45,0x78,0x61,0x6D,0x70,0x6C, /* 00000030 "p.Exampl" */
|
||||
0x65,0x20,0x69,0x6E,0x73,0x74,0x61,0x6C, /* 00000038 "e instal" */
|
||||
0x6C,0x65,0x64,0x20,0x6D,0x65,0x74,0x68, /* 00000040 "led meth" */
|
||||
0x6F,0x64,0x00,0x5B,0x31,0x70,0x68,0x5B, /* 00000048 "od.[1ph[" */
|
||||
0x31,0xA4,0x00,
|
||||
};
|
||||
|
||||
|
||||
/*
|
||||
* We need a local FADT so that the hardware subcomponent will function,
|
||||
@ -427,7 +457,26 @@ AeInstallTables (
|
||||
Status = AcpiInitializeTables (Tables, ACPI_MAX_INIT_TABLES, TRUE);
|
||||
Status = AcpiReallocateRootTable ();
|
||||
Status = AcpiLoadTables ();
|
||||
return (Status);
|
||||
|
||||
/*
|
||||
* Test run-time control method installation. Do it twice to test code
|
||||
* for an existing name.
|
||||
*/
|
||||
Status = AcpiInstallMethod (MethodCode);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
AcpiOsPrintf ("%s, Could not install method\n",
|
||||
AcpiFormatException (Status));
|
||||
}
|
||||
|
||||
Status = AcpiInstallMethod (MethodCode);
|
||||
if (ACPI_FAILURE (Status))
|
||||
{
|
||||
AcpiOsPrintf ("%s, Could not install method\n",
|
||||
AcpiFormatException (Status));
|
||||
}
|
||||
|
||||
return (AE_OK);
|
||||
}
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user