C/C++使用WinIO读取CMOS数据
基本原理
CMOS RAM 芯片介绍
PC机的主板上集成有CMOS实时时钟,为操作系统提供时间信息:年、月、日与时、分、秒。它附有128或256个字节的RAM,用于存放时间与硬盘、内存、显示卡等最基本的硬件配置信息。操作系统启动时,从CMOS实时时钟中读取时间信息作为系统的基准时间。系统断电后由后备的锂电池供电,以保障信息不丢失。这个芯片内部有两个端口,端口地址为 70h 和 71h,CPU 通过这两个端口来读写 CMOS RAM。70h 为地址端口,存放要访问的 CMOS RAM 单元的地址,71h 位数据端口,存放从选 定的 CMOS RAM 单元中读取的数据,或者要写入到其中的数据。
WinIO简介
Yariv Kaplan在2010年发布开源软件WinIo 3.0,它采用了非文档化的Windows API(native API)和其它一些底层编程技巧绕过Windows安全保护机制,使得Windows下的应用程序可直接对I/O端口进行操作。WinIo 3.0提供了10个库函数,用于对I/O端口和内存物理存储单元的直接读写。WinIo软件包由WinIo.sys、winio_nt.h、Winio.h、WinIo.dll、WinIo.lib(未提供,需要用户在VC2010下生成)等5个核心文件组成。
CMOS RAM信息表
地址 | 内容 |
---|---|
00H | Time - Seconds |
01H | Alarm - Seconds |
02H | Time - Minutes |
03H | Alarm - Minutes |
04H | Time - Hours |
05H | Alarm - Hours |
06H | Date - Day of the week |
07H | Date - Day |
08H | Date - Month |
09H | Date - Year |
0AH | Status Register A |
0BH | Status Register B |
0CH | Status Register C |
0DH | Status Register D |
0EH | Diagnostic Status |
0FH | Shutdown Status |
2EH | CMOS Checksum (high byte) |
2FH | CMOS Checksum (low byte) |
32H | Date - Century |
WinIo与I/O端口操作相关的4个函数
WinIo库函数初始化
WINIO_API bool _stdcall InitializeWinIo();
卸载WinIo库函数
WINIO_API void _stdcall ShutdownWinIo();
I/O端口读操作函数
WINIO_API bool _stdcall GetPortVal(WORD wPortAddr, PDWORD pdwPortVal, BYTE bSize);
参数wPortAddr为端口地址,16位整型变量或常量;参数pdwPortVal为指向一存放读取端口内容的32位整型变量指针;参数bSize为实际读取的字节数,8位整型变量或常量,取值范围为1、2或4,表示读操作的对象为8位、16位或32位端口。
I/O端口写操作函数
WINIO_API bool _stdcall SetPortVal(WORD wPortAddr, DWORD dwPortVal, BYTE bSize);
参数wPortAddr为端口地址,16位整型变量或常量;
参数dwPortVal为要写入端口的32位整型变量或常量;
参数bSize为实际写出的字节数,8位整型变量或常量,取值范围为1、2或4,表示读操作的对象为8位、16位或32位端口。
实现代码
读取CMOS RAM中的数据
代码比较简单,但是可以运行
#include "stdio.h"
#include "windows.h"
#include "winio.h"
#pragma comment( lib, "winio.lib" )
int main( )
{
DWORD dw;
bool re;
byte i;
re = InitializeWinIo();
if (re)
{
for (i = 0; i < 64; i++) {
SetPortVal(0x70, i, 1);
GetPortVal(0x71, &dw, 1);
switch (i)
{
case 0:
printf("%2d:%4x***秒\n",i,dw);
break;
case 2:
printf("%2d:%4x***分\n", i, dw);
break;
case 4:
printf("%2d:%4x***时\n", i, dw);
break;
case 6:
printf("%2d:%4x*星期\n", i, dw);
break;
case 7:
printf("%2d:%4x***日\n", i, dw);
break;
case 8:
printf("%2d:%4x***月\n", i, dw);
break;
case 9:
printf("%2d:%4x***年\n", i, dw);
break;
default:
printf("%2d:%4x\n", i, dw);
}
}
ShutdownWinIo();
}
else
{
printf("WinIo函数初始化错误\n");
exit(1);
}
system("pause");
return 0;
}
将CMOS RAM 中的前64为置零
#include "stdio.h"
#include "windows.h"
#include "winio.h"
#pragma comment( lib, "winio.lib" )
int main( )
{
DWORD dw;
bool bResult;
int i;
bResult = InitializeWinIo();
if (bResult)
{
for (i = 0; i < 64; i++) {
SetPortVal(0x70, i, 1);
SetPortVal(0x71, 0, 1);
}
ShutdownWinIo();
}
else
{
printf("WinIo函数初始化错误\n");
exit(1);
}
system("pause");
return 0;
}
注意事项
生成WinIO.lib
WinIo 3.0软件包的Source文件夹下包含了WinIo的源文件及其所需的资源,其下的DLL文件夹为VC 2010的WinIo项目文件夹。生成WinIo.lib文件的步骤如下:
(1)双击“WinIo.sln”启动WinIo项目
(2)在VC 2010 IDE下打开“生成”菜单,单击“生成WinIo”生成的WinIo.lib文件它存放于“…\Suorce\DLL\Debug”文件夹。
注意:VC 2010学习版不能生成WinIo.lib文件;Visual Studio 2015及以上无法生成;
WinIo应用环境配置 :
创建一个Win32控制台应用项目
创建一个“Win32控制台应用程序”的WinIoDemo项目,打开“生成”菜单,单击“生成WinIoDemo”。
复制WinIo核心文件到制定的文件夹
将WinIo 3.0软件包的Source文件夹下的winio_nt.h、Winio.h与WinIo.lib复制到WinIoDemo项目文件夹下,WinIo.sys与WinIo.dll复制到WinIoDemo项目文件夹下的Debug文件夹。
修改Winio.h文件
将Winio.h中的 “#include ”…\drv\winio_nt.h“”,修改为“#include ”winio_nt.h“”;
测试模式/证书安装
64位的系统管理员身份进入“命令提示符”,输入“bcdedit /set testsigning on”打开测试模式,重启;
右击winio65.dll->属性->数字签名->详细信息->查看证书->安装证书->下一步->将所有的证书都放入下列存储->受信任的根证书颁发机构
以管理员身份打开VC2017!!!
资源下载
WinIO 资源包(含winio.lib、winio.h、winio.sys、winio.dll文件)64/32 位下载
C/C++使用WinIO读取CMOS数据代码下载
部分内容来源:“VC 2010下WinIo 3.0直接访问IO端口”