乐于分享
好东西不私藏

WinIo内存访问驱动编译方法与源码解析

WinIo内存访问驱动编译方法与源码解析

安装 Visual Studio 专业版 2022

WDK 包已经不支持 2019 ,请更新到 2022版本

搜索 最新全选

可先下载源码便于 验证安装是否成功:

WinIoNote: https://github.com/foryouos/WinIoNote

安装环境

安装 SDK

查看系统已经安装的 SDK , 也可以在 上一步安装过程中安装 SDK,就不用再单独下载安装。

注: 检查 系统本身所存在的 环境,版本 过多,和WDK 版本不匹配 会导致 WDK 安装进去 Visual Studio 报错版本不匹配.

下载链接: https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk

系统安装的版本对应
安装SDK

安装 WDK

如果在 Visual Studio 中找不到驱动程序项目模板,则表示 WDK Visual Studio 扩展未正确安装。 要解决此问题,请从以下位置运行 WDK.vsix 文件:C:\Program Files (x86)\Windows Kits\10\Vsix\VS2022\10.0.26100.1\WDK.vsix

安装WDK

如果上述方式 安装失败,可以通过,在插件里 直接进行安装。如果还是失败? 查看下面的 该扩展的版本比 Visual Studio 要求的版本低

通过VS 2022进行安装

WDK的 版本 要和 自身的 系统对应,避免安装之后 出现 版本不兼容,失败的问题

经过测试:我使用 win11 23H2 直接安装的最新版本。

根据自身版本下载WDK

以前的 WDK 版本和其他下载 – Windows drivers | Microsoft Learn[1]

确保版本一致

确保版本一致

激活

Vs2022 激活码:

  • Pro: > TD244-P4NB7-YQ6XK-Y8MMM-YWV2J
  • Enterprise: > VHF9H-NXBBB-638P6-6JHCY-88JWH

初始化运行问题

未找到 ntddk.h

Windows微软解释
C:\Program Files (x86)\Windows Kits\10\Include\10.0.26100.0\km\ntddk.h

确认您的 windows kits目录,加入到 C++的附加项 即可

添加附加项
严重性 代码 说明 项目 文件 行 禁止显示状态 详细信息错误 C1083 无法打开包括文件: “ntddk.h”: No such file or directory 

创建 Hello Word 驱动

  • 打开 Microsoft Visual Studio。 在文件 菜单上,选择新建>项目
创建驱动

生成的 解决方案

解决方案

在 Source Files文件夹中创建 Driver.c文件

编写函数

#include<ntddk.h> //包含所有驱动程序的核心Widnows内核定义,#include<wdf.h> // 基于Windows 驱动程序框架WDF的驱动程序的定义DRIVER_INITIALIZE DriverEntry;EVT_WDF_DRIVER_DEVICE_ADD KmdfHelloWorldEvtDeviceAdd;// 驱动程序的入口函数NTSTATUSDriverEntry(    _In_ PDRIVER_OBJECT     DriverObject,    _In_ PUNICODE_STRING    RegistryPath){// NTSTATUS variable to record success or failure    NTSTATUS status = STATUS_SUCCESS;// Allocate the driver configuration object    WDF_DRIVER_CONFIG config;// Print "Hello World" for DriverEntry    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: DriverEntry\n"));// Initialize the driver configuration object to register the// entry point for the EvtDeviceAdd callback, KmdfHelloWorldEvtDeviceAdd    WDF_DRIVER_CONFIG_INIT(&config,        KmdfHelloWorldEvtDeviceAdd    );// Finally, create the driver object    status = WdfDriverCreate(DriverObject,        RegistryPath,        WDF_NO_OBJECT_ATTRIBUTES,        &config,        WDF_NO_HANDLE    );return status;}// 系统检查到你的设备已到达时,会调用  EvtDeviceAdd 任务时初始化该设备的结构与资源NTSTATUSKmdfHelloWorldEvtDeviceAdd(    _In_    WDFDRIVER       Driver,    _Inout_ PWDFDEVICE_INIT DeviceInit){// We're not using the driver object,// so we need to mark it as unreferenced    UNREFERENCED_PARAMETER(Driver);    NTSTATUS status;// Allocate the device object    WDFDEVICE hDevice;// Print "Hello World"    KdPrintEx((DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL, "KmdfHelloWorld: KmdfHelloWorldEvtDeviceAdd\n"));// Create the device object    status = WdfDeviceCreate(&DeviceInit,        WDF_NO_OBJECT_ATTRIBUTES,        &hDevice    );return status;}

点击生成之后,就可以查看自己生成的 sys驱动文件

编译驱动文件

调用测试驱动

生成的驱动文件

  • HelloDriver.sys – 内核模式驱动程序文件
  • HelloDriver.inf – 在安装驱动程序时 Windows 使用的信息文件
  • HelloDriver.cat– 安装程序验证驱动程序的测试签名所使用的目录文件
查看生成的文件

管理员身份运行 DriverMonitor

调试驱动
选择驱动文件
点击GO运行即可打印数据

由于 sys文件,目前系统 都有签名认证要求,对于没有签名认证的,都会默认被Windows系统拦截

调试方案

  • 启动系统测试模式 cmd 中以管理员身份运行执行此指令bcdedit /set testsigning on 然后重启
加载驱动
  • 获取打印的测试结果
  • 使用 Dbgview 工具,它会实时打印当前系统的 驱动输出 后续章节 进行更新。

WINIO基础流程

驱动程序是一个软件组件,它允许操作系统设备进行通信。

显示应用程序、操作系统和驱动程序之间交互的关系图。
winio用户进程与DLL以及SYS驱动的关系

WINIO函数解析

DriverEntry

主要对驱动程序进行初始化,由系统进程System调用

  • 驱动程序的标准例程提供入口点
NTSTATUS DriverEntry(  _In_ PDRIVER_OBJECT  DriverObject,  _In_ PUNICODE_STRING RegistryPath);

KdPrint

  • 驱动打印Logo信息
  • 通过驱动检测工具来抓取 Logo
KdPrint(("Entering DriverEntry"));

rtlInitUnicodeString 函数

函数初始化Unicode 字符的计数字符串

// 如果成功返回 STATUS_SUCCESSNTSYSAPI VOID RtlInitUnicodeString(  [out]          PUNICODE_STRING         DestinationString,//指向要初始化的UNICODE_STRING结构的指针  [in, optional] __drv_aliasesMem PCWSTR SourceString //指向以NULL结尾的宽字符字符串指针,用于初始化目的字符串指向的计数字符串);RtlInitUnicodeString(&DeviceNameUnicodeString, L"\\Device\\TestIO");

