ACPI!RunContext函数分析之ACPI!ParseTerm和ACPI!ParseScope和ACPI!ParseCall---AML语法分析--非常重要
1: kd> g
Breakpoint 47 hit
eax=89da334c ebx=89defef8 ecx=89da330a edx=00000000 esi=89defed8 edi=89dee000
eip=f741dc18 esp=f789a0ec ebp=f789a114 iopl=0 nv up ei pl zr na pe nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000246
ACPI!CreateNameSpaceObject:
f741dc18 55 push ebp
0: kd> kc
#
00 ACPI!CreateNameSpaceObject
01 ACPI!Name
02 ACPI!ParseTerm
03 ACPI!RunContext
04 ACPI!InsertReadyQueue
05 ACPI!RestartContext
06 ACPI!SyncLoadDDB
07 ACPI!AMLILoadDDB
08 ACPI!ACPIInitializeDDB
09 ACPI!ACPIInitializeDDBs
0a ACPI!ACPIInitialize
0b ACPI!ACPIInitStartACPI
0c ACPI!ACPIRootIrpStartDevice
0d ACPI!ACPIDispatchIrp
0e nt!IofCallDriver
0f nt!IopSynchronousCall
10 nt!IopStartDevice
11 nt!PipProcessStartPhase1
12 nt!PipProcessDevNodeTree
13 nt!PipDeviceActionWorker
14 nt!PipRequestDeviceAction
15 nt!IopInitializeBootDrivers
16 nt!IoInitSystem
17 nt!Phase1Initialization
18 nt!PspSystemThreadStartup
19 nt!KiThreadStartup
0: kd> dv
pheap = 0x89da3000
pszName = 0x89da3380 "\GPIC"
pnsScope = 0x89da3024
powner = 0x89da3330
ppns = 0x89defef8
dwfNS = 0
pns = 0x00000008
rc = 0n-146678759
pnsParent = 0x89da3380
iLen = 0n-1982189532
0: kd> dt _nsobj 0x89da3394
ACPI!_NSObj
+0x000 list : _List
+0x008 pnsParent : 0x89da3024 _NSObj
+0x00c pnsFirstChild : (null)
+0x010 dwNameSeg : 0x43495047
+0x014 hOwner : 0x89da3330 Void
+0x018 pnsOwnedNext : (null)
+0x01c ObjData : _ObjData
+0x030 Context : (null)
+0x034 dwRefCount : 0
0: kd> db 0x89da3394+10
89da33a4 47 50 49 43 30 33 da 89-00 00 00 00 00 00 00 00 GPIC03..........
NTSTATUS LOCAL Name(PCTXT pctxt, PTERM pterm)
{
TRACENAME("NAME")
NTSTATUS rc = STATUS_SUCCESS;
ENTER(2, ("Name(pctxt=%x,pbOp=%x,pterm=%x)\n", pctxt, pctxt->pbOp, pterm));
ASSERT(pterm->pdataArgs[0].dwDataType == OBJTYPE_STRDATA);
if ((rc = CreateNameSpaceObject(pctxt->pheapCurrent,
(PSZ)pterm->pdataArgs[0].pbDataBuff,
pctxt->pnsScope, pctxt->powner,
&pterm->pnsObj, 0)) == STATUS_SUCCESS)
{
MoveObjData(&pterm->pnsObj->ObjData, &pterm->pdataArgs[1]);
}
EXIT(2, ("Name=%x (pnsObj=%x)\n", rc, pterm->pnsObj));
return rc;
} //Name
VOID LOCAL MoveObjData(POBJDATA pdataDst, POBJDATA pdataSrc)
{
TRACENAME("MOVEOBJDATA")
ENTER(3, ("MoveObjData(Dest=%x,Src=%x)\n", pdataDst, pdataSrc));
ASSERT(pdataDst != NULL);
ASSERT(pdataSrc != NULL);
if (pdataDst != pdataSrc)
{
//
// We can only move an alias object or a base object with zero
// reference count or a base object with no data buffer.
//
ASSERT((pdataSrc->dwfData & DATAF_BUFF_ALIAS) ||
(pdataSrc->pbDataBuff == NULL) ||
(pdataSrc->dwRefCount == 0));
MEMCPY(pdataDst, pdataSrc, sizeof(OBJDATA));
MEMZERO(pdataSrc, sizeof(OBJDATA));
}
EXIT(3, ("MoveObjData!\n"));
} //MoveObjData
0: kd> dv
pdataDst = 0x89da33b0
pdataSrc = 0x89da3360
0: kd> dx -id 0,0,ffffffff89dd5240 -r1 ((ACPI!_ObjData *)0x89da3360)
((ACPI!_ObjData *)0x89da3360) : 0x89da3360 [Type: _ObjData *]
[+0x000] dwfData : 0x0 [Type: unsigned short]
[+0x002] dwDataType : 0x1 [Type: unsigned short]
[+0x004] dwRefCount : 0x0 [Type: unsigned long]
[+0x004] pdataBase : 0x0 [Type: _ObjData *]
[+0x008] dwDataValue : 0x0 [Type: unsigned long]
[+0x008] uipDataValue : 0x0 [Type: unsigned long]
[+0x008] pnsAlias : 0x0 [Type: _NSObj *]
[+0x008] pdataAlias : 0x0 [Type: _ObjData *]
[+0x008] powner : 0x0 [Type: void *]
[+0x00c] dwDataLen : 0x0 [Type: unsigned long]
[+0x010] pbDataBuff : 0x0 [Type: unsigned char *]
0: kd> dt _nsobj 0x89da3394
ACPI!_NSObj
+0x000 list : _List
+0x008 pnsParent : 0x89da3024 _NSObj
+0x00c pnsFirstChild : (null)
+0x010 dwNameSeg : 0x43495047
+0x014 hOwner : 0x89da3330 Void
+0x018 pnsOwnedNext : (null)
+0x01c ObjData : _ObjData
+0x030 Context : (null)
+0x034 dwRefCount : 0
0: kd> dx -id 0,0,ffffffff89dd5240 -r1 (*((ACPI!_ObjData *)0xffffffff89da33b0))
(*((ACPI!_ObjData *)0xffffffff89da33b0)) [Type: _ObjData]
[+0x000] dwfData : 0x0 [Type: unsigned short]
[+0x002] dwDataType : 0x1 [Type: unsigned short]
[+0x004] dwRefCount : 0x0 [Type: unsigned long]
[+0x004] pdataBase : 0x0 [Type: _ObjData *]
[+0x008] dwDataValue : 0x0 [Type: unsigned long]
[+0x008] uipDataValue : 0x0 [Type: unsigned long]
[+0x008] pnsAlias : 0x0 [Type: _NSObj *]
[+0x008] pdataAlias : 0x0 [Type: _ObjData *]
[+0x008] powner : 0x0 [Type: void *]
[+0x00c] dwDataLen : 0x0 [Type: unsigned long]
[+0x010] pbDataBuff : 0x0 [Type: unsigned char *]
while (!IsStackEmpty(pctxt))
{
CHKDEBUGGERREQ();
pfh = (PFRAMEHDR)pctxt->LocalHeap.pbHeapEnd;
ASSERT(pfh->pfnParse != NULL);
rc = pfh->pfnParse(pctxt, pfh, rc);
if ((rc == AMLISTA_PENDING) || (rc == AMLISTA_DONE))
{
break;
}
}
0: kd> dt _CTXT 89dee000
ACPI!_ctxt
+0x000 dwSig : 0x54585443
+0x004 pbCtxtEnd : 0x89df0000 "TSER"
+0x008 listCtxt : _List
+0x010 listQueue : _List
+0x018 pplistCtxtQueue : (null)
+0x01c plistResources : (null)
+0x020 dwfCtxt : 0x10
+0x024 pnsObj : (null)
+0x028 pnsScope : 0x89da3024 _NSObj
+0x02c powner : 0x89da3330 _objowner
+0x030 pcall : 0x89deff34 _call
+0x034 pnctxt : (null)
+0x038 dwSyncLevel : 0
+0x03c pbOp : 0xf74d74ea "???"
+0x040 Result : _ObjData
+0x054 pfnAsyncCallBack : 0xf741eeb5 void ACPI!EvalMethodComplete+0
+0x058 pdataCallBack : (null)
+0x05c pvContext : 0xf789a1bc Void
+0x060 Timer : _KTIMER
+0x088 Dpc : _KDPC
+0x0a8 pheapCurrent : 0x89da3000 _heap
+0x0ac CtxtData : _ctxtdata
+0x0bc LocalHeap : _heap
0: kd> dx -id 0,0,ffffffff89dd5240 -r1 (*((ACPI!_heap *)0xffffffff89dee0bc))
(*((ACPI!_heap *)0xffffffff89dee0bc)) [Type: _heap]
[+0x000] dwSig : 0x50414548 [Type: unsigned long]
[+0x004] pbHeapEnd : 0x89deff0c : 0x53 [Type: unsigned char *]
[+0x008] pheapHead : 0x89dee0bc [Type: _heap *]
[+0x00c] pheapNext : 0x0 [Type: _heap *]
[+0x010] pbHeapTop : 0x89dee0d4 : 0x0 [Type: unsigned char *]
[+0x014] plistFreeHeap : 0x0 [Type: _List *]
[+0x018] Heap [Type: _heapobjhdr]
0: kd> dt _FRAMEHDR 0x89deff0c
ACPI!_framehdr
+0x000 dwSig : 0x504f4353
+0x004 dwLen : 0x28
+0x008 dwfFrame : 1
+0x00c pfnParse : 0xf74274fd long ACPI!ParseScope+0
0: kd> dt _FRAMEHDR 0x89deff0c+28
ACPI!_framehdr
+0x000 dwSig : 0x4c4c4143
+0x004 dwLen : 0xcc
+0x008 dwfFrame : 4
+0x00c pfnParse : 0xf7427709 long ACPI!ParseCall+0
0: kd> t
eax=89deff00 ebx=f743a948 ecx=89dee000 edx=89da3000 esi=89dee000 edi=89deff0c
eip=f74274fd esp=f789a134 ebp=f789a158 iopl=0 nv up ei ng nz na po nc
cs=0008 ss=0010 ds=0023 es=0023 fs=0030 gs=0000 efl=00000282
ACPI!ParseScope:
f74274fd 55 push ebp
0: kd> kc
#
00 ACPI!ParseScope
01 ACPI!RunContext
02 ACPI!InsertReadyQueue
03 ACPI!RestartContext
04 ACPI!SyncLoadDDB
05 ACPI!AMLILoadDDB
06 ACPI!ACPIInitializeDDB
07 ACPI!ACPIInitializeDDBs
08 ACPI!ACPIInitialize
09 ACPI!ACPIInitStartACPI
0a ACPI!ACPIRootIrpStartDevice
0b ACPI!ACPIDispatchIrp
0c nt!IofCallDriver
0d nt!IopSynchronousCall
0e nt!IopStartDevice
0f nt!PipProcessStartPhase1
10 nt!PipProcessDevNodeTree
11 nt!PipDeviceActionWorker
12 nt!PipRequestDeviceAction
13 nt!IopInitializeBootDrivers
14 nt!IoInitSystem
15 nt!Phase1Initialization
16 nt!PspSystemThreadStartup
17 nt!KiThreadStartup
0: kd> dv
pctxt = 0x89dee000
pscope = 0x89deff0c
rc = 0n0
1. Scope 指令的 AML 编码
在 AML 二进制代码中,Scope 被编码为 0x10 操作码,后面接命名空间路径和 Scope 体内容:
ScopeOp (0x10) <NameString> <TermList>
解析时,ACPI 解释器会根据 NameString 定位 Scope,并将 TermList 解析到该命名空间下。
2. 命名空间查找算法
当 AML 代码运行时,对象查找遵循如下算法:
当前 Scope 查找目标对象。
如果未找到,递归查找父 Scope。
如果仍未找到,查找根 Scope(\)。
如果有 External 声明,则尝试解析外部对象。
这样保证了对象访问的灵活性和层次性。
3. Scope 的动态扩展
ACPI 支持运行时载入或扩展 ACPI 表(如热插拔设备),Scope 可以动态扩展命名空间树,实现设备热插拔、资源动态配置:
SSDT 载入后,Scope 体内对象自动挂载到命名空间树。
新增的设备可在 Scope 内定义,无需修改主 DSDT。
4. 方法覆盖和重载机制
方法名(如 _STA, _INI)如果在多个 Scope 下定义,操作系统会优先调用目标设备所在 Scope 下的方法,实现方法覆盖和多态。
六、Scope 的常见对象类型
Scope 内可以定义如下类型的对象:
Device:设备对象
Method:方法
Field/BankField/IndexField:寄存器/内存映射
OperationRegion:操作区
PowerResource:电源资源
ThermalZone:热区
Name:变量或常量
Alias:别名
Mutex/Event:同步对象
这些对象在 Scope 中拥有唯一命名和访问路径。
七、Scope 相关的 ACPI 预留命名空间
ACPI 标准定义了很多预留命名空间,Scope 经常用于这些空间:
\:根命名空间
_SB:系统总线
_SI:系统信息
_PR:处理器
_TZ:热区
_GL:全局锁
0: kd> dv
pctxt = 0x89dee000
pscope = 0x89deff0c
rc = 0n0
0: kd> dx -id 0,0,ffffffff89dd5240 -r1 ((ACPI!_scope *)0x89deff0c)
((ACPI!_scope *)0x89deff0c) : 0x89deff0c [Type: _scope *]
[+0x000] FrameHdr [Type: _framehdr]
[+0x010] pbOpEnd : 0xf74e5ca8 : 0x4d [Type: unsigned char *]
[+0x014] pbOpRet : 0x0 [Type: unsigned char *]
[+0x018] pnsPrevScope : 0x0 [Type: _NSObj *]
[+0x01c] pownerPrev : 0x0 [Type: _objowner *]
[+0x020] pheapPrev : 0x89da3000 [Type: _heap *]
[+0x024] pdataResult : 0x89dee040 [Type: _ObjData *]
0: kd> dx -id 0,0,ffffffff89dd5240 -r1 (*((ACPI!_framehdr *)0x89deff0c))
(*((ACPI!_framehdr *)0x89deff0c)) [Type: _framehdr]
[+0x000] dwSig : 0x504f4353 [Type: unsigned long]
[+0x004] dwLen : 0x28 [Type: unsigned long]
[+0x008] dwfFrame : 0x1 [Type: unsigned long]
[+0x00c] pfnParse : 0xf74274fd [Type: long (__cdecl*)(_ctxt *,void *,long)]
&