本文为看雪论坛精华文章
看雪论坛作者ID:hyjxiaobia
Step1. 创建承上启下的虚拟设备
Scope(_SB) {
Device(HAND) { #HAND->Han's device
Name(_HID, EISAID("HAN0000"))
Method(_STA) {
Return(0x0B)
}
}
}
Step 2.设计测试驱动,解决黄标
2.1 修改Inf文件,使其匹配Bios虚拟的设备
[Version]
Signature="$CHICAGO$"
Class=System
ClassGuid={4d36e97d-e325-11ce-bfc1-08002be10318}
Provider=%TOS%
CatalogFile=demo.cat
DriverVer=02/23/2021,2.2.0.0
[DestinationDirs]
demoNT.CopyFiles = 12
[Manufacturer]
%HAN%=Demo,NTx86,NTia64,NTamd64
[ControlFlags]
ExcludeFromSelect = *HAN0000
[Demo.NTx86]
%*HAN0000.DeviceDescNTx86%=demo,*HAN0000
[Demo.NTia64]
%*HAN0000.DeviceDescNTia64%=demo,*HAN0000
[Demo.NTamd64]
%*HAN0000.DeviceDescNTamd64%=demo,*HAN0000
[SourceDisksNames]
1=%demo%
[SourceDisksFiles]
demo.SYS = 1
[demo.NT]
CopyFiles=demoNT.CopyFiles
[demo.NT.Services]
AddService=demo,2,demo_Service_Inst
[demo_Service_Inst]
DisplayName = %demo.SvcDesc%
ServiceType = 1
StartType = 0
ErrorControl = 1
ServiceBinary = %12%demo.SYS
[demoNT.CopyFiles]
demo.SYS
[strings]
HAN = "HAN Co., Ltd."
demo = "demo"
*HAN0000.DeviceDescNTx86 = "Demo x86 ACPI-Compliant Value Added Logical and General Purpose Device"
*HAN0000.DeviceDescNTia64 = "Demo ia64 ACPI-Compliant Value Added Logical and General Purpose Device"
*HAN0000.DeviceDescNTamd64 = "Demo x64 ACPI-Compliant Value Added Logical and General Purpose Device"
demo.SvcDesc = "Demo ACPI-Based Value Added Logical and General Purpose Device Driver"
2.2 根据Inf文件生成.cat
Inf2cat.exe /driver:E:WinDDkmy_testobjchk_win7_amd64amd64 /os:7_x64
2.3 为.cat/.sys签名
Signtool sign /a /v /s PrivateCertStore /n Contoso.com(Test) demo.cat
Signtool sign /a /v /s PrivateCertStore /n Contoso.com(Test) demo.sys
Step 3. 编写驱动,接受ACPI Notification
3.1 SCI的中转:进一步完善Bios Method(_L56)的功能,转发SCI到驱动层
External(_SB.HAND, MethodObj)
Method (_L56, 0, Serialized){
DSTR("l-event _L56");
Notify(_SB.HAND,0x9A)
}
3.2 SCI的处理:完成ACPI驱动
3.2.1 获得ACPI direct call Interface接口并注册AcpiNotify:
NTSTATUS
DemoAddDevice(__in PDRIVER_OBJECT DriverObject,
__in PDEVICE_OBJECT PhysicalDeviceObject
)
{
//Phase 1
PDEVICE_OBJECT fdo = NULL;
PDEVICE_OBJECT lowerDevice = NULL;
PDemoDATA demoData;
RtlInitUnicodeString(&NameString, L"\Device\demo");
status = IoCreateDevice (
DriverObject, // our driver object
sizeof (DEMODATA), // device object extension size
&NameString, // FDOs do not have names
FILE_DEVICE_UNKNOWN,
0, // No special characteristics
FALSE,
&fdo);
lowerDevice = IoAttachDeviceToDeviceStack(fdo,PhysicalDeviceObject);
demoData= fdo->DeviceExtension;
demoData->DeviceObject = fdo;
demoData->LowerDeviceObject = lowerDevice;
demoData->Pdo = PhysicalDeviceObject;
//Phase 2
status = GetAcpiInterfaces(demoData);
RegisterNotifyHandler(demoData);
KeInitializeSpinLock(&demoData->RetrieveLock);
//Phase 3
RtlInitUnicodeString(&DOSNameString, L"\DosDevices\demo");
status = IoCreateSymbolicLink(&DOSNameString, &NameString);
fdo->Flags &= ~DO_DEVICE_INITIALIZING;
fdo->Flags |= DO_POWER_PAGABLE;
}
extern ACPI_INTERFACE_STANDARD AcpiInterfaces;
NTSTATUS
GetAcpiInterfaces(IN DemoDATA demoData)
{
KEVENT event;
IO_STATUS_BLOCK ioStatus;
NTSTATUS status;
PIRP Irp;
PIO_STACK_LOCATION irpSp;
KeInitializeEvent(&event, SynchronizationEvent, FALSE);
Irp = IoBuildSynchronousFsdRequest(
IRP_MJ_PNP,
demoData->LowerDeviceObject,
NULL,
0,
NULL,
&event,
&ioStatus
);
if (!Irp) {
return(STATUS_INSUFFICIENT_RESOURCES);
}
Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
Irp->IoStatus.Information = 0;
irpSp = IoGetNextIrpStackLocation(Irp);
irpSp->MajorFunction = IRP_MJ_PNP;
irpSp->MinorFunction = IRP_MN_QUERY_INTERFACE;
irpSp->Parameters.QueryInterface.InterfaceType = (LPGUID) &GUID_ACPI_INTERFACE_STANDARD;
irpSp->Parameters.QueryInterface.Version = 1;
irpSp->Parameters.QueryInterface.Size = sizeof (AcpiInterfaces);
irpSp->Parameters.QueryInterface.Interface = (PINTERFACE) &AcpiInterfaces;
irpSp->Parameters.QueryInterface.InterfaceSpecificData = NULL;
//
// send the request down
//
status = IoCallDriver(demoData->LowerDeviceObject, Irp);
return status;
}
NTSTATUS
RegisterNotifyHandler(IN PDemoData demoData)
{
NTSTATUS status;
status = AcpiInterfaces.RegisterForDeviceNotifications(
demoData->Pdo,
demoNotifyHandler,
AcpiInterfaces.Context
);
return status;
}
3.2.2.demoNotifyHandler处理来自Acpi层的Event
#define TVALDDRVR_DEVICE_OPEN_NAME TEXT("\\.\demo")
hDriver = ::CreateFile(TVALZ_DEVICE_OPEN_NAME,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_ATTRIBUTE_NORMAL |
FILE_FLAG_OVERLAPPED ,
NULL);
::DeviceIoControl(m_hDriver,
IOCTL_TVALZ_RETRIEVE_EVENT,
&iaeInputBuffer,
sizeof(iaeInputBuffer),
&iaeOutputBuffer,
sizeof(iaeOutputBuffer),
&dwReturned, &ol);
if (::GetLastError() == ERROR_IO_PENDING)
{
dwResult = ::WaitForMultipleObjects(2, hEventArray, FALSE, INFINITE) - WAIT_OBJECT_0;
}
#define GPIO_QEVENT_L56 0x9a //_GPE._L56 发出的Notify Code的值为0x9A
VOID
demoNotifyHandler(IN PVOID Context,
IN ULONG ulNotifyValue
)
{
KIRQL Irql;
PULONG pNotification;
PLIST_RETRIEVE_IRP pEntry, pNextEntry;
PIOBUF_ACPI_EVENT pAcpiEvent;
UINT64 MsrData64 = 0; //AddNewEvent+
WORK_QUEUE_ITEM* turboWorkItem; //AddNewEvent+
PIRP retrieveIrp;
DebugPrint(-1,(" : NotifyHandler...Notification=%xn", ulNotifyValue));
KeAcquireSpinLock(&RetrieveLock, &Irql);
if (!IsListEmpty((PLIST_ENTRY)&RetrieveList)) {
for (pEntry = (PLIST_RETRIEVE_IRP)RetrieveList.ListEntry.Flink; pEntry != &RetrieveList; pEntry = pNextEntry) {
pNextEntry = (PLIST_RETRIEVE_IRP)pEntry->ListEntry.Flink;
pAcpiEvent = (PIOBUF_ACPI_EVENT)pEntry->pIrp->AssociatedIrp.SystemBuffer;
if (pAcpiEvent->ulNotifyCode == ulNotifyValue) {
RemoveEntryList((PLIST_ENTRY)pEntry);
InsertTailList((PLIST_ENTRY)&CompleteList, (PLIST_ENTRY)pEntry);
if(ulNotifyValue == GPIO_QEVENT_L56)
{
DebugInfo(1,("Demo:receive Q-event _L56n"));
}
else
{}
//tvalz_AddNewEvent+
}
}
}
KeReleaseSpinLock(&RetrieveLock, Irql);
if (!IsListEmpty((PLIST_ENTRY)&CompleteList)) {
for (pEntry = (PLIST_RETRIEVE_IRP)CompleteList.ListEntry.Flink; pEntry != &CompleteList; pEntry = pNextEntry) {
pNextEntry = (PLIST_RETRIEVE_IRP)pEntry->ListEntry.Flink;
RemoveEntryList((PLIST_ENTRY)pEntry);
IoSetCancelRoutine(pEntry->pIrp, NULL);
pAcpiEvent = (PIOBUF_ACPI_EVENT)pEntry->pIrp->AssociatedIrp.SystemBuffer;
pAcpiEvent->dwStatus = STATUS_SUCCESS;
pEntry->pIrp->IoStatus.Information = sizeof(PIOBUF_ACPI_EVENT);
pEntry->pIrp->IoStatus.Status = STATUS_SUCCESS;
IoCompleteRequest(pEntry->pIrp, IO_NO_INCREMENT);
}
}
TvalzDebug(Tvalz_INFO,("TVALZ : NotifyHandler...endn"));
}
附注:为了Enable DbgView输出:
结尾
看雪ID:hyjxiaobia
https://bbs.pediy.com/user-home-399589.htm
# 往期推荐
球分享
球点赞
球在看
点击“阅读原文”,了解更多!
本文始发于微信公众号(看雪学院):Windows应用程序响应主板上GPIO(SCI)设备中断 软件篇
免责声明:文章中涉及的程序(方法)可能带有攻击性,仅供安全研究与教学之用,读者将其信息做其他用途,由读者承担全部法律及连带责任,本站不承担任何法律及连带责任;如有问题可邮件联系(建议使用企业邮箱或有效邮箱,避免邮件被拦截,联系方式见首页),望知悉。
- 左青龙
- 微信扫一扫
-
- 右白虎
- 微信扫一扫
-
评论