-
-
[原创][有码]键盘过滤中关于IOAPIC重定位表的学习笔记
-
发表于:
2011-6-10 18:09
17584
-
[原创][有码]键盘过滤中关于IOAPIC重定位表的学习笔记
#define IOAPIC_REGSEL_PHYSICAL_ADDRESS 0xfec00000
#define IOAPIC_WIN_PHYSICAL_ADDRESS \
IOAPIC_REGSEL_PHYSICAL_ADDRESS + 0x10
[COLOR="SeaGreen"]//根据中断描述表来定义个中断门的结构[/COLOR]
typedef struct _INTGATE
{
USHORT OffsetLow;
USHORT Selector;
UCHAR Reserved; [COLOR="SeaGreen"]//这个与是保留值,需要设置成NULL[/COLOR]
UCHAR Attributes;
USHORT OffsetHigh;
}INTGATE,*PINTGATE;
NTSTATUS
InsertNewInterruptRoutine(PVOID pNewRoutine,PULONG pulInterruptVectorNumber)
{
NTSTATUS ReturnStatus;
ULONG ulInterruptVectorNumber;
PVOID pInterruptTableAddress;
PINTGATE pstNewIntGate;
[COLOR="SeaGreen"]//检测参数的合法性[/COLOR]
if(!MmIsAddressValid(pNewRoutine))
return STATUS_INVALID_PARAMETER;
[COLOR="SeaGreen"]//获取idt表的地址[/COLOR]
ReturnStatus = GetIdtServiceTableAddress(&pInterruptTableAddress);
if(!NT_SUCCESS(ReturnStatus))
return ReturnStatus;
[COLOR="SeaGreen"]//枚举idt表[/COLOR]
for(ulInterruptVectorNumber=1;ulInterruptVectorNumber<INT_VECTOR_MAX_COUNT+1;ulInterruptVectorNumber++)
{
[COLOR="SeaGreen"]//判断中断门是否已经存在[/COLOR]
if(!IsInterruptVectorExisted(pInterruptTableAddress,ulInterruptVectorNumber))
break;
}
if(ulInterruptVectorNumber > INT_VECTOR_MAX_COUNT)
return STATUS_UNSUCCESSFUL;
[COLOR="SeaGreen"]//保存中断向量号[/COLOR]
*pulInterruptVectorNumber = ulInterruptVectorNumber;
[COLOR="SeaGreen"]//填写中断门结构[/COLOR]
pstNewIntGate = &((PINTGATE)pInterruptTableAddress)[ulInterruptVectorNumber];
pstNewIntGate->Reserved = NULL;
pstNewIntGate->Selector = 8; [COLOR="SeaGreen"]//在内核中的段选择子[/COLOR]
pstNewIntGate->Attributes = 0x80 | 0x08 | 0x06;
pstNewIntGate->OffsetLow = (USHORT)pNewRoutine;
pstNewIntGate->OffsetHigh = (USHORT)((ULONG)pNewRoutine >> sizeof(USHORT)*8);
return STATUS_SUCCESS;
}
BOOLEAN [COLOR="SeaGreen"]//判断中断门是否存在[/COLOR]
IsInterruptVectorExisted(PVOID pIdtAddress,ULONG ulInterruptVectorNumber)
{
PINTGATE pstIntGate;
[COLOR="YellowGreen"][COLOR="SeaGreen"]//检测idt地址是否有效[/COLOR][/COLOR]
if(!MmIsAddressValid(pIdtAddress))
return STATUS_INVALID_PARAMETER;
pstIntGate = &((PINTGATE)pIdtAddress)[ulInterruptVectorNumber];
[COLOR="SeaGreen"]//判断中断门的P位,也就是判断该调用们是否有效[/COLOR]
if(pstIntGate->Attributes & 0x80)
return TRUE;
return FALSE;
}
[COLOR="SeaGreen"]//获取IDT表的地址[/COLOR]
NTSTATUS
GetIdtServiceTableAddress(PVOID pIdtServiceTableAddressPointer)
{
USHORT wSelectorAndOffset[3];
ULONG ulUshortSize;
ulUshortSize = sizeof(USHORT);
__asm
{
pushad;
pushfd;
sidt [wSelectorAndOffset];
lea esi,dword ptr [wSelectorAndOffset];
add esi,[ulUshortSize]; [COLOR="SeaGreen"]//将指针移到段内偏移值上[/COLOR]
mov ebx,[pIdtServiceTableAddressPointer];
mov eax,dword ptr [esi];
mov dword ptr [ebx],eax;
popfd;
popad;
}
if(!(*(PULONG)pIdtServiceTableAddressPointer)) [COLOR="SeaGreen"]//如果获取失败的话,就返回不成功[/COLOR]
return STATUS_UNSUCCESSFUL;
return STATUS_SUCCESS;
}
NTSTATUS
ChangeInterruptVectorNumber(ULONG ulIrqVectorNumber,ULONG ulNewNumber,PULONG pulPerviousNumber)
{
PHYSICAL_ADDRESS TempPhysicalAddress;
PUCHAR pIoRegSelAddress;
PULONG pIoWinAddress;
[COLOR="SeaGreen"]//检查指针地址是否合法[/COLOR]
if(!MmIsAddressValid(pulPerviousNumber))
return STATUS_INVALID_PARAMETER;
RtlZeroMemory(&TempPhysicalAddress,sizeof(TempPhysicalAddress));
TempPhysicalAddress.LowPart = IOAPIC_REGSEL_PHYSICAL_ADDRESS;
pIoRegSelAddress = (PUCHAR)MmMapIoSpace(TempPhysicalAddress,0x10+sizeof(ULONG),MmNonCached);
[COLOR="SeaGreen"]//如果映射失败的话,就返回[/COLOR]
if(!MmIsAddressValid(pIoRegSelAddress))
return STATUS_UNSUCCESSFUL
pIoWinAddress = (PULONG)(pIoRegSelAddress + 0x10); [COLOR="SeaGreen"]//IOWIN的映射地址[/COLOR]
[COLOR="SeaGreen"]//指定获取IRQ1的项,参考intel手册[/COLOR]
*pIoRegSelAddress = 0x10 + (UCHAR)ulIrqVectorNumber * sizeof(UCHAR)*2;
[COLOR="SeaGreen"]//保存原来的向量号[/COLOR]
__asm
{
mov eax,[pIoWinAddress];
movzx eax,byte ptr [eax];
push eax;
mov eax,[pulPerviousNumber];
pop dword ptr [eax];
}
[COLOR="SeaGreen"]//设置新的中断向量号[/COLOR]
__asm
{
mov eax,[pIoWinAddress];
mov ecx,[ulNewNumber];
mov byte ptr [eax],cl;
}
[COLOR="SeaGreen"]//解除地址映射[/COLOR]
MmUnmapIoSpace(pIoRegSelAddress,0x10+sizeof(ULONG));
return STATUS_SUCCESS;
}
[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!