Source code of Windows XP (NT5)
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.
 
 
 
 
 
 

1903 lines
53 KiB

/*** parser.c - AML Parser
*
* Copyright (c) 1996,1997 Microsoft Corporation
* Author: Michael Tsang (MikeTs)
* Created 06/13/97
*
* MODIFICATION HISTORY
*/
#include "pch.h"
#ifdef LOCKABLE_PRAGMA
#pragma ACPI_LOCKABLE_DATA
#pragma ACPI_LOCKABLE_CODE
#endif
/***LP ParseScope - Parse a scope
*
* ENTRY
* pctxt -> CTXT
* pscope -> SCOPE
* rc - status code
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseScope(PCTXT pctxt, PSCOPE pscope, NTSTATUS rc)
{
TRACENAME("PARSESCOPE")
ULONG dwStage = ((rc == STATUS_SUCCESS) || (rc == AMLISTA_BREAK))?
(pscope->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 2;
ENTER(2, ("ParseScope(Stage=%d,pctxt=%p,pbOp=%p,pscope=%p,rc=%x)\n",
dwStage, pctxt, pctxt->pbOp, pscope, rc));
ASSERT(pscope->FrameHdr.dwSig == SIG_SCOPE);
switch (dwStage)
{
case 0:
//
// Stage 0: Do debug print if necessary.
//
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PrintIndent(pctxt);
PRINTF("{");
gDebugger.iPrintLevel++;
pscope->FrameHdr.dwfFrame |= SCOPEF_FIRST_TERM;
}
#endif
//
// There is nothing blockable, so continue to next stage.
//
pscope->FrameHdr.dwfFrame++;
case 1:
Stage1:
//
// Stage 1: Parse next opcode.
//
if (rc == AMLISTA_BREAK)
{
pctxt->pbOp = pscope->pbOpEnd;
rc = STATUS_SUCCESS;
}
else
{
while (pctxt->pbOp < pscope->pbOpEnd)
{
#ifdef DEBUGGER
gDebugger.pbUnAsm = pctxt->pbOp;
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (pscope->FrameHdr.dwfFrame & SCOPEF_FIRST_TERM)
{
pscope->FrameHdr.dwfFrame &= ~SCOPEF_FIRST_TERM;
}
else if (gDebugger.dwfDebugger & DBGF_STEP_OVER)
{
gDebugger.dwfDebugger &= ~DBGF_STEP_OVER;
AMLIDebugger(FALSE);
}
}
if ((gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES)) &&
(*pctxt->pbOp != OP_PACKAGE))
{
PrintIndent(pctxt);
}
#endif
//
// Discard result of previous term if any.
//
FreeDataBuffs(pscope->pdataResult, 1);
if (((rc = ParseOpcode(pctxt, pscope->pbOpEnd,
pscope->pdataResult)) !=
STATUS_SUCCESS) ||
(&pscope->FrameHdr !=
(PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
}
if (rc == AMLISTA_BREAK)
{
pctxt->pbOp = pscope->pbOpEnd;
rc = STATUS_SUCCESS;
}
else if ((rc == AMLISTA_PENDING) ||
(&pscope->FrameHdr !=
(PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
else if ((rc == STATUS_SUCCESS) &&
(pctxt->pbOp < pscope->pbOpEnd))
{
goto Stage1;
}
}
//
// If we come here, there was no more opcode in this scope, so
// continue to next stage.
//
pscope->FrameHdr.dwfFrame++;
case 2:
//
// Stage 2: clean up.
//
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
gDebugger.iPrintLevel--;
PrintIndent(pctxt);
PRINTF("}");
}
#endif
pctxt->pnsScope = pscope->pnsPrevScope;
pctxt->powner = pscope->pownerPrev;
pctxt->pheapCurrent = pscope->pheapPrev;
if (pscope->pbOpRet != NULL)
{
pctxt->pbOp = pscope->pbOpRet;
}
PopFrame(pctxt);
}
EXIT(2, ("ParseScope=%x\n", rc));
return rc;
} //ParseScope
/***LP ParseNestedContext - Parse and evaluate a nested context
*
* ENTRY
* pctxt -> CTXT
* pcall -> CALL
* rc - status code
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseNestedContext(PCTXT pctxt, PNESTEDCTXT pnctxt, NTSTATUS rc)
{
TRACENAME("PARSENESTEDCONTEXT")
ENTER(2, ("ParseNestedContext(pctxt=%x,pnctxt=%x,rc=%x)\n",
pctxt, pnctxt, rc));
ASSERT(pctxt->dwfCtxt & CTXTF_NEST_EVAL);
if ((rc == STATUS_SUCCESS) && (pnctxt->pdataCallBack != NULL))
{
rc = DupObjData(gpheapGlobal, pnctxt->pdataCallBack, &pnctxt->Result);
}
AsyncCallBack(pctxt, rc);
FreeDataBuffs(&pnctxt->Result, 1);
pctxt->dwfCtxt &= ~CTXTF_ASYNC_EVAL;
pctxt->dwfCtxt |= pnctxt->dwfPrevCtxt & CTXTF_ASYNC_EVAL;
pctxt->pnctxt = pnctxt->pnctxtPrev;
PopFrame(pctxt);
EXIT(2, ("ParseNestedContext=%x (rcEval=%x)\n", AMLISTA_DONE, rc));
return AMLISTA_DONE;
} //ParseNestedContext
/***LP ParseCall - Parse and evaluate a method call
*
* ENTRY
* pctxt -> CTXT
* pcall -> CALL
* rc - status code
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseCall(PCTXT pctxt, PCALL pcall, NTSTATUS rc)
{
TRACENAME("PARSECALL")
ULONG dwStage = (rc == STATUS_SUCCESS)?
(pcall->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 4;
PMETHODOBJ pm;
POBJOWNER powner;
ENTER(2, ("ParseCall(Stage=%d,pctxt=%x,pbOp=%x,pcall=%x,rc=%x)\n",
dwStage, pctxt, pctxt->pbOp, pcall, rc));
ASSERT(pcall->FrameHdr.dwSig == SIG_CALL);
pm = (pcall->pnsMethod != NULL)?
(PMETHODOBJ)pcall->pnsMethod->ObjData.pbDataBuff: NULL;
switch (dwStage)
{
case 0:
//
// Stage 0: Print debug stuff if necessary.
//
pcall->FrameHdr.dwfFrame++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("(");
}
#endif
case 1:
Stage1:
//
// Stage 1: Parse arguments.
//
while (pcall->iArg < pcall->icArgs)
{
//
// There are still arguments, parse it.
//
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (pcall->iArg > 0)
{
PRINTF(",");
}
}
#endif
rc = ParseArg(pctxt, 'C', &pcall->pdataArgs[pcall->iArg++]);
if ((rc != STATUS_SUCCESS) ||
(&pcall->FrameHdr !=
(PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
}
if ((rc != STATUS_SUCCESS) ||
(&pcall->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
else if (pcall->iArg < pcall->icArgs)
{
goto Stage1;
}
//
// If we come here, there is no more argument, so we can fall
// through to the next stage.
//
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF(")");
}
#endif
pcall->FrameHdr.dwfFrame++;
case 2:
//
// Stage 2: Acquire mutex if necessary
//
pcall->FrameHdr.dwfFrame++;
if(pm)
{
if (pm->bMethodFlags & METHOD_SERIALIZED)
{
PACQUIRE pacq;
if ((rc = PushFrame(pctxt, SIG_ACQUIRE, sizeof(ACQUIRE),
ParseAcquire, &pacq)) == STATUS_SUCCESS)
{
pacq->pmutex = &pm->Mutex;
pacq->wTimeout = 0xffff;
pacq->pdataResult = pcall->pdataResult;
}
break;
}
}
else
{
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED, ("ParseCall: pcall->pnsMethod == NULL"));
break;
}
case 3:
//
// Stage 3: Invoke the method.
//
pcall->FrameHdr.dwfFrame++;
//
// If we come here, we must have acquired the serialization mutex.
//
if (pcall->FrameHdr.dwfFrame & CALLF_NEED_MUTEX)
{
pcall->FrameHdr.dwfFrame |= CALLF_ACQ_MUTEX;
}
if ((rc = NewObjOwner(pctxt->pheapCurrent, &powner)) ==
STATUS_SUCCESS)
{
pcall->pownerPrev = pctxt->powner;
pctxt->powner = powner;
pcall->pcallPrev = pctxt->pcall;
pctxt->pcall = pcall;
pcall->FrameHdr.dwfFrame |= CALLF_INVOKE_CALL;
rc = PushScope(pctxt, pm->abCodeBuff,
pcall->pnsMethod->ObjData.pbDataBuff +
pcall->pnsMethod->ObjData.dwDataLen,
pctxt->pbOp,
pcall->pnsMethod,
powner,
pctxt->pheapCurrent,
pcall->pdataResult);
break;
}
case 4:
//
// Stage 4: Clean up.
//
pcall->FrameHdr.dwfFrame++;
if (rc == AMLISTA_RETURN)
{
rc = STATUS_SUCCESS;
}
if (pcall->pdataResult->dwfData & DATAF_BUFF_ALIAS)
{
OBJDATA data;
//
// The result object is an alias. It could be an alias of
// ArgX or LocalX. We better dup it because we are going
// to blow ArgX and LocalX away.
//
DupObjData(pctxt->pheapCurrent, &data, pcall->pdataResult);
FreeDataBuffs(pcall->pdataResult, 1);
MoveObjData(pcall->pdataResult, &data);
}
FreeDataBuffs(pcall->Locals, MAX_NUM_LOCALS);
if (pcall->FrameHdr.dwfFrame & CALLF_INVOKE_CALL)
{
FreeObjOwner(pctxt->powner, FALSE);
pctxt->powner = pcall->pownerPrev;
pctxt->pcall = pcall->pcallPrev;
}
else if (pcall->pnsMethod == NULL)
{
//
// This is the dummy call frame for LoadDDB. All NameSpace
// objects created by LoadDDB are persistent (i.e. don't
// destroy them).
//
pctxt->powner = pcall->pownerPrev;
pctxt->pcall = pcall->pcallPrev;
}
if (pcall->pdataArgs != NULL)
{
FreeDataBuffs(pcall->pdataArgs, pcall->icArgs);
FREEODOBJ(pcall->pdataArgs);
}
if (pcall->FrameHdr.dwfFrame & CALLF_ACQ_MUTEX)
{
ReleaseASLMutex(pctxt, &pm->Mutex);
}
case 5:
//
// Stage 5: This stage is for the dummy call frame to exit.
//
PopFrame(pctxt);
}
EXIT(2, ("ParseCall=%x\n", rc));
return rc;
} //ParseCall
/***LP ParseTerm - Parse and evaluate an ASL term
*
* ENTRY
* pctxt -> CTXT
* pterm -> TERM
* rc - status code
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseTerm(PCTXT pctxt, PTERM pterm, NTSTATUS rc)
{
TRACENAME("PARSETERM")
ULONG dwStage = (rc == STATUS_SUCCESS)?
(pterm->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 4;
int i;
ENTER(2, ("ParseTerm(Term=%s,Stage=%d,pctxt=%x,pbOp=%x,pterm=%x,rc=%x)\n",
pterm->pamlterm->pszTermName, dwStage, pctxt, pctxt->pbOp, pterm,
rc));
ASSERT(pterm->FrameHdr.dwSig == SIG_TERM);
switch (dwStage)
{
case 0:
//
// Stage 0: Parse package length if any.
//
pterm->FrameHdr.dwfFrame++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (pterm->pamlterm->dwOpcode == OP_PACKAGE)
{
gDebugger.iPrintLevel++;
PrintIndent(pctxt);
}
PRINTF("%s", pterm->pamlterm->pszTermName);
if (pterm->icArgs > 0)
{
PRINTF("(");
}
}
#endif
if (pterm->pamlterm->dwfOpcode & OF_VARIABLE_LIST)
{
ParsePackageLen(&pctxt->pbOp, &pterm->pbOpEnd);
}
case 1:
Stage1:
//
// Stage 1: Parse arguments.
//
while (pterm->iArg < pterm->icArgs)
{
i = pterm->iArg++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (i > 0)
{
PRINTF(",");
}
}
#endif
rc = ParseArg(pctxt, pterm->pamlterm->pszArgTypes[i],
&pterm->pdataArgs[i]);
if ((rc != STATUS_SUCCESS) ||
(&pterm->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
}
if ((rc != STATUS_SUCCESS) ||
(&pterm->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
else if (pterm->iArg < pterm->icArgs)
{
goto Stage1;
}
//
// If we come here, there is no more argument, so we can fall
// through to the next stage.
//
pterm->FrameHdr.dwfFrame++;
case 2:
//
// Stage 2: Execute the term and prepare to go to the next stage.
//
pterm->FrameHdr.dwfFrame++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (pterm->icArgs > 0)
{
PRINTF(")");
}
}
#endif
if ((pterm->pamlterm->dwfOpcode & OF_CALLBACK_EX) &&
(pterm->pamlterm->pfnCallBack != NULL))
{
((PFNOPEX)pterm->pamlterm->pfnCallBack)(
EVTYPE_OPCODE_EX,
OPEXF_NOTIFY_PRE,
pterm->pamlterm->dwOpcode,
pterm->pnsObj,
pterm->pamlterm->dwCBData);
}
if (pterm->pamlterm->pfnOpcode != NULL)
{
if (((rc = pterm->pamlterm->pfnOpcode(pctxt, pterm)) !=
STATUS_SUCCESS) ||
(&pterm->FrameHdr != (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd))
{
break;
}
}
case 3:
//
// Stage 3: Do Opcode Callback if any
//
pterm->FrameHdr.dwfFrame++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if ((pterm->pamlterm->dwOpcode != OP_BUFFER) &&
(pterm->pamlterm->dwOpcode != OP_PACKAGE))
{
if (pterm->pamlterm->dwTermClass == TC_OPCODE_TYPE2)
{
PRINTF("=");
PrintObject(pterm->pdataResult);
}
}
}
if (gDebugger.dwfDebugger & DBGF_SINGLE_STEP)
{
gDebugger.dwfDebugger &= ~DBGF_SINGLE_STEP;
AMLIDebugger(FALSE);
}
else
{
#endif
if (pterm->pamlterm->pfnCallBack != NULL)
{
if (pterm->pamlterm->dwfOpcode & OF_CALLBACK_EX)
{
((PFNOPEX)pterm->pamlterm->pfnCallBack)(
EVTYPE_OPCODE_EX,
OPEXF_NOTIFY_POST,
pterm->pamlterm->dwOpcode,
pterm->pnsObj,
pterm->pamlterm->dwCBData);
}
else
{
pterm->pamlterm->pfnCallBack(
EVTYPE_OPCODE,
pterm->pamlterm->dwOpcode,
pterm->pnsObj,
pterm->pamlterm->dwCBData
);
}
}
#ifdef DEBUGGER
}
#endif
case 4:
//
// Stage 4: Clean up.
//
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
if (pterm->pamlterm->dwOpcode == OP_PACKAGE)
{
gDebugger.iPrintLevel--;
}
}
#endif
if (pterm->pdataArgs != NULL)
{
FreeDataBuffs(pterm->pdataArgs, pterm->icArgs);
FREEODOBJ(pterm->pdataArgs);
}
PopFrame(pctxt);
}
EXIT(2, ("ParseTerm=%x\n", rc));
return rc;
} //ParseTerm
/***LP ParseAcquire - Parse and evaluate an Acquire term
*
* ENTRY
* pctxt -> CTXT
* pacq - ACQUIRE
* rc - status code
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseAcquire(PCTXT pctxt, PACQUIRE pacq, NTSTATUS rc)
{
TRACENAME("PARSEACQUIRE")
ULONG dwStage = (rc == STATUS_SUCCESS)?
(pacq->FrameHdr.dwfFrame & FRAMEF_STAGE_MASK): 2;
ENTER(2, ("ParseAcquire(Stage=%d,pctxt=%x,pbOp=%x,pacq=%x,rc=%x)\n",
dwStage, pctxt, pctxt->pbOp, pacq, rc));
ASSERT(pacq->FrameHdr.dwSig == SIG_ACQUIRE);
switch (dwStage)
{
case 0:
//
// Stage 0: Acquire GlobalLock if necessary.
//
pacq->FrameHdr.dwfFrame++;
if (pacq->FrameHdr.dwfFrame & ACQF_NEED_GLOBALLOCK)
{
if ((rc = AcquireGL(pctxt)) != STATUS_SUCCESS)
{
break;
}
}
case 1:
//
// Stage 1: Acquire the mutex.
//
if (pacq->FrameHdr.dwfFrame & ACQF_NEED_GLOBALLOCK)
{
//
// If we come here, we must have acquired the global lock.
//
pacq->FrameHdr.dwfFrame |= ACQF_HAVE_GLOBALLOCK;
}
rc = AcquireASLMutex(pctxt, pacq->pmutex, pacq->wTimeout);
if (rc == AMLISTA_PENDING)
{
//
// If it is pending, we must release the global lock and
// retry the whole operation.
//
if (pacq->FrameHdr.dwfFrame & ACQF_HAVE_GLOBALLOCK)
{
pacq->FrameHdr.dwfFrame &= ~ACQF_HAVE_GLOBALLOCK;
if ((rc = ReleaseGL(pctxt)) == STATUS_SUCCESS)
{
pacq->FrameHdr.dwfFrame--;
}
else
{
pacq->FrameHdr.dwfFrame++;
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
("ParseAcquire: failed to release global lock (rc=%x)",
rc));
}
}
break;
}
else
{
if (pacq->FrameHdr.dwfFrame & ACQF_SET_RESULT)
{
pacq->pdataResult->dwDataType = OBJTYPE_INTDATA;
if (rc == AMLISTA_TIMEOUT)
{
pacq->pdataResult->uipDataValue = DATAVALUE_ONES;
rc = STATUS_SUCCESS;
}
else
{
pacq->pdataResult->uipDataValue = DATAVALUE_ZERO;
}
}
}
pacq->FrameHdr.dwfFrame++;
case 2:
//
// Stage 2: Clean up.
//
PopFrame(pctxt);
}
EXIT(2, ("ParseAcquire=%x\n", rc));
return rc;
} //ParseAcquire
/***LP ParseOpcode - Parse AML opcode
*
* ENTRY
* pctxt -> CTXT
* pbScopeEnd -> end of current scope
* pdataResult -> result object
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseOpcode(PCTXT pctxt, PUCHAR pbScopeEnd, POBJDATA pdataResult)
{
TRACENAME("PARSEOPCODE")
NTSTATUS rc = STATUS_SUCCESS;
PUCHAR pbOpTerm;
PAMLTERM pamlterm;
#ifdef DEBUGGER
int iBrkPt;
#endif
ENTER(2, ("ParseOpcode(pctxt=%x,pbOp=%x,pbScopeEnd=%x,pdataResult=%x)\n",
pctxt, pctxt->pbOp, pbScopeEnd, pdataResult));
ASSERT(pdataResult != NULL);
#ifdef DEBUGGER
if ((iBrkPt = CheckBP(pctxt->pbOp)) != -1)
{
PRINTF("\nHit Breakpoint %d.\n", iBrkPt);
AMLIDebugger(FALSE);
}
#endif
pbOpTerm = pctxt->pbOp;
if (*pctxt->pbOp == OP_EXT_PREFIX)
{
pctxt->pbOp++;
pamlterm = FindOpcodeTerm(*pctxt->pbOp, ExOpcodeTable);
}
else
{
pamlterm = OpcodeTable[*pctxt->pbOp];
}
if (pamlterm == NULL)
{
rc = AMLI_LOGERR(AMLIERR_INVALID_OPCODE,
("ParseOpcode: invalid opcode 0x%02x at 0x%08x",
*pctxt->pbOp, pctxt->pbOp));
}
else if (pamlterm->dwfOpcode & OF_DATA_OBJECT)
{
rc = ParseIntObj(&pctxt->pbOp, pdataResult, FALSE);
}
else if (pamlterm->dwfOpcode & OF_STRING_OBJECT)
{
rc = ParseString(&pctxt->pbOp, pdataResult, FALSE);
}
else if (pamlterm->dwfOpcode & OF_ARG_OBJECT)
{
rc = ParseArgObj(pctxt, pdataResult);
}
else if (pamlterm->dwfOpcode & OF_LOCAL_OBJECT)
{
rc = ParseLocalObj(pctxt, pdataResult);
}
else if (pamlterm->dwfOpcode & OF_NAME_OBJECT)
{
rc = ParseNameObj(pctxt, pdataResult);
}
else if (pamlterm->dwfOpcode & OF_DEBUG_OBJECT)
{
rc = AMLI_LOGERR(AMLIERR_FATAL,
("ParseOpcode: debug object cannot be evaluated"));
}
else
{
//
// Must be an ASL Term.
//
pctxt->pbOp++;
rc = PushTerm(pctxt, pbOpTerm, pbScopeEnd, pamlterm, pdataResult);
}
EXIT(2, ("ParseOpcode=%x (pbOp=%x,pamlterm=%x)\n",
rc, pctxt->pbOp, pamlterm));
return rc;
} //ParseOpcode
/***LP ParseArgObj - Parse and execute the ArgX instruction
*
* ENTRY
* pctxt -> CTXT
* pdataResult -> result object
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseArgObj(PCTXT pctxt, POBJDATA pdataResult)
{
TRACENAME("PARSEARGOBJ")
NTSTATUS rc = STATUS_SUCCESS;
int i;
ENTER(2, ("ParseArgObj(pctxt=%x,pbOp=%x,pdataResult=%x)\n",
pctxt, pctxt->pbOp, pdataResult));
ASSERT(pdataResult != NULL);
i = *pctxt->pbOp - OP_ARG0;
if (i >= pctxt->pcall->icArgs)
{
rc = AMLI_LOGERR(AMLIERR_ARG_NOT_EXIST,
("ParseArgObj: Arg%d does not exist", i));
}
else
{
CopyObjData(pdataResult, &pctxt->pcall->pdataArgs[i]);
pctxt->pbOp++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Arg%d=", i);
PrintObject(pdataResult);
}
#endif
}
EXIT(2, ("ParseArgObj=%x (pbOp=%x)\n", rc, pctxt->pbOp));
return rc;
} //ParseArgObj
/***LP ParseLocalObj - Parse and execute the LocalX instruction
*
* ENTRY
* pctxt -> CTXT
* pdataResult -> Result object
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseLocalObj(PCTXT pctxt, POBJDATA pdataResult)
{
TRACENAME("PARSELOCALOBJ")
NTSTATUS rc = STATUS_SUCCESS;
int i;
ENTER(2, ("ParseLocalObj(pctxt=%x,pbOp=%x,pdataResult=%x)\n",
pctxt, pctxt->pbOp, pdataResult));
ASSERT(pdataResult != NULL);
i = *pctxt->pbOp - OP_LOCAL0;
CopyObjData(pdataResult, &pctxt->pcall->Locals[i]);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger & (DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Local%d=", i);
PrintObject(pdataResult);
}
#endif
pctxt->pbOp++;
EXIT(2, ("ParseLocalObj=%x (pbOp=%x)\n", rc, pctxt->pbOp));
return rc;
} //ParseLocalObj
/***LP ParseNameObj - Parse and evaluate an AML name object
*
* ENTRY
* pctxt -> CTXT
* pdataResult -> result object
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseNameObj(PCTXT pctxt, POBJDATA pdataResult)
{
TRACENAME("PARSENAMEOBJ")
NTSTATUS rc = STATUS_SUCCESS;
PNSOBJ pns = NULL;
ENTER(2, ("ParseNameObj(pctxt=%x,pbOp=%x,pdataResult=%x)\n",
pctxt, pctxt->pbOp, pdataResult));
ASSERT(pdataResult != NULL);
rc = ParseAndGetNameSpaceObject(&pctxt->pbOp, pctxt->pnsScope, &pns, FALSE);
if (rc == STATUS_SUCCESS)
{
pns = GetBaseObject(pns);
if (pns->ObjData.dwDataType == OBJTYPE_METHOD)
{
rc = PushCall(pctxt, pns, pdataResult);
}
else
{
rc = ReadObject(pctxt, &pns->ObjData, pdataResult);
}
}
EXIT(2, ("ParseNameObj=%x\n", rc));
return rc;
} //ParseNameObj
/***LP ParseAndGetNameSpaceObject - Parse NameSpace path and get the object
*
* ENTRY
* ppbOp -> opcode pointer
* pnsScope - current scope
* ppns -> to hold the object found
* fAbsentOK - if TRUE, do not print error message when object is not
* found
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseAndGetNameSpaceObject(PUCHAR *ppbOp, PNSOBJ pnsScope,
PPNSOBJ ppns, BOOLEAN fAbsentOK)
{
TRACENAME("PARSEANDGETNAMESPACEOBJECT")
NTSTATUS rc;
char szNameBuff[MAX_NAME_LEN + 1];
ENTER(2, ("ParseAndGetNameSpaceObject(pbOp=%x,Scope=%s,ppns=%x,fAbsentOK=%x)\n",
*ppbOp, GetObjectPath(pnsScope), ppns, fAbsentOK));
if ((rc = ParseName(ppbOp, szNameBuff, sizeof(szNameBuff))) ==
STATUS_SUCCESS)
{
rc = GetNameSpaceObject(szNameBuff, pnsScope, ppns, 0);
if (rc == AMLIERR_OBJ_NOT_FOUND)
{
if (fAbsentOK)
{
rc = STATUS_SUCCESS;
*ppns = NULL;
}
else
{
rc = AMLI_LOGERR(rc,
("ParseAndGetNameSpaceObject: object %s not found",
szNameBuff));
}
}
}
EXIT(2, ("ParseAndGetNameSpaceObject=%x (Name=%s)\n", rc, szNameBuff));
return rc;
} //ParseAndGetNameSpaceObject
/***LP ParseArg - Parse and evaluate an argument
*
* ENTRY
* pctxt -> CTXT
* chArgType - expected argument type
* pdataArg -> argument object
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseArg(PCTXT pctxt, char chArgType, POBJDATA pdataArg)
{
TRACENAME("PARSEARG")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(2, ("ParseArg(pctxt=%x,pbOp=%x,ArgType=%c,pdataArg=%x)\n",
pctxt, pctxt->pbOp, chArgType, pdataArg));
ASSERT(pdataArg != NULL);
switch (chArgType)
{
case ARGTYPE_NAME:
rc = ParseObjName(&pctxt->pbOp, pdataArg, FALSE);
break;
case ARGTYPE_DATAOBJ:
if (((rc = ParseIntObj(&pctxt->pbOp, pdataArg, TRUE)) ==
AMLIERR_INVALID_OPCODE) &&
((rc = ParseString(&pctxt->pbOp, pdataArg, TRUE)) ==
AMLIERR_INVALID_OPCODE) &&
((*pctxt->pbOp == OP_BUFFER) || (*pctxt->pbOp == OP_PACKAGE)))
{
rc = PushTerm(pctxt, pctxt->pbOp, NULL,
OpcodeTable[*pctxt->pbOp], pdataArg);
pctxt->pbOp++;
}
break;
case ARGTYPE_BYTE:
rc = ParseInteger(&pctxt->pbOp, pdataArg, sizeof(UCHAR));
break;
case ARGTYPE_WORD:
rc = ParseInteger(&pctxt->pbOp, pdataArg, sizeof(USHORT));
break;
case ARGTYPE_DWORD:
rc = ParseInteger(&pctxt->pbOp, pdataArg, sizeof(ULONG));
break;
case ARGTYPE_SNAME:
rc = ParseSuperName(pctxt, pdataArg, FALSE);
break;
case ARGTYPE_SNAME2:
rc = ParseSuperName(pctxt, pdataArg, TRUE);
break;
case ARGTYPE_OPCODE:
rc = ParseOpcode(pctxt, NULL, pdataArg);
break;
default:
rc = AMLI_LOGERR(AMLIERR_ASSERT_FAILED,
("ParseArg: unexpected arguemnt type (%c)",
chArgType));
}
EXIT(2, ("ParseArg=%x\n", rc));
return rc;
} //ParseArg
/***LP ParseSuperName - Parse AML SuperName
*
* ENTRY
* pctxt -> CTXT
* pdata -> object data
* fAbsentOK - If TRUE, it is not an error for the object to be absent
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseSuperName(PCTXT pctxt, POBJDATA pdata, BOOLEAN fAbsentOK)
{
TRACENAME("PARSESUPERNAME")
NTSTATUS rc = STATUS_SUCCESS;
PAMLTERM pamlterm;
PNSOBJ pns = NULL;
int i;
ENTER(2, ("ParseSuperName(pctxt=%x,pbOp=%x,pdata=%x,fAbsentOK=%x)\n",
pctxt, pctxt->pbOp, pdata, fAbsentOK));
ASSERT(pdata != NULL);
if (*pctxt->pbOp == 0)
{
ASSERT(pdata->dwDataType == OBJTYPE_UNKNOWN);
pctxt->pbOp++;
}
else if ((*pctxt->pbOp == OP_EXT_PREFIX) &&
(*(pctxt->pbOp + 1) == EXOP_DEBUG))
{
pctxt->pbOp += 2;
pdata->dwDataType = OBJTYPE_DEBUG;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Debug");
}
#endif
}
else if ((pamlterm = OpcodeTable[*pctxt->pbOp]) == NULL)
{
rc = AMLI_LOGERR(AMLIERR_INVALID_SUPERNAME,
("ParseSuperName: invalid SuperName - 0x%02x at 0x%08x",
*pctxt->pbOp, pctxt->pbOp));
}
else if (pamlterm->dwfOpcode & OF_NAME_OBJECT)
{
rc = ParseAndGetNameSpaceObject(&pctxt->pbOp, pctxt->pnsScope, &pns,
fAbsentOK);
if (rc == STATUS_SUCCESS)
{
if (pns != NULL)
{
pdata->dwDataType = OBJTYPE_OBJALIAS;
pdata->pnsAlias = GetBaseObject(pns);
}
else
{
ASSERT(pdata->dwDataType == OBJTYPE_UNKNOWN);
}
}
}
else if (pamlterm->dwfOpcode & OF_ARG_OBJECT)
{
i = *pctxt->pbOp - OP_ARG0;
pctxt->pbOp++;
if (i < pctxt->pcall->icArgs)
{
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Arg%d", i);
}
#endif
pdata->dwDataType = OBJTYPE_DATAALIAS;
pdata->pdataAlias = GetBaseData(&pctxt->pcall->pdataArgs[i]);
}
else
{
rc = AMLI_LOGERR(AMLIERR_ARG_NOT_EXIST,
("ParseSuperName: Arg%d does not exist", i));
}
}
else if (pamlterm->dwfOpcode & OF_LOCAL_OBJECT)
{
i = *pctxt->pbOp - OP_LOCAL0;
pctxt->pbOp++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Local%d", i);
}
#endif
pdata->dwDataType = OBJTYPE_DATAALIAS;
pdata->pdataAlias = &pctxt->pcall->Locals[i];
}
else if (pamlterm->dwfOpcode & OF_REF_OBJECT)
{
rc = PushTerm(pctxt, pctxt->pbOp, NULL, pamlterm, pdata);
pctxt->pbOp++;
}
else
{
rc = AMLI_LOGERR(AMLIERR_INVALID_SUPERNAME,
("ParseSuperName: invalid SuperName %x at %x",
*pctxt->pbOp, pctxt->pbOp));
}
EXIT(2, ("ParseSuperName=%x\n", rc));
return rc;
} //ParseSuperName
/***LP ParseIntObj - Parse AML integer object
*
* ENTRY
* ppbOp -> opcode pointer
* pdataResult -> result object
* fErrOK - TRUE if error is OK
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseIntObj(PUCHAR *ppbOp, POBJDATA pdataResult, BOOLEAN fErrOK)
{
TRACENAME("PARSEINTOBJ")
NTSTATUS rc = STATUS_SUCCESS;
UCHAR bOp;
ENTER(2, ("ParseIntObj(pbOp=%x,pdataResult=%x,fErrOK=%x)\n",
*ppbOp, pdataResult, fErrOK));
ASSERT(pdataResult != NULL);
bOp = **ppbOp;
(*ppbOp)++;
pdataResult->dwDataType = OBJTYPE_INTDATA;
pdataResult->uipDataValue = 0;
switch (bOp)
{
case OP_ZERO:
pdataResult->uipDataValue = DATAVALUE_ZERO;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Zero");
}
#endif
break;
case OP_ONE:
pdataResult->uipDataValue = DATAVALUE_ONE;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("One");
}
#endif
break;
case OP_ONES:
pdataResult->uipDataValue = DATAVALUE_ONES;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Ones");
}
#endif
break;
case OP_REVISION:
pdataResult->uipDataValue = AMLI_REVISION;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("Revision");
}
#endif
break;
case OP_BYTE:
MEMCPY(&pdataResult->uipDataValue, *ppbOp, sizeof(UCHAR));
(*ppbOp) += sizeof(UCHAR);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("0x%x", pdataResult->uipDataValue);
}
#endif
break;
case OP_WORD:
MEMCPY(&pdataResult->uipDataValue, *ppbOp, sizeof(USHORT));
(*ppbOp) += sizeof(USHORT);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("0x%x", pdataResult->uipDataValue);
}
#endif
break;
case OP_DWORD:
MEMCPY(&pdataResult->uipDataValue, *ppbOp, sizeof(ULONG));
(*ppbOp) += sizeof(ULONG);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("0x%x", pdataResult->uipDataValue);
}
#endif
break;
default:
(*ppbOp)--;
if (fErrOK)
{
rc = AMLIERR_INVALID_OPCODE;
}
else
{
rc = AMLI_LOGERR(AMLIERR_INVALID_OPCODE,
("ParseIntObj: invalid opcode 0x%02x at 0x%08x",
**ppbOp, *ppbOp));
}
}
EXIT(2, ("ParseIntObj=%x (pbOp=%x,Value=%x)\n",
rc, *ppbOp, pdataResult->uipDataValue));
return rc;
} //ParseIntObj
/***LP ParseString - Parse AML string object
*
* ENTRY
* ppbOp -> opcode pointer
* pdataResult -> result object
* fErrOK - TRUE if error is OK
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseString(PUCHAR *ppbOp, POBJDATA pdataResult, BOOLEAN fErrOK)
{
TRACENAME("PARSESTRING")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(2, ("ParseString(pbOp=%x,pdataResult=%x,fErrOK=%x)\n",
*ppbOp, pdataResult, fErrOK));
ASSERT(pdataResult != NULL);
if (**ppbOp == OP_STRING)
{
(*ppbOp)++;
pdataResult->dwDataType = OBJTYPE_STRDATA;
pdataResult->dwDataLen = STRLEN((PSZ)*ppbOp) + 1;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PRINTF("\"%s\"", *ppbOp);
}
#endif
if ((pdataResult->pbDataBuff = NEWSDOBJ(gpheapGlobal,
pdataResult->dwDataLen)) ==
NULL)
{
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
("ParseString: failed to allocate string buffer"));
}
else
{
MEMCPY(pdataResult->pbDataBuff, *ppbOp, pdataResult->dwDataLen);
}
(*ppbOp) += pdataResult->dwDataLen;
}
else if (fErrOK)
{
rc = AMLIERR_INVALID_OPCODE;
}
else
{
rc = AMLI_LOGERR(AMLIERR_INVALID_OPCODE,
("ParseStrObj: invalid opcode 0x%02x at 0x%08x",
**ppbOp, *ppbOp));
}
EXIT(2, ("ParseString=%x (Value=%s)\n",
rc, pdataResult->pbDataBuff? (PSZ)pdataResult->pbDataBuff:
"<null>"));
return rc;
} //ParseString
/***LP ParseObjName - Parse AML object name
*
* ENTRY
* ppbOp -> opcode pointer
* pdata -> to hold name data
* fErrOK - TRUE if error is OK
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseObjName(PUCHAR *ppbOp, POBJDATA pdata, BOOLEAN fErrOK)
{
TRACENAME("PARSEOBJNAME")
NTSTATUS rc = STATUS_SUCCESS;
PAMLTERM pamlterm = OpcodeTable[**ppbOp];
char szNameBuff[MAX_NAME_LEN+1];
ENTER(2, ("ParseObjName(pbOp=%x,pdata=%x,fErrOK=%x)\n",
*ppbOp, pdata, fErrOK));
ASSERT(pdata != NULL);
if ((pamlterm == NULL) || !(pamlterm->dwfOpcode & OF_NAME_OBJECT))
{
if (fErrOK)
{
rc = AMLIERR_INVALID_OPCODE;
}
else
{
rc = AMLI_LOGERR(AMLIERR_INVALID_OPCODE,
("ParseObjName: invalid opcode 0x%02x at 0x%08x",
**ppbOp, *ppbOp));
}
}
else if ((rc = ParseName(ppbOp, szNameBuff, sizeof(szNameBuff))) ==
STATUS_SUCCESS)
{
pdata->dwDataType = OBJTYPE_STRDATA;
pdata->dwDataLen = STRLEN(szNameBuff) + 1;
if ((pdata->pbDataBuff = (PUCHAR)NEWSDOBJ(gpheapGlobal,
pdata->dwDataLen)) == NULL)
{
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
("ParseObjName: failed to allocate name buffer - %s",
szNameBuff));
}
else
{
MEMCPY(pdata->pbDataBuff, szNameBuff, pdata->dwDataLen);
}
}
EXIT(2, ("ParseObjName=%x (Name=%s)\n", rc, szNameBuff));
return rc;
} //ParseObjName
/***LP ParseName - Parse AML name
*
* ENTRY
* ppbOp -> opcode pointer
* pszBuff -> to hold parsed name
* dwLen - buffer length
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseName(PUCHAR *ppbOp, PSZ pszBuff, ULONG dwLen)
{
TRACENAME("PARSENAME")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(2, ("ParseName(pbOp=%x,pszBuff=%x,Len=%d)\n",
*ppbOp, pszBuff, dwLen));
if (**ppbOp == OP_ROOT_PREFIX)
{
if (dwLen > 1)
{
STRCPY(pszBuff, "\\");
(*ppbOp)++;
rc = ParseNameTail(ppbOp, pszBuff, dwLen);
}
else
{
rc = AMLI_LOGERR(AMLIERR_NAME_TOO_LONG,
("ParseName: name too long - \"%s\"", pszBuff));
}
}
else if (**ppbOp == OP_PARENT_PREFIX)
{
if (dwLen > 1)
{
int i;
STRCPY(pszBuff, "^");
for ((*ppbOp)++, i = 1;
(i < (int)dwLen) && (**ppbOp == OP_PARENT_PREFIX);
(*ppbOp)++, i++)
{
pszBuff[i] = '^';
}
pszBuff[i] = '\0';
if (**ppbOp == OP_PARENT_PREFIX)
{
rc = AMLI_LOGERR(AMLIERR_NAME_TOO_LONG,
("ParseName: name too long - \"%s\"",
pszBuff));
}
else
{
rc = ParseNameTail(ppbOp, pszBuff, dwLen);
}
}
else
{
rc = AMLI_LOGERR(AMLIERR_NAME_TOO_LONG,
("ParseName: name too long - \"%s\"", pszBuff));
}
}
else if (dwLen > 0)
{
pszBuff[0] = '\0';
rc = ParseNameTail(ppbOp, pszBuff, dwLen);
}
else
{
rc = AMLI_LOGERR(AMLIERR_NAME_TOO_LONG,
("ParseName: name too long - \"%s\"", pszBuff));
}
#ifdef DEBUGGER
if ((rc == STATUS_SUCCESS) &&
(gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES)))
{
PRINTF("%s", pszBuff);
}
#endif
EXIT(2, ("ParseName=%x (Name=%s)\n", rc, pszBuff));
return rc;
} //ParseName
/***LP ParseNameTail - Parse AML name tail
*
* ENTRY
* ppbOp -> opcode pointer
* pszBuff -> to hold parsed name
* dwLen - buffer length
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseNameTail(PUCHAR *ppbOp, PSZ pszBuff, ULONG dwLen)
{
TRACENAME("PARSENAMETAIL")
NTSTATUS rc = STATUS_SUCCESS;
int iLen;
int icNameSegs = 0;
ENTER(2, ("ParseNameTail(pbOp=%x,Name=%s,Len=%d)\n",
*ppbOp, pszBuff, dwLen));
//
// We do not check for invalid NameSeg characters here and assume that
// the compiler does its job not generating it.
//
iLen = STRLEN(pszBuff);
if (**ppbOp == '\0')
{
//
// There is no NameTail (i.e. either NULL name or name with just
// prefixes.
//
(*ppbOp)++;
}
else if (**ppbOp == OP_MULTI_NAME_PREFIX)
{
(*ppbOp)++;
icNameSegs = (int)**ppbOp;
(*ppbOp)++;
}
else if (**ppbOp == OP_DUAL_NAME_PREFIX)
{
(*ppbOp)++;
icNameSegs = 2;
}
else
icNameSegs = 1;
while ((icNameSegs > 0) && (iLen + sizeof(NAMESEG) < dwLen))
{
STRCPYN(&pszBuff[iLen], (PSZ)(*ppbOp), sizeof(NAMESEG));
iLen += sizeof(NAMESEG);
(*ppbOp) += sizeof(NAMESEG);
icNameSegs--;
if ((icNameSegs > 0) && (iLen + 1 < (int)dwLen))
{
STRCPY(&pszBuff[iLen], ".");
iLen++;
}
}
if (icNameSegs > 0)
{
rc = AMLI_LOGERR(AMLIERR_NAME_TOO_LONG,
("ParseNameTail: name too long - %s", pszBuff));
}
EXIT(2, ("ParseNameTail=%x (Name=%s)\n", rc, pszBuff));
return rc;
} //ParseNameTail
/***LP ParseInteger - Parse AML integer object
*
* ENTRY
* ppbOp -> opcode pointer
* pdata -> to hold data
* dwDataLen - data length in bytes
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseInteger(PUCHAR *ppbOp, POBJDATA pdata, ULONG dwDataLen)
{
TRACENAME("PARSEINTEGER")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(2, ("ParseInteger(pbOp=%x,pdata=%x,DataLen=%d)\n",
*ppbOp, pdata, dwDataLen));
ASSERT(pdata != NULL);
pdata->dwDataType = OBJTYPE_INTDATA;
pdata->uipDataValue = 0;
MEMCPY(&pdata->uipDataValue, *ppbOp, dwDataLen);
(*ppbOp) += dwDataLen;
#ifdef DEBUGGER
if ((rc == STATUS_SUCCESS) &&
(gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES)))
{
PRINTF("0x%x", pdata->uipDataValue);
}
#endif
EXIT(2, ("ParseInteger=%x (Value=%x,pbOp=%x)\n",
rc, pdata->uipDataValue, *ppbOp));
return rc;
} //ParseInteger
/***LP ParseField - Parse AML field data
*
* ENTRY
* pctxt -> CTXT
* pnsParent -> parent
* pdwFieldFlags -> field flags
* pdwBitPos -> to hold the bit position parsed
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseField(PCTXT pctxt, PNSOBJ pnsParent, PULONG pdwFieldFlags,
PULONG pdwBitPos)
{
TRACENAME("PARSEFIELD")
NTSTATUS rc = STATUS_SUCCESS;
char szName[sizeof(NAMESEG) + 1];
ENTER(2, ("ParseField(pctxt=%x,pbOp=%x,pnsParent=%x,FieldFlags=%x,BitPos=%x)\n",
pctxt, pctxt->pbOp, pnsParent, *pdwFieldFlags, *pdwBitPos));
if (*pctxt->pbOp == 0x01)
{
pctxt->pbOp++;
*pdwFieldFlags &= ~ACCTYPE_MASK;
*pdwFieldFlags |= *pctxt->pbOp & ACCTYPE_MASK;
pctxt->pbOp++;
*pdwFieldFlags &= ~ACCATTRIB_MASK;
*pdwFieldFlags |= (ULONG)*pctxt->pbOp << 8;
pctxt->pbOp++;
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PrintIndent(pctxt);
PRINTF("AccessAs(0x%x,0x%x)",
*pdwFieldFlags & 0xff, (*pdwFieldFlags >> 8) & 0xff);
}
#endif
}
else
{
ULONG dwcbBits, dwAccSize = ACCSIZE(*pdwFieldFlags);
PNSOBJ pns;
if (*pctxt->pbOp == 0)
{
szName[0] = '\0';
pctxt->pbOp++;
}
else
{
STRCPYN(szName, (PSZ)pctxt->pbOp, sizeof(NAMESEG));
pctxt->pbOp += sizeof(NAMESEG);
}
dwcbBits = ParsePackageLen(&pctxt->pbOp, NULL);
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PrintIndent(pctxt);
if (szName[0] == '\0')
{
if ((dwcbBits > 32) && (((*pdwBitPos + dwcbBits) % 8) == 0))
{
PRINTF("Offset(0x%x)", (*pdwBitPos + dwcbBits)/8);
}
else
{
PRINTF(",%d", dwcbBits);
}
}
else
{
PRINTF("%s,%d", szName, dwcbBits);
}
}
#endif
if ((rc = CreateNameSpaceObject(pctxt->pheapCurrent, szName,
pctxt->pnsScope, pctxt->powner, &pns,
0)) == STATUS_SUCCESS)
{
pns->ObjData.dwDataType = OBJTYPE_FIELDUNIT;
pns->ObjData.dwDataLen = sizeof(FIELDUNITOBJ);
if ((pns->ObjData.pbDataBuff = NEWFUOBJ(pctxt->pheapCurrent,
pns->ObjData.dwDataLen)) ==
NULL)
{
rc = AMLI_LOGERR(AMLIERR_OUT_OF_MEM,
("ParseField: failed to allocate FieldUnit object"));
}
else
{
PFIELDUNITOBJ pfu;
MEMZERO(pns->ObjData.pbDataBuff, pns->ObjData.dwDataLen);
pfu = (PFIELDUNITOBJ)pns->ObjData.pbDataBuff;
pfu->pnsFieldParent = pnsParent;
pfu->FieldDesc.dwFieldFlags = *pdwFieldFlags;
pfu->FieldDesc.dwByteOffset = (*pdwBitPos / (dwAccSize*8))*
dwAccSize;
pfu->FieldDesc.dwStartBitPos = *pdwBitPos -
pfu->FieldDesc.dwByteOffset*8;
pfu->FieldDesc.dwNumBits = dwcbBits;
(*pdwBitPos) += dwcbBits;
}
}
}
EXIT(2, ("ParseField=%x (Field=%s,BitPos=%x)\n", rc, szName, *pdwBitPos));
return rc;
} //ParseField
/***LP ParseFieldList - Parse the FieldUnit list
*
* ENTRY
* pctxt -> CTXT
* pbOpEnd -> end of field list
* pnsParent -> parent
* dwFieldFlags - field flags
* dwRegionLen - length of operation region (0xffffffff if no length limit)
*
* EXIT-SUCCESS
* returns STATUS_SUCCESS
* EXIT-FAILURE
* returns AMLIERR_ code
*/
NTSTATUS LOCAL ParseFieldList(PCTXT pctxt, PUCHAR pbOpEnd, PNSOBJ pnsParent,
ULONG dwFieldFlags, ULONG dwRegionLen)
{
TRACENAME("PARSESFIELDLIST")
NTSTATUS rc = STATUS_SUCCESS;
ULONG dwBitPos = 0;
ENTER(2, ("ParseFieldList(pctxt=%x,pbOp=%x,pnsParent=%x,FieldFlags=%x,RegionLen=%x)\n",
pctxt, pctxt->pbOp, pnsParent, dwFieldFlags, dwRegionLen));
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
PrintIndent(pctxt);
PRINTF("{");
gDebugger.iPrintLevel++;
}
#endif
while ((rc == STATUS_SUCCESS) && (pctxt->pbOp < pbOpEnd))
{
if ((rc = ParseField(pctxt, pnsParent, &dwFieldFlags, &dwBitPos)) ==
STATUS_SUCCESS)
{
#ifdef DEBUGGER
if ((gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES)) &&
(rc == STATUS_SUCCESS) &&
(pctxt->pbOp < pbOpEnd))
{
PRINTF(",");
}
#endif
if ((dwRegionLen != 0xffffffff) && ((dwBitPos + 7)/8 > dwRegionLen))
{
rc = AMLI_LOGERR(AMLIERR_INDEX_TOO_BIG,
("ParseFieldList: offset exceeds OpRegion range (Offset=0x%x, RegionLen=0x%x)",
(dwBitPos + 7)/8, dwRegionLen));
}
}
}
#ifdef DEBUGGER
if (gDebugger.dwfDebugger &
(DBGF_AMLTRACE_ON | DBGF_STEP_MODES))
{
gDebugger.iPrintLevel--;
PrintIndent(pctxt);
PRINTF("}");
}
#endif
EXIT(2, ("ParseFieldList=%x\n", rc));
return rc;
} //ParseFieldList
/***LP ParsePackageLen - parse package length
*
* ENTRY
* ppbOp -> instruction pointer
* ppbOpNext -> to hold pointer to next instruction (can be NULL)
*
* EXIT
* returns package length
*/
ULONG LOCAL ParsePackageLen(PUCHAR *ppbOp, PUCHAR *ppbOpNext)
{
TRACENAME("PARSEPACKAGELEN")
ULONG dwLen;
UCHAR bFollowCnt, i;
ENTER(2, ("ParsePackageLen(pbOp=%x,ppbOpNext=%x)\n", *ppbOp, ppbOpNext));
if (ppbOpNext != NULL)
*ppbOpNext = *ppbOp;
dwLen = (ULONG)(**ppbOp);
(*ppbOp)++;
bFollowCnt = (UCHAR)((dwLen & 0xc0) >> 6);
if (bFollowCnt != 0)
{
dwLen &= 0x0000000f;
for (i = 0; i < bFollowCnt; ++i)
{
dwLen |= (ULONG)(**ppbOp) << (i*8 + 4);
(*ppbOp)++;
}
}
if (ppbOpNext != NULL)
*ppbOpNext += dwLen;
EXIT(2, ("ParsePackageLen=%x (pbOp=%x,pbOpNext=%x)\n",
dwLen, *ppbOp, ppbOpNext? *ppbOpNext: 0));
return dwLen;
} //ParsePackageLen