IoCreateDevice

用于创建供驱动程序使用的设备对象

NTSTATUS IoCreateDevice(  [in]           PDRIVER_OBJECT  DriverObject, //指向调用方驱动程序对象的指针,每个驱动程序在指向DriverEntry例程的参数中接受指向其驱动程序对象的指针  [in]           ULONG           DeviceExtensionSize,//指向要为设备对象的设备扩展分配的驱动程序确定的字节数  [in, optional] PUNICODE_STRING DeviceName,// 指向包含以null结尾的Unicode字符串的缓冲区,该字符串为设备对象命名  [in]           DEVICE_TYPE     DeviceType,//指定系统定义的 FILE_DEVICE_XXX 常量之一,这些常量指示设备 (的类型,例如FILE_DEVICE_DISK或FILE_DEVICE_KEYBOARD) 或供应商为新类型的设备定义值  [in]           ULONG           DeviceCharacteristics,// 指定一个或多个系统定义的常量(ORed 在一起),这些常量提供有关驱动程序设备的其他信息。  [in]           BOOLEAN         Exclusive, //指定设备对象是否表示独占设备  [out]          PDEVICE_OBJECT  *DeviceObject // 指向变量的指针,该变量接受指向新创建的Device_OBJECT结构的指针);// WINIO驱动使用ntStatus = IoCreateDevice(DriverObject,0, &DeviceNameUnicodeString, FILE_DEVICE_WINIO,0, FALSE, &DeviceObject);

IoCreateSymbolicLink

IoCreateSymbolicLink 例程在设备对象名称和设备的用户可见名称之间设置符号链接

// 创建成功之后 返回 STATUS_SUCCESSNTSTATUS IoCreateSymbolicLink(  [in] PUNICODE_STRING SymbolicLinkName, //指向用户可见名称的缓冲Unicode字符串的指针  [in] PUNICODE_STRING DeviceName // 指向缓冲Unicode字符串的指针,该字符串时驱动程序创建的设备对象的名称);

ioDeleteDevice

ioDeleteDevice 例程从系统中删除设备对象,例如:从系统中删除基础设备时

voidIoDeleteDevice(  [in] PDEVICE_OBJECT DeviceObject // 指向要删除的设备对象的指针);//WINIO使用if (!NT_SUCCESS(ntStatus)){// Symbolic link creation failed- note this & then delete the// device object (it's useless if a Win32 app can't get at it).    KdPrint(("ERROR: IoCreateSymbolicLink failed"));    IoDeleteDevice(DeviceObject);}

IoGetCurrentIrpStackLocation

IoGetCurrentIrpStackLocation例程返回指向指定IRP中调用方I/O堆栈位置的指针

__drv_aliasesMem PIO_STACK_LOCATION IoGetCurrentIrpStackLocation(  [in] PIRP Irp  // 指向 IRP 的指针。);// WINIO示例// Init to default settingsIrp->IoStatus.Status = STATUS_SUCCESS;Irp->IoStatus.Information = 0;IrpStack = IoGetCurrentIrpStackLocation(Irp);// Get the pointer to the input/output buffer and it's lengthpvIOBuffer = Irp->AssociatedIrp.SystemBuffer;dwInputBufferLength = IrpStack->Parameters.DeviceIoControl.InputBufferLength;dwOutputBufferLength = IrpStack->Parameters.DeviceIoControl.OutputBufferLength;

每个驱动程序都必须使用发送的每个 IRP 调用 IoGetCurrentIrpStackLocation ,以获取当前请求的任何参数。 除非驱动程序为驱动程序处理的每个IRP_MJ_\*XXX 代码提供调度例程,否则驱动程序还必须在 IRP 中检查其I/O堆栈位置,以确定正在请求的操作。

WRITE_PORT_UCHAR

将字节写入指定的端口地址

voidWRITE_PORT_UCHAR(  [in] PVOID Port,  // 指向端口的指针,该端口必须是I/O空间中的映射内存范围  [in] ULONG Value  // 指定要写入端口的字节);//WINIO示例代码memcpy(&PortStruct, pvIOBuffer, dwInputBufferLength);switch (PortStruct.bSize){case1:        WRITE_PORT_UCHAR((PUCHAR)(USHORT)PortStruct.wPortAddr, (UCHAR)PortStruct.dwPortVal);break;case2:        WRITE_PORT_USHORT((PUSHORT)(USHORT)PortStruct.wPortAddr, (USHORT)PortStruct.dwPortVal);break;case4:        WRITE_PORT_ULONG((PULONG)(USHORT)PortStruct.wPortAddr, PortStruct.dwPortVal);break;}

READ_PORT_UCHAR

从指定的端口地址读取字节

UCHAR READ_PORT_UCHAR(  [in] PVOID Port  //指定端口地址,该地址必须是I/O空间中的映射内存范围);// WINIO示例代码switch (PortStruct.bSize){case1:        PortStruct.dwPortVal = (ULONG)READ_PORT_UCHAR((PUCHAR)(USHORT)PortStruct.wPortAddr);break;case2:        PortStruct.dwPortVal = (ULONG)READ_PORT_USHORT((PUSHORT)(USHORT)PortStruct.wPortAddr);break;case4:        PortStruct.dwPortVal = READ_PORT_ULONG((PULONG)(USHORT)PortStruct.wPortAddr);break;}

ZwOpenSection

打开现有节对象的[2] 句柄。

NTSYSAPI NTSTATUS ZwOpenSection(  [out] PHANDLE            SectionHandle,// 指向 HANDLE 变量的指针,该变量接收 section 对象的句柄。  [in]  ACCESS_MASK        DesiredAccess,//指向一个ACCESS_MASK值,该值确定对对象的请求访问权限  [in]  POBJECT_ATTRIBUTES ObjectAttributes // 该结构指定对象名称和其他属性);

HalTranslateBusAddress

This function translates a physical bus address to a physical system address.

该函数将物理总线地址转换为物理系统地址。

BOOL HalTranslateBusAddress(  INTERFACE_TYPE InterfaceType, // 表示总线接口类型。支持总线类型的上限始终是MaximumInterfaceType。这指示了设备使用的总线类型,如果PCI,ISA等  ULONG BusNumber,  // 设备的零基系统分配总线编号。用于在同一类型的多个总线中识别总线  PHYSICAL_ADDRESS BusAddress, //相对于总线的地址,此地址通常是设备在总线上的物理地址  PULONG AddressSpace, //输入时初始化为PULONG,输出时为端口号或内存地址,值0x0表示内存地址,0x1表示I/O空间  PPHYSICAL_ADDRESS TranslatedAddress // 指向转换后地址的指针,此参数返回的地址可以被设备驱动程序使用);

ZwMapViewOfSection

将节的视图映射到主题进程的虚拟地址空间中

NTSYSAPI NTSTATUS ZwMapViewOfSection(  [in] HANDLE SectionHandle,//节对象的句柄,  [in] HANDLE ProcessHandle,// 对象的句柄,该对象表示视图应映射到的进程。  [in, out]  PVOID *BaseAddress, // 指向接受视图基址的变量的指针  [in]   ULONG_PTR  ZeroBits, // 指定视图基址中必须为0的高序地址位数  [in]   SIZE_T  CommitSize,// 指定视图的初始提交区域的大小(以字节为单位)  [in, out, optional] PLARGE_INTEGER  SectionOffset,// 指向变量的指针,该变量接收从节开头到视图的偏移量(以字节为单位)  [in, out]   PSIZE_T         ViewSize,// 指向SIZE_T变量的指针  [in]   SECTION_INHERIT InheritDisposition,// 指向如何与子进程共享视图  [in]   ULONG  AllocationType,// 指定一组表示,用于描述要为指定的页面区域执行的分配类型  [in]    ULONG   Win32Protect// 指定要应用于映射视图的页面保护);

ZwUnmapViewOfSection

从主题进程的虚拟地址空间中取消映射节的视图

NTSYSAPI NTSTATUS ZwUnmapViewOfSection(  [in] HANDLE ProcessHandle, //以前传递给 ZwMapViewOfSection的进程对象的句柄  [in, optional] PVOID  BaseAddress // 指向要取消映射的视图基虚拟地址的指针,可是视图中的任何虚拟地址);

此例程从指定进程的虚拟地址空间取消映射包含*BaseAddress* 的节的整个视图,即使 *BaseAddress* 未指向视图的开头也是如此。

ObDereferenceObject

递减给定对象的引用次数并执行保留检查

ObDereferenceObject 返回为系统使用保留的值。驱动程序必须将此值视为 VOID

voidObDereferenceObject(  [in]  a //指向对象主体的指针);

zwClose

zwClose 例程关闭对象句柄

wClose 是一个泛型例程,可对任何类型的对象进行操作。

NTSYSAPI NTSTATUS ZwClose(  [in] HANDLE Handle  //任何类型的对象的句柄);

DeviceIoControl

将控制代码直接发送到指定的设备驱动程序,相应的设备执行应用的操作

BOOL DeviceIoControl(  [in]                HANDLE       hDevice, //设备句柄  [in]                DWORD        dwIoControlCode,// 操作的控制码,在winio_nt.h 文件或者 sys头文件中  [in, optional]      LPVOID       lpInBuffer,//指向输入缓冲区的指针,其中包含执行操作所需的数据  [in]                DWORD        nInBufferSize,//输入缓冲区的大小  [out, optional]     LPVOID       lpOutBuffer,//指向输出缓冲区的指针,用于接收操作返回的数据  [in]                DWORD        nOutBufferSize,// 输出缓冲区的大小  [out, optional]     LPDWORD      lpBytesReturned,// 指向变量的指针,改变量接受存储在输出缓冲区中的数据的大小(以字节为单位)  [in, out, optional] LPOVERLAPPED lpOverlapped// 指向 OVERLAPPED 结构的指针。);

创建动态链接库项目

创建项目
创建项目名称和对应目录
配置属性

创建文件

创建文件

smbios.h 和 smbios.cpp使用 开源库: DumpSMBIOS https://github.com/KunYi/DumpSMBIOS

头文件

  • 对于 全局变量 但是 在实现函数中需要全局使用,请放到对应的 实现函数 当中
#ifndef SMBIOSAPI_H_#define SMBIOSAPI_H_#include<Windows.h>#define _DllExport _declspec(dllexport) //使用宏定义缩写下// for Type 0typedefstruct {    PWCHAR m_wszBIOSVendor;    PWCHAR m_wszBIOSVersion;    PWCHAR m_wszBIOSReleaseDate;    DWORD  m_BIOSSysVersion;    DWORD  m_BIOSECVersion;} BIOSInfo;// for Type 1typedefstruct {    PWCHAR m_wszSysManufactor;    PWCHAR m_wszSysProductName;    PWCHAR m_wszSysVersion;    PWCHAR m_wszSysSerialNumber;    UUID   m_SysUUID;    PWCHAR m_wszSysSKU;    PWCHAR m_wszSysFamily;} SystemInfo;// for Type 2typedefstruct {    PWCHAR m_wszBoardManufactor;    PWCHAR m_wszBoardProductName;    PWCHAR m_wszBoardVersion;    PWCHAR m_wszBoardSerialNumber;    PWCHAR m_wszBoardAssetTag;    PWCHAR m_wszBoardLocation;} BoardInfo;// 函数 实现区域extern"C"{_DllExport voidSMBIOS_INIT();  // 初始化SMBIOS数据_DllExport voidSMBIOS_Free();  // 释放 SMBIOS 申请的 资源// 获取单个数据_DllExport DWORD SMBIOS_Get_BIOS_Version();  // 获取 BIOS信息 结构体// 获取数据结构体 指针 传入 结构体指针,返回对应的结构体 数据_DllExport voidSMBIOS_Get_BIOS_Info(BIOSInfo* info);  // 获取 BIOS信息 结构体_DllExport voidSMBIOS_Get_SYSTEM_Info(SystemInfo* info)// 获取系统 信息 结构体_DllExport voidSMBIOS_Get_BOARD_Info(BoardInfo* info);  // 获取主板 信息 结构体// 获取 UUID需要的 数据 包括  UUID  SysSerialNumber  BoardSerialNumber  SysSKU// 此函数 为 产线 UUID 测试 使用 传入对应  char 字符串// 输出 对应的 字符串值_DllExport  wchar_tSMBIOS_Get_UUID_Info(constchar* UUID_Type);}#endif// SMBIOSAPI_H_

实现函数

实现函数 主要是 对 头文件中的 函数 进行实现。

#include"pch.h"// use stdafx.h in Visual Studio 2017 and earlier#include"smbiosapi.h"#include"smbios.h"#include<memory>BIOSInfo* g_bios_info = nullptr;  // 全局 BIOS Info信息SystemInfo* g_system_info = nullptr// 全局 系统信息 结构体BoardInfo* g_board_info = nullptr;   // 全局 主板 信息 结构体_DllExport voidSMBIOS_INIT(){if (g_bios_info == nullptr) {  g_bios_info = new BIOSInfo; }if (g_system_info == nullptr) {  g_system_info = new SystemInfo; }if (g_board_info == nullptr) {  g_board_info = new BoardInfo; }const SMBIOS& SmBios = SMBIOS::getInstance();// 初始化 BIOS信息 g_bios_info->m_wszBIOSVendor      = SmBios.BIOSVendor(); g_bios_info->m_BIOSECVersion      = SmBios.BIOSECVersion(); g_bios_info->m_BIOSSysVersion     = SmBios.BIOSSysVersion(); g_bios_info->m_wszBIOSReleaseDate = SmBios.BIOSReleaseDate(); g_bios_info->m_wszBIOSVersion     = SmBios.BIOSVersion();// 初始化 系统信息 g_system_info->m_wszSysManufactor = SmBios.SysManufactor(); g_system_info->m_wszSysProductName = SmBios.SysProductName(); g_system_info->m_wszSysSerialNumber = SmBios.SysSerialNumber(); g_system_info->m_wszSysFamily = SmBios.SysFamily(); g_system_info->m_SysUUID = SmBios.SysUUID(); g_system_info->m_wszSysSKU = SmBios.SysSKU(); g_system_info->m_wszSysVersion = SmBios.SysVersion();// 初始化主板信息 g_board_info->m_wszBoardAssetTag = SmBios.BoardAssetTag(); g_board_info->m_wszBoardLocation = SmBios.BoardLocation(); g_board_info->m_wszBoardManufactor = SmBios.BoardManufactor(); g_board_info->m_wszBoardProductName = SmBios.BoardProductName(); g_board_info->m_wszBoardSerialNumber = SmBios.BoardSerialNumber(); g_board_info->m_wszBoardVersion = SmBios.BoardVersion();return ;}_DllExport voidSMBIOS_Free(){if (g_bios_info != nullptr) {delete g_bios_info;  g_bios_info = nullptr; }if (g_system_info == nullptr) {delete g_system_info;  g_system_info = nullptr; }if (g_board_info == nullptr) {delete g_board_info;  g_board_info = nullptr; }return ;}_DllExport DWORD SMBIOS_Get_BIOS_Version(){if (g_bios_info != nullptr) {return  g_bios_info->m_BIOSECVersion; }return  DWORD();}_DllExport voidSMBIOS_Get_BIOS_Info(BIOSInfo* info){if (info != NULL) {  info->m_wszBIOSVendor = g_bios_info->m_wszBIOSVendor;  info->m_BIOSECVersion = g_bios_info->m_BIOSECVersion;  info->m_BIOSSysVersion = g_bios_info->m_BIOSSysVersion;  info->m_wszBIOSReleaseDate = g_bios_info->m_wszBIOSReleaseDate;  info->m_wszBIOSVersion = g_bios_info->m_wszBIOSVersion; }return  ;}_DllExport voidSMBIOS_Get_SYSTEM_Info(SystemInfo* info){if (info != NULL) {  info->m_wszSysManufactor = g_system_info->m_wszSysManufactor;  info->m_wszSysProductName = g_system_info->m_wszSysProductName;  info->m_wszSysVersion = g_system_info->m_wszSysVersion;  info->m_wszSysSerialNumber = g_system_info->m_wszSysSerialNumber;  info->m_SysUUID = g_system_info->m_SysUUID;  info->m_wszSysSKU = g_system_info->m_wszSysSKU;  info->m_wszSysFamily = g_system_info->m_wszSysFamily; }return ;}_DllExport voidSMBIOS_Get_BOARD_Info(BoardInfo* info){if (info != NULL) {  info->m_wszBoardManufactor = g_board_info->m_wszBoardManufactor;  info->m_wszBoardProductName = g_board_info->m_wszBoardProductName;  info->m_wszBoardVersion = g_board_info->m_wszBoardVersion;  info->m_wszBoardSerialNumber = g_board_info->m_wszBoardSerialNumber;  info->m_wszBoardAssetTag = g_board_info->m_wszBoardAssetTag;  info->m_wszBoardLocation = g_board_info->m_wszBoardLocation; }return ;}wchar_tUUIDToString(const UUID& uuid){wchar_t* buffer = newwchar_t[37]; // 动态分配内存,长度为37 swprintf(buffer, 37,L"%08x-%04x-%04x-%04x-%012llx",  uuid.Data1, uuid.Data2, uuid.Data3,  (uuid.Data4[0] << 8) | uuid.Data4[1],  *reinterpret_cast<constunsignedlonglong*>(uuid.Data4 + 2));return buffer; // 返回指向动态分配内存的指针}// 传入的 参数 UUID  SysSerialNumber  BoardSerialNumber  SysSKU_DllExport  wchar_tSMBIOS_Get_UUID_Info(constchar* UUID_Type){if (strcmp(UUID_Type, "UUID") == 0) {return UUIDToString(g_system_info->m_SysUUID); }elseif (strcmp(UUID_Type, "SysSerialNumber") == 0) {return g_system_info->m_wszSysSerialNumber; }elseif (strcmp(UUID_Type, "BoardSerialNumber") == 0) {return g_board_info->m_wszBoardSerialNumber; }elseif (strcmp(UUID_Type, "SysSKU") == 0) {return g_system_info->m_wszSysSKU; }returnnullptr// 如果 UUID_Type 不匹配,返回 nullptr}

Visual Studio 静态链接配置

配置 lib静态链接库 所在 目录

添加附加库文件

链接对应的 动态链接库 名称

链接静态库
// TestSMBIOS.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。//#include<iostream>#include<Windows.h>#include"../SMBIOSDLL/smbiosapi.h"usingnamespacestd;// #pragma comment(lib,"SMBIOSDLL.lib")intmain(){cout << "Hello World!\n";    SMBIOS_INIT();    DWORD BIOS_Version = SMBIOS_Get_BIOS_Version();cout << "BIOS版本:" << BIOS_Version <<endl ;// 获取 BIOS信息    BIOSInfo* m_bios_info  = new BIOSInfo;    SMBIOS_Get_BIOS_Info(m_bios_info);    wprintf(L"BIOS Version: %s\r\n", m_bios_info->m_wszBIOSReleaseDate);// 获取 系统 信息    SystemInfo* m_system_info = new SystemInfo;    SMBIOS_Get_SYSTEM_Info(m_system_info);    wprintf(L"Sys Manufactor: %s\r\n", m_system_info->m_wszSysManufactor);// 获取  主板信息    BoardInfo* m_board_info = new BoardInfo;    SMBIOS_Get_BOARD_Info(m_board_info);    wprintf(L"BIOS ProductName: %s\r\n", m_board_info->m_wszBoardProductName);    SMBIOS_Free();return0;}

Qt 连接静态链接库

右键项目名称–> 添加库 –> 选择 外部库 —> 选择库文件

外部库
选择库文件
  • pro 文件静态 引用 头文件
win32: LIBS += -L$$PWD/./ -lSMBIOSDLLINCLUDEPATH += $$PWD/''DEPENDPATH += $$PWD/''win32:!win32-g++: PRE_TARGETDEPS += $$PWD/./SMBIOSDLL.libelse:win32-g++: PRE_TARGETDEPS += $$PWD/./libSMBIOSDLL.a
#include"smbiosapi.h"// 将对应的头文件 引入到项目 当中SMBIOS_INIT();qDebug()<<"BIOS版本信息:"<<SMBIOS_Get_BIOS_Version();// 获取 BIOS信息BIOSInfo* m_bios_info  = new BIOSInfo;SMBIOS_Get_BIOS_Info(m_bios_info);qDebug()<<m_bios_info->m_BIOSSysVersion;// 获取 系统 信息SystemInfo* m_system_info = new SystemInfo;SMBIOS_Get_SYSTEM_Info(m_system_info);qDebug()<<QString::fromWCharArray(m_system_info->m_wszSysManufactor);// 获取  主板信息BoardInfo* m_board_info = new BoardInfo;SMBIOS_Get_BOARD_Info(m_board_info);qDebug()<<QString::fromWCharArray(m_board_info->m_wszBoardProductName);// 测试 UUID 模块 返回的 字符qDebug()<< QString::fromWCharArray(SMBIOS_Get_UUID_Info("UUID"));qDebug()<< QString::fromWCharArray(SMBIOS_Get_UUID_Info("SysSerialNumber"));qDebug()<< QString::fromWCharArray(SMBIOS_Get_UUID_Info("BoardSerialNumber"));qDebug()<< QString::fromWCharArray(SMBIOS_Get_UUID_Info("SysSKU"));SMBIOS_Free();

动态链接库 创建 Qt 为例

  • Pro 文件中添加如下内容
DEFINES += WINIO_DLL

winapi.h

#ifndef WINAPI_H#define WINAPI_H#include<QObject>#include<windows.h>#include<winioctl.h>// 定义内存映射结构#include"winio_nt.h"#include<QLibrary>#include<QDebug>// 函数定义typedefbool( _stdcall* LP_InitializeWinIo)();typedefbool( _stdcall* LP_ShutdownWinIo)();typedefbool( _stdcall* LP_InstallWinIoDriver)(PSTR pszWinIoDriverPath,bool IsDemandLoaded);typedefbool(_stdcall* LP_RemoveWinIoDriver)();typedefbool( _stdcall* LP_GetPortVal)(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);typedefbool( _stdcall* LP_SetPortVal)(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);typedefbool( _stdcall* LP_GetPhysLong)(PBYTE pbPhysAddr, PDWORD pdwPhysVal);typedefbool( _stdcall* LP_SetPhysLong)(PBYTE pbPhysAddr, DWORD dwPhysVal);typedefPBYTE(_stdcall* LP_MapPhysToLin)(tagPhysStruct &PhysStruct);typedefbool(_stdcall* LP_UnmapPhysicalMemory)(tagPhysStruct &PhysStruct);typedefbool(_stdcall* LP_OpenSioDecode)();typedefbool(_stdcall* LP_CloseSioDecode)();classWinAPI :public QObject{    Q_OBJECTpublic:explicitWinAPI(QObject *parent = nullptr);    ~ WinAPI() override;// 共有供外接访问的 API 接口public slots:// 1,加载动态链接库boolLoad_WinIO();// 2, 函数调用端口 以BIOS源代码同步// 2.1 读取SuperIO 数据BYTE IoRead8(WORD  port)//参数: 端口地址 ,端口值  BYTE 8位WORD  IoRead16(WORD  port)//参数: 端口地址 ,端口值  WORD 16位DWORD  IoRead32(WORD  port)//参数: 端口地址 ,端口值  DWORD 32 wei// 2,2 向SuperIO中写入数据boolIoWrite8(WORD port, DWORD  val);boolIoWrite16(WORD port, DWORD  val);boolIoWrite32(WORD port, DWORD  val);// 2.3 读取内存中的数据DWORD GetMemory(PBYTE pbPhysAddr);  //获取内存中的值// 2.4 向内存中写入数据boolSetMemory(PBYTE pbPhysAddr, DWORD dwPhysVal)// 向内存中写入数据// 2.5 向内存空间映射地址PBYTE MapMemoryToLin(tagPhysStruct &PhysStruct);boolUnMapMemoryToLin(tagPhysStruct &PhysStruct);// 私有接口private slots:inlinevoidDebug(QString Content){        qDebug()<<Content;emit Send_Log(Content + "\n");    }signals:voidSend_Log(QString log);private://    HMODULE m_hDllFile  =  nullptr;  // 初始化WinIO 句柄// 对函数指针进行重定义。    LP_InitializeWinIo InitializeWinIo =  nullptr;    LP_ShutdownWinIo ShutdownWinIo  =  nullptr;    LP_GetPhysLong GetPhysLong  =  nullptr;    LP_SetPhysLong SetPhysLong  =  nullptr;    LP_SetPortVal SetPortVal  =  nullptr;    LP_GetPortVal GetPortVal  =  nullptr;    LP_MapPhysToLin MapPhysToLin  =  nullptr;    LP_UnmapPhysicalMemory UnmapPhysicalMemory  =  nullptr;    LP_InstallWinIoDriver InstallWinIoDriver = nullptr;    LP_RemoveWinIoDriver RemoveWinIoDriver = nullptr;    LP_OpenSioDecode OpenSioDecode = nullptr;    LP_CloseSioDecode CloseSioDecode = nullptr;};#endif// WINAPI_H

winapi.cpp

#include"winapi.h"#include<QCoreApplication>#include<QDir>WinAPI::WinAPI(QObject *parent)    : QObject{parent}{//1,初始化WinIO    Debug("WinAPI 构造初始化加载WinIO");this->Load_WinIO();if(InitializeWinIo())    {        Debug("二次初始化成功!");    }}WinAPI::~WinAPI(){    Debug("WinAPI 析构函数");if(ShutdownWinIo != nullptr)  // 确保指针已经初始化成功    {        RemoveWinIoDriver();        ShutdownWinIo();    }}boolWinAPI::Load_WinIO(){//加载动态链接库,并通过GetProcAddress方法调用取函数空间地址// @ 传入所需的动态链接库// 返回m_hDllFile将作为GetProcAddress去调用WinIO的函数地址使用int Fail = 0;#ifdef Q_OS_WIN64// 64 位 Windows 版本    m_hDllFile = LoadLibrary(L"drv64.dll");#else// 32 位 Windows 版本    m_hDllFile = LoadLibrary(L"32drv.dll");#endifif(m_hDllFile == nullptr)    {        Debug("1,Load 失败,请检查 WinIO 文件是否与exe same location!!! ");        Fail ++;    }else    {// 对函数指针初始化OEMLib_InitializeWinIo -> InitializeWinIo        InitializeWinIo=(LP_InitializeWinIo)::GetProcAddress(m_hDllFile,"InitializeWinIo");if(nullptr == InitializeWinIo)        {            Debug( "InitializeWinIo 加载函数指针失败");            Fail ++;        }//qDebug()<< "后:"<< OEMLib_InitializeWinIo;// 函数指针初始化  OEMLib_ShutdownWinIo ->  ShutdownWinIo        ShutdownWinIo=(LP_ShutdownWinIo)::GetProcAddress(m_hDllFile,"ShutdownWinIo");if(nullptr == ShutdownWinIo)        {            Debug("ShutdownWinIo 加载函数指针失败");            Fail ++;        }        InstallWinIoDriver=(LP_InstallWinIoDriver)::GetProcAddress(m_hDllFile,"InstallWinIoDriver");if(nullptr==InstallWinIoDriver)        {            qDebug()<< "InstallWinIoDriver 加载函数指针失败";            Fail ++;        }        RemoveWinIoDriver=(LP_RemoveWinIoDriver)::GetProcAddress(m_hDllFile,"RemoveWinIoDriver");if(nullptr==RemoveWinIoDriver)        {            qDebug()<< "RemoveWinIoDriver 加载函数指针失败";            Fail ++;        }// 函数指针初始化 OEMLib_GetPhysLong -> GetPhysLong        GetPhysLong=(LP_GetPhysLong)::GetProcAddress(m_hDllFile,"GetPhysLong");if(nullptr == GetPhysLong)        {            Debug( "GetPhysLong 加载函数指针失败");            Fail ++;        }// 函数        OEMLib_SetPhysLong  -> SetPhysLong        SetPhysLong = (LP_SetPhysLong)::GetProcAddress(m_hDllFile,"SetPhysLong");if(nullptr == SetPhysLong)        {            Debug( "SetPhysLong 加载函数指针失败");            Fail ++;        }        SetPortVal=(LP_SetPortVal)::GetProcAddress(m_hDllFile,"SetPortVal");if(nullptr == SetPortVal)        {            Debug("SetPortVal 加载函数指针失败");            Fail ++;        }// 初始化操作        GetPortVal = (LP_GetPortVal)::GetProcAddress(m_hDllFile, "GetPortVal");ifnullptr== GetPortVal)        {            Debug("GetPortVal 加载函数指针失败");            Fail ++;        }        MapPhysToLin=(LP_MapPhysToLin)::GetProcAddress(m_hDllFile,"MapPhysToLin");if(nullptr==MapPhysToLin)        {            Debug( "MapPhysToLin 加载函数指针失败");            Fail ++;        }        UnmapPhysicalMemory = (LP_UnmapPhysicalMemory)::GetProcAddress(m_hDllFile,"UnmapPhysicalMemory");if(nullptr == UnmapPhysicalMemory)        {            Debug( "UnmapPhysicalMemory 加载函数指针失败");            Fail ++;        }        OpenSioDecode = (LP_OpenSioDecode)::GetProcAddress(m_hDllFile,"OpenSioDecode");if(nullptr == OpenSioDecode)        {            Debug( "OpenSioDecode 加载函数指针失败");            Fail ++;        }        CloseSioDecode = (LP_CloseSioDecode)::GetProcAddress(m_hDllFile,"CloseSioDecode");if(nullptr == CloseSioDecode)        {            Debug( "CloseSioDecode 加载函数指针失败");            Fail ++;        }// 对WinIO进行初始化bool status = InitializeWinIo();if(status)        {            Debug("1,WinIO初始化成功");        }else        {            Debug("WinIO初始化失败,失败原因请检查如下:");            Fail ++;        };    }if(Fail == 0)    {returntrue;    }else    {returnfalse;    }}BYTE WinAPI::IoRead8(WORD Port){    DWORD val = 0x0;if(GetPortVal(Port,&val,1)) // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).    {        Debug("十六进制:" + QString::number(val,16) + "  二进制:" + QString::number(val,2) );    }else    {        Debug("读取 0x " + QString::number(Port,16)+ "数据失败");    };return val;}WORD WinAPI::IoRead16(WORD Port){    DWORD val = 0x0;if(GetPortVal(Port,&val,2)) // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).    {        Debug("十六进制:" + QString::number(val,16) + "  二进制:" + QString::number(val,2));    }else    {        Debug("读取 0x" + QString::number(Port,16) + "数据失败");    };return val;}DWORD WinAPI::IoRead32(WORD Port){    DWORD val = 0x0;if(GetPortVal(Port,&val,4)) // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).    {        Debug("十六进制:" + QString::number(val,16) + "  二进制:" + QString::number(val,2) ) ;    }else    {        Debug( "读取 0x" + QString::number(Port,16) + "数据失败" );    };return val;}boolWinAPI::IoWrite8(WORD port, DWORD val){if(SetPortVal(port,val,1))    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "成功");returntrue;    }else    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "失败");returnfalse;    }}boolWinAPI::IoWrite16(WORD port, DWORD val){if(SetPortVal(port,val,2))    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "成功");returntrue;    }else    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "失败");returnfalse;    }}boolWinAPI::IoWrite32(WORD port, DWORD val){if(SetPortVal(port,val,4))    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "成功");returntrue;    }else    {        Debug( "向:" + QString::number(port,16) + "中写入:" + QString::number(val,16) + "失败");returnfalse;    }}DWORD WinAPI::GetMemory(PBYTE pbPhysAddr){    DWORD val = 0x0;if(GetPhysLong)    {if(GetPhysLong(pbPhysAddr,&val))        {            Debug( QString("GetMemory 数据读取 Successful " ));        }else        {            Debug( QString( "GetMemory 数据读取   Failed ") );        };    }return val;}boolWinAPI::SetMemory(PBYTE pbPhysAddr, DWORD dwPhysVal){if(SetPhysLong(pbPhysAddr,dwPhysVal))    {        Debug("SetMemory 写入 成功  Successful");returntrue;    }else    {        Debug("SetMemory 写入 失败  Failed");returnfalse;    }}PBYTE WinAPI::MapMemoryToLin(tagPhysStruct &PhysStruct){return MapPhysToLin(PhysStruct);}boolWinAPI::UnMapMemoryToLin(tagPhysStruct &PhysStruct){return UnmapPhysicalMemory(PhysStruct);}

代码结构

  • 头文件 中定义 引用所需要的头文件 供动态和静态调用时使用
  • Source 文件中定义头文件实现函数
代码结构

头文件

动态链接库的头文件

基础函数

相关细节,可以查看本文件夹的WINIO源码

CreateFile

此函数可以创建新文件或打开现有文件,必须指定文件名,创建文件说明和其他属性。

创建或打开文件或 I/O 设备。常用的 I/O 设备有:文件,文件流,目录,物理磁盘,卷,控制台缓冲区,磁带驱动器,通信资源,邮筒和管道。该函数返回一个句柄,该句柄可用于根据文件或设备以及指定的标志和属性访问文件或设备以获取各种类型的 I/O.

HANDLE WINAPI CreateFile(  _In_     LPCTSTR lpFileName,//要创建或打开的文件或设备的名称  _In_     DWORD dwDesiredAccess,// 所请求的文件或设备访问权限,可以被概括为读,写,两者或非  _In_     DWORD dwShareMode,// 文件或设备的请求共享模式,可以读取,写入,删除,全部或全部删除  _In_opt_ LPSECURITY_ATTRIBUTES lpSecurityAttributes,//指向SECURITY_ATTRIBUTES结构的指针,该结构包含两个独立相关的数据成员,一个可选的安全描述符以及一个布尔值,该值确定返回的句柄是否可以被子进程继承,若为NULL则由CreateFile返回的句柄不能由应用程序可能创建的任何子进程继承,并且与返回句柄关联的文件或设备将获得默认安全描述符  _In_     DWORD dwCreationDisposition,//采用存在或不存在的文件或设备的操作  _In_     DWORD dwFlagsAndAttributes,// 文件或设备属性和标志  _In_opt_ HANDLE hTemplateFile// 具有GENERIC_READ访问权限的模版文件的有效句柄);

DeviceIoControl

DeviceIoControl 是一个Windows API函数,用于与设备驱动程序进行通信。这个函数可以用来发送控制代码接收响应

BOOL DeviceIoControl(    HANDLE hDevice,              // 设备的句柄    DWORD dwIoControlCode,       // 控制代码    LPVOID lpInBuffer,           // 输入缓冲区    DWORD nInBufferSize,         // 输入缓冲区大小    LPVOID lpOutBuffer,          // 输出缓冲区    DWORD nOutBufferSize,        // 输出缓冲区大小    LPDWORD lpBytesReturned,     // 返回的字节数    LPOVERLAPPED lpOverlapped     // 重叠结构);

实现函数

  • 实现对指定内存访问接口
  • 实现对某个SuperIO的某个bit位的控制。
  • 实现对SumBus的访问

winIo头文件中加入如下 函数,并在相关的cpp函数进行实现

// 添加自定义函数 IT8786 系列的WINIO_API bool _stdcall IoWrite8(UINT8 Register, UINT8 Value);WINIO_API UINT8 _stdcall IoRead8(UINT8 Register);// 使 ITE  使能 superIo访问 接口已验证 可行WINIO_API bool _stdcall OpenSioITEDecode();WINIO_API bool _stdcall CloseSioITEDecode();// 操作SUPERUI 单个寄存器的 单个Bit值// 参数:读取Port 读取的 bit位// 返回值:返回bit位是 0还是 1WINIO_API int _stdcall IoRead8_Single_Bit(WORD port, int bit);// 参数 Port 写入Bit 写入值0/1WINIO_API bool _stdcall IoWrite8_Single_Bit(WORD addr, int bit, int bit_value);// 以机型// 控制某个GPIO 的函数 传入参数 GPIO pin编号 ,高1 或者 低0// SMBIOS访问 控制// 访问SumBus函数封装于此WINIO_API bool _stdcall SmbusWriteByte(WORD slav_address, WORD offset_address, WORD write_data);WINIO_API bool _stdcall SmbusReadByte(WORD slav_address, WORD offset_address, WORD* read_data);//给接口访问内存 l来进行控制 可行 已验证WINIO_API bool _stdcall MemoryTest();WINIO_API DWORD _stdcall GetMemoryTest();

自定义步骤

  • 首先在winio.h中定义头文件
  • 然后在具体的函数中,可自己定义应用头文件,并对头文件进行实现
  • 在进行自定义函数封装时,尽量调用不要过于封装,避免出现访问失败问题。例如在访问SMBus时就调用了SuperIO的封装,SuperIO有调用 API 接口,API 调用系统接口,一个函数调用太多,容易出问题。
自定义函数

SuperIO自定义函数

// ---------------------------------------------------- ////    对SuperIO相关的定制化函数                //// ---------------------------------------------------- //#include<windows.h>#include"winio.h"UINT8  IT8728F_CONFIG_INDEX = 0x2e;UINT8  IT8728F_CONFIG_DATA = 0x2f;bool _stdcall IoWrite8(UINT8 Register, UINT8 Value){if (SetPortVal((WORD)Register, (WORD)Value, 1))    {returntrue;    }else    {returnfalse;    }}UINT8 _stdcall IoRead8(UINT8 Register){    DWORD portValue = 0x0// 用于存储读取的值    GetPortVal(Register, &portValue, 1);return portValue; // 只返回低8位}bool _stdcall OpenSioITEDecode(){    IoWrite8(IT8728F_CONFIG_INDEX, 0x87);    IoWrite8(IT8728F_CONFIG_INDEX, 0x01);    IoWrite8(IT8728F_CONFIG_INDEX, 0x55);    IoWrite8(IT8728F_CONFIG_INDEX, 0x55);returntrue;}bool _stdcall CloseSioITEDecode(){    IoWrite8(IT8728F_CONFIG_INDEX, 0x02);    IoWrite8(IT8728F_CONFIG_DATA, 0x02);returntrue;}int _stdcall IoRead8_Single_Bit(WORD port, int bit){    BYTE Value = 0x0;    DWORD val = 0x0;if (GetPortVal(port, &val, 1)) // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).    {// 获取 val 的第 bit 位的值if (bit < 0 || bit >= 32// 确保 bit 在合法范围内        {return-1// 返回错误代码        }// 使用位操作获取对应的 bit 位int bitValue = (val >> bit) & 1// 右移 bit 位并与 1 进行与操作return bitValue; // 返回对应 bit 位的值(0或1)    }else    {return-1;    }}bool _stdcall IoWrite8_Single_Bit(WORD addr, int bit, int bit_value){    BYTE Curr_Value = IoRead8(addr);// 根据条件与或操作来更新对应的值if (bit_value == 1)    {// 将第bit位设置为1        Curr_Value |= (1 << bit);    }else    {// 将第bit位设置为0        Curr_Value &= ~(1 << bit);    }// 将更新后的值 写入if (SetPortVal(addr, Curr_Value, 1))    {returntrue;    }else    {returnfalse;    }returntrue;}

内存测试函数

bool _stdcall MemoryTest(){if (SetPhysLong(0x000000000x44000200)) {returntrue; }else {returnfalse; }}DWORD _stdcall GetMemoryTest(){ DWORD val = 0x0; GetPhysLong(0x00000000, &val);return val;}

SMBus自定义函数

// ---------------------------------------------------- ////    对SMBus进行访问的相关函数                //// ---------------------------------------------------- //#include<windows.h>#include"winio.h"WORD Sumbus_base = 0xf000;// 使用动态链接库 来进行 IO Space的函数 请直接使用原生的函数,不要嵌套那么多层,否则会出现访问失效的问题bool _stdcall SmbusWriteByte(WORD slav_address, WORD offset_address, WORD write_data){int Timer_Num = 0;    DWORD val = 0x0// 存储读到的值// 初始化超时时间位 0unsignedlong timeout = 0;// 使用outb方法将write_date的值写入到I/O端口地址0xf005/*        端口IO        * port I/O 地址,此地址位虚拟地址        * data 位写入数据    */    SetPortVal(Sumbus_base + 0x05,write_data,1);// 将0x1f的值写入指定的I/O端口地址0xf000    SetPortVal(Sumbus_base, 0x1f1);while (1)    {// inb读取指定寄存器的值 0xf000        DWORD val = 0x0;        GetPortVal(Sumbus_base, &val, 1); // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).// 暂停10微妙//usleep(10);        Sleep(10);// 检查对应的值最低为是否为 0if ((val & 0x1) == 0)        {break;        }// 超市时间        timeout++;// 10微妙一次,相当于超过一秒,访问超时if (timeout > 100)        {            Timer_Num++;break;        }    }// 将slav_address基地址写到0xf004    SetPortVal(Sumbus_base + 0x04, slav_address, 1);    SetPortVal(Sumbus_base + 0x03, offset_address, 1);// 将0x48 写入到 0xf002    SetPortVal(Sumbus_base + 0x020x481);// 将超时进行初始化    timeout = 0;while (1)    {// 读取0xf000的数据//tempvalue= io->inb(Sumbus_base);        GetPortVal(Sumbus_base, &val, 1); // Can be 1 (BYTE), 2 (WORD) or 4 (DWORD).//usleep(10);        Sleep(10);// 判断最低为是否为0if ((val & 0x1) == 0)        {break;        }        timeout++;// 超时算上10微妙就为1秒if (timeout > 100)        {            Timer_Num++;break;        }    }// 如果tempvalue为零 则写入成功if ((val & 0x1C) != 0)    {        Timer_Num++;    }if (Timer_Num != 0)    {returnfalse;//    }else    {returntrue;    }returntrue;}bool _stdcall SmbusReadByte(WORD slav_address, WORD offset_address, WORD* read_data){int Timer_Num = 0;// 记录读取的值    DWORD val = 0x0;// 设置超时时间unsignedlong   timeout = 0;// 将0x1f写入0xf000    SetPortVal(Sumbus_base, 0x1f1);while (1)    {// 判断是否写入        GetPortVal(Sumbus_base, &val, 1);        Sleep(10);// 判断最低为是否为0if ((val & 0x1) == 0)        {break;        }        timeout++;//if (timeout > 100)        {            Timer_Num++;//            perror("Smbus timeout!");break;        }    }// 将基地址+1存入寄存器IO 0xf004// +1 为读.    SetPortVal(Sumbus_base + 0x04, (slav_address + 1), 1);// 将偏移量 写入 0xf003    SetPortVal(Sumbus_base + 0x03, offset_address, 1);// 将0x48 写入 0x002    SetPortVal(Sumbus_base + 0x020x481);    timeout = 0;while (1)    {        GetPortVal(Sumbus_base, &val, 1);        Sleep(10);if ((val & 0x1) == 0)        {break;        }        timeout++;if (timeout > 100)        {            Timer_Num++;//            perror("Smbus timeout!");break;        }    }if ((val & 0x1C) != 0)    {        Timer_Num++;    }else    {        GetPortVal(Sumbus_base, &val, 1);        *read_data = val;    }if (Timer_Num != 0)    {returnfalse;    }}

签名问题

通过第三方机构对驱动SYS文件签名,记得修改对应的驱动服务文件,详见提交:

https://github.com/foryouos/WinIoNote/commit/935889f81d4c14884c5a269337ba68e73ad0b361

开源地址

  • DumpSMBIOS 开源项目[3]
  • WinIoNote[4]

参考资料

  • CreateFile 函数详细解析[5]
  • [下载 Windows 驱动程序工具包 (WDK) – Windows drivers | Microsoft Learn](https://learn.microsoft.com/zh-cn/windows-hardware/drivers/download-the-wdk “下载 Windows 驱动程序工具包 (WDK “下载 Windows 驱动程序工具包 (WDK) – Windows drivers | Microsoft Learn”) – Windows drivers | Microsoft Learn”)
  • [编写 Hello World Windows 驱动程序 (KMDF) – Windows drivers | Microsoft Learn](https://learn.microsoft.com/zh-cn/windows-hardware/drivers/gettingstarted/writing-a-very-small-kmdf–driver “编写 Hello World Windows 驱动程序 (KMDF “编写 Hello World Windows 驱动程序 (KMDF) – Windows drivers | Microsoft Learn”) – Windows drivers | Microsoft Learn”)
WinIO的使用以及在Qt调用
参考资料
[1] 

以前的 WDK 版本和其他下载 – Windows drivers | Microsoft Learn: https://learn.microsoft.com/zh-cn/windows-hardware/drivers/other-wdk-downloads

[2] 

节对象的: https://learn.microsoft.com/zh-cn/windows-hardware/drivers/

[3] 

DumpSMBIOS开源项目: https://github.com/KunYi/DumpSMBIOS

[4] 

WinIoNote: https://github.com/foryouos/WinIoNote 查看原文

[5] 

CreateFile 函数详细解析: https://blog.csdn.net/li_wen01/article/details/80142931

本站文章均为手工撰写未经允许谢绝转载:夜雨聆风 » WinIo内存访问驱动编译方法与源码解析

评论 抢沙发

1 + 6 =
  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址
×
订阅图标按钮