BIOS开发笔记 15 – WMI 在系统中的集成及应用(下)

一、前言

上一篇了解了 WMI 的基础知识,这篇则通过实例来巩固一下。下面以读写 CMOS 为例,通过 WMI 直接在操作系统进行读写。

二、编写 MOF 和 ASL 文件

首先需要创建 MOF 文件,它用于告诉操作系统,我们的 ASL 代码包含了哪些实现。我们在 MOF 文件中定义 2 两个函数,分别是 ReadCmos 和 WriteCmos。

[WMI,
Dynamic,
Provider("WMIProv"),
Locale("MS\0x409"),
Guid("{2969FE46-B6AB-40F8-ADE0-C58DBB378674}"),
Description("AY123 WMI Example")]
class AY123
{
  [key, read]
  string InstanceName;
  [read] boolean Active;
  [WmiMethodId(1),
   Implemented,
   read, write,
   Description("Read CMOS method")
  ] void ReadCmos([in, Description("uint8 Index")] uint8 Index,[out, Description("string Data")] string Data);
  [WmiMethodId(2),
   Implemented,
   read, write,
   Description("Write CMOS method")
  ] void WriteCmos([in, Description("uint8 Index")] uint8 Index,[in, Description("uint8 Data")] uint8 Data,[out, Description("string status")] string status);
};

这一段程序对于没学过面向对象语言的可能有点陌生,但把它当成一个规则就可以了,写的时候注意一下 GUID、函数名称以及输入输出参数即可。需要注意一下的是,标记为 out 的输出参数,在 ASL 中需要 return 相应的参数。
将上面程序保存为 Wmi.mof, 使用如下命令编译:

 mofcomp -B:Wmi.bmf "Wmi.mof"

将生成 Wmi.bmf,可以使用 16 进制编辑器打开,导出为数组,可包含在 ASL 代码中的 WQxx method中。

接下来是 ASL 代码的实现:

DefinitionBlock ("", "SSDT", 2, "AY123", "CUSTOM", 0x00000001)
{
Scope(_SB)
{
Device (WMIA) {
Name (_HID, "PNP0C14")
Name (_UID, "AY123WMI")
        Method (_WDG, 0, NotSerialized) {
            Return (Buffer() {
                // GUID: 2969FE46-B6AB-40F8-ADE0-C58DBB378674,与MOF中的GUID保持一致
                0x46, 0xFE, 0x69, 0x29, 0xAB, 0xB6, 0xF8, 0x40,
                0xAD, 0xE0, 0xC5, 0x8D, 0xBB, 0x37, 0x86, 0x74,
                65, 67,        // 此 2 byte 为 ASCII 编码,65, 67 对应字符 A,C,则 Object ID (AC) => WMAC
                1,             // Instance Count
                0x02,          // Flags (ACPI WMI Method)
    
                //
                // This GUID for returning the MOF data
                //
                0x21, 0x12, 0x90, 0x05, 0x66, 0xd5, 0xd1, 0x11, 
                0xb2, 0xf0, 0x00, 0xa0, 0xc9, 0x06, 0x29, 0x10,
                66, 65,        // Object ID (BA) => WQBA
                1,             // Instance Count
                0x00,          // Flags
            })
        }
        Name (WQBA, Buffer() {
            0x46, 0x4F, 0x4D, 0x42, 0x01, 0x00, 0x00, 0x00, 0x6F, 0x03, 0x00, 0x00,
            0xAE, 0x0B, 0x00, 0x00, 0x44, 0x53, 0x00, 0x01, 0x1A, 0x7D, 0xDA, 0x54,
            0xA8, 0xCE, 0x85, 0x00, 0x01, 0x06, 0x18, 0x42, 0x20, 0x34, 0x01, 0x89,
            0xC0, 0xA2, 0x69, 0x24, 0xC2, 0x01, 0x0C, 0x46, 0x03, 0x88, 0xE4, 0x40,
            0x88, 0x8F, 0xC2, 0x85, 0x90, 0x57, 0x01, 0x36, 0x05, 0x98, 0x04, 0x51,
            0xFF, 0xFE, 0x10, 0x25, 0xC1, 0xA1, 0x84, 0x40, 0x48, 0xA2, 0x00, 0xF3,
            0x02, 0x74, 0x0B, 0x30, 0x2C, 0xC0, 0xB6, 0x00, 0xD3, 0x02, 0x1C, 0x43,
            0x52, 0x69, 0xE0, 0x94, 0xC0, 0x52, 0x20, 0x24, 0x54, 0x80, 0x72, 0x01,
            0xBE, 0x05, 0x68, 0x47, 0x94, 0x64, 0x01, 0x96, 0x61, 0x44, 0xE0, 0x51,
            0x30, 0x34, 0x0E, 0x8D, 0x1D, 0x86, 0x65, 0x82, 0x69, 0x10, 0x87, 0x51,
            0x36, 0xB2, 0x08, 0x8C, 0xDB, 0xA9, 0x00, 0xB9, 0x02, 0x84, 0x09, 0x10,
            0x8F, 0x2A, 0x8C, 0xE6, 0xA0, 0x08, 0x5C, 0x68, 0x8C, 0x0C, 0x08, 0x79,
            0x14, 0x60, 0x7D, 0x24, 0x84, 0xC0, 0xEE, 0x05, 0x28, 0xC3, 0x94, 0x36,
            0x08, 0x69, 0x14, 0x60, 0x11, 0x5A, 0x28, 0x6D, 0x09, 0x50, 0x88, 0x21,
            0x83, 0x18, 0x42, 0x39, 0x02, 0x83, 0x15, 0x87, 0x22, 0xA0, 0x13, 0x0C,
            0x18, 0x27, 0x4A, 0x87, 0x02, 0xAC, 0x21, 0x09, 0x27, 0x60, 0x84, 0xCE,
            0x04, 0x78, 0x83, 0x11, 0x6E, 0x8C, 0xA8, 0xED, 0x0F, 0x82, 0x0C, 0xEA,
            0x58, 0x30, 0x62, 0x86, 0x4B, 0x86, 0xD5, 0xF9, 0xC4, 0x34, 0xC0, 0x93,
            0x29, 0x5C, 0x80, 0x74, 0x0C, 0x0D, 0xEE, 0x90, 0x13, 0x1C, 0x44, 0xB3,
            0x02, 0x8C, 0x8D, 0x47, 0x13, 0x28, 0x68, 0xA4, 0x14, 0xE4, 0x40, 0xCE,
            0xEE, 0xC4, 0x0D, 0x7A, 0x8E, 0x2C, 0xD0, 0x51, 0x40, 0x12, 0x40, 0x14,
            0x69, 0x14, 0xA8, 0xE1, 0x27, 0x78, 0x1C, 0x30, 0xF0, 0x19, 0x1C, 0xC6,
            0x41, 0x04, 0x0E, 0x72, 0x1E, 0x71, 0xEB, 0x44, 0x27, 0x23, 0x66, 0x58,
            0x09, 0x7E, 0x0D, 0x7C, 0x30, 0xC0, 0xBB, 0x06, 0xD4, 0x8D, 0xE0, 0x79,
            0x80, 0xCD, 0x25, 0x1C, 0x66, 0xD4, 0x1E, 0x58, 0xB8, 0xFF, 0xFF, 0x09,
            0x1C, 0x35, 0x03, 0xF4, 0x54, 0x1F, 0x05, 0xB0, 0xB3, 0x3D, 0x99, 0x33,
            0x2B, 0x75, 0x76, 0x3A, 0x13, 0x1C, 0x5A, 0x82, 0xE3, 0xF1, 0x28, 0x3D,
            0x9F, 0x9E, 0x21, 0x89, 0xFC, 0x41, 0xA0, 0x46, 0x66, 0x68, 0x8F, 0xF4,
            0xB4, 0x4E, 0xD6, 0xC7, 0x83, 0xC3, 0x62, 0x62, 0x21, 0xA4, 0x00, 0x42,
            0xE3, 0x01, 0xBF, 0xE2, 0x13, 0x80, 0x10, 0x8E, 0xDC, 0xF3, 0x35, 0x30,
            0x8C, 0x01, 0xD9, 0xAF, 0x00, 0x84, 0xE0, 0xEF, 0x04, 0x47, 0xF4, 0xD0,
            0x10, 0xE1, 0x61, 0x00, 0x47, 0x50, 0xE4, 0xC9, 0x00, 0x0D, 0xCC, 0x4F,
            0x00, 0x31, 0x0F, 0xE5, 0x44, 0x02, 0x1F, 0x4A, 0x94, 0xF8, 0xC7, 0xE2,
            0xE3, 0x84, 0x11, 0xCE, 0xF0, 0x29, 0xE2, 0xA9, 0xC2, 0x9A, 0x27, 0xA3,
            0xF3, 0xC3, 0xE9, 0xBC, 0x08, 0x98, 0xA0, 0x8A, 0x15, 0x68, 0x90, 0x8E,
            0xF3, 0x16, 0x90, 0x8D, 0x55, 0xFA, 0x88, 0x41, 0x03, 0x50, 0x49, 0xE9,
            0x28, 0xE9, 0x0C, 0xDE, 0x0A, 0x0E, 0xE0, 0xDC, 0x1F, 0x29, 0x08, 0x98,
            0x4E, 0x21, 0x86, 0xB6, 0x60, 0x0A, 0x89, 0xA2, 0xD1, 0x78, 0x3C, 0x64,
            0x02, 0x23, 0x38, 0x83, 0x18, 0xD0, 0x19, 0x21, 0x64, 0xE4, 0x10, 0x80,
            0x1A, 0xBA, 0x4F, 0x0B, 0x9E, 0x91, 0x6F, 0x0E, 0x09, 0x66, 0x82, 0xD0,
            0xB9, 0xC1, 0x03, 0xF4, 0x19, 0x80, 0x9F, 0x4A, 0x7C, 0x29, 0x30, 0xB2,
            0x05, 0x1E, 0x29, 0x40, 0x73, 0xE5, 0x30, 0x48, 0xA0, 0x37, 0x8C, 0x0B,
            0xFC, 0xFF, 0x1F, 0x08, 0x4E, 0xCD, 0x09, 0x82, 0x0E, 0x83, 0xC3, 0x9D,
            0x40, 0x02, 0x26, 0xEB, 0x5E, 0x00, 0x7D, 0x12, 0x18, 0x82, 0xFA, 0xAE,
            0x05, 0xA0, 0x00, 0xF2, 0x61, 0xC0, 0x93, 0x7F, 0x1F, 0x60, 0x53, 0x08,
            0x11, 0x26, 0x9A, 0xD1, 0xB9, 0xB4, 0xA1, 0xA3, 0xC4, 0x0C, 0x9D, 0x82,
            0x78, 0xE8, 0x0E, 0x7A, 0xEE, 0x40, 0x0F, 0xDD, 0x53, 0x7B, 0x1D, 0x78,
            0xED, 0x30, 0x81, 0x83, 0x0D, 0x9D, 0x9E, 0x39, 0xF0, 0xF3, 0x3D, 0xB4,
            0x37, 0x04, 0xCF, 0xC2, 0x63, 0x07, 0xE7, 0x48, 0x70, 0xE3, 0xF0, 0xD8,
            0xF9, 0x10, 0x3C, 0x76, 0x3E, 0x34, 0x1F, 0x41, 0xC0, 0x37, 0x26, 0xDC,
            0xE4, 0xC1, 0x08, 0x8F, 0x11, 0xB1, 0x1E, 0x59, 0xB8, 0x1B, 0xD0, 0x71,
            0xF1, 0x71, 0xFA, 0x2C, 0xF3, 0x42, 0x64, 0xEC, 0x13, 0x3D, 0x9C, 0xA2,
            0x87, 0xA9, 0xC3, 0xC2, 0x41, 0xBD, 0x8E, 0x78, 0x6C, 0xFE, 0xFF, 0xC3,
            0x7A, 0xE4, 0x1C, 0xD6, 0x68, 0xCF, 0x34, 0xFC, 0x1A, 0xE3, 0xE9, 0x1A,
            0x23, 0xAC, 0x0F, 0x30, 0xE0, 0x00, 0xC4, 0x7B, 0x9F, 0x29, 0x99, 0x80,
            0x01, 0xD9, 0x78, 0x9E, 0x06, 0xC0, 0x72, 0x04, 0x31, 0xCE, 0xEB, 0x40,
            0xB0, 0x38, 0x47, 0x71, 0x74, 0x06, 0x0A, 0x12, 0x34, 0x9E, 0xE7, 0x60,
            0x0C, 0x83, 0x47, 0x0A, 0xF4, 0x5C, 0x12, 0xE3, 0x84, 0x42, 0x3C, 0x50,
            0xE0, 0x08, 0x6A, 0x7E, 0x2F, 0xE8, 0x5C, 0x82, 0x53, 0xB9, 0x66, 0x8D,
            0xF8, 0x98, 0xF8, 0xBD, 0x04, 0xA3, 0x0D, 0x4C, 0xE7, 0x12, 0xAE, 0x0A,
            0x46, 0xA9, 0x4F, 0x13, 0xA8, 0x9C, 0xA7, 0x09, 0x0A, 0xE2, 0x33, 0x80,
            0xCF, 0x25, 0x80, 0xC5, 0x84, 0x33, 0x44, 0xAB, 0x10, 0xF0, 0xFF, 0xBF,
            0x7E, 0xE0, 0x4E, 0x53, 0x1E, 0x21, 0xDC, 0x6B, 0x0A, 0xEE, 0xF4, 0x01,
            0xC6, 0x09, 0xC2, 0x3A, 0x51, 0xF0, 0x7B, 0x0C, 0xB0, 0x95, 0x77, 0x55,
            0x40, 0x09, 0xBA, 0x2A, 0x50, 0x10, 0x5F, 0x19, 0x1C, 0xF6, 0x1E, 0x83,
            0x9E, 0x89, 0x6F, 0x63, 0xEC, 0x54, 0xE1, 0x5B, 0x12, 0x8B, 0x76, 0x91,
            0x01, 0xC5, 0x3C, 0x3D, 0x77, 0x70, 0xDC, 0x59, 0x70, 0x83, 0x3F, 0x15,
            0xEC, 0x4D, 0x06, 0xDE, 0xD0, 0x7C, 0x93, 0x01, 0x16, 0xFF, 0xFF, 0x9B,
            0x0C, 0x30, 0x1C, 0x9B, 0x6F, 0x32, 0x80, 0x53, 0x85, 0x36, 0x7D, 0x6A,
            0x34, 0x6A, 0xD5, 0xA0, 0x4C, 0x8D, 0x32, 0x0D, 0x6A, 0xF5, 0xA9, 0xD4,
            0x98, 0xB1, 0x31, 0x59, 0xC6, 0x5A, 0x35, 0x6A, 0x87, 0x00, 0xA1, 0x32,
            0x5E, 0x0E, 0x3A, 0x8C, 0x58, 0x13, 0x88, 0x80, 0x2C, 0x6E, 0xF9, 0x02,
            0xB2, 0x54, 0x10, 0x01, 0x39, 0x94, 0x07, 0x20, 0x96, 0x10, 0x44, 0x40,
            0x56, 0xBD, 0x3C, 0x01, 0x39, 0x02, 0x88, 0x80, 0x9C, 0xC7, 0x04, 0x10,
            0x4B, 0x07, 0x22, 0x20, 0xFF, 0xFF, 0x01
        })
        Name (RBUF, Buffer () {0xff,0xff,0xff})
        OperationRegion(CMOS, SystemIO, 0x70, 0x2)
        Field(CMOS,AnyAcc,NoLock,Preserve) {
            INDX, 8,
            DATA, 8,
        }
        //
        // Package Method data block
        // Arg0 has the instance being queried
        // Arg1 has the method id
        // Arg2 has the data passed
        Method (WMAC, 3, Serialized) {
            Store (Arg2, RBUF)
            CreateByteField  (RBUF, 0, DAT0)        // Return status
            CreateByteField  (RBUF, 1, DAT1)        // Return EC Register data 
            CreateByteField  (RBUF, 2, DAT2)
            if (LEqual(Arg1, 1)) { // ReadCmos
                Store (DAT0, INDX)
                Store (DATA, DAT2)
            }
            ElseIf (LEqual(Arg1, 2)) { // WriteCmos
                Store (DAT0, INDX)
                Store (DAT1, DATA)
            }
            Else{
            }
            Return (ToHexString(RBUF))
        }
    }
}
}

WQBA

该 Method 用于返回编译的 bmf 文件数据。

WMAC

WMAC 用于实现 MOF 中定义的 Method,通过 MOF 中的 WmiMethodId 来标识。如 WmiMethodId(1) 对应 ReadCmos,asl 中,WMAC 可使用 arg1 等于 1 的情况来处理。

GUID匹配

_WDG 方法中的 GUID 与 MOF 文件中的定义需保持一致,这种对应关系将 ACPI 实现与 WMI 类定义关联起来。

编译 ASL

本实验使用 QEMU 进行验证,可使用 iasl 工具直接编译 AML 文件加载。编译命令:

 iasl.exe .\WMI.asl

启用 QEMU 时,利用 -acpitable 参数添加外部的 ACPI Table,如:

 -acpitable file=/WMI.aml

三、Windows 测试

启动 QEMU 中的 Windows,管理员权限打开 powershell,输入如下命令可直接调用函数:

 $instance = Get-WmiObject -NameSpace "rootwmi" -Class "AY123" 
 $instance.ReadCmos(0)

可看到,控制台可正常打印时间的秒数。

 

四、Linux 测试

Linux 以 Ubuntu 为例。由于我本地收藏的 Ubuntu 镜像是 22.04 的,便直接拿来安装使用了。

1.安装 acpi_call:

 sudo apt update
 sudo apt install acpi-call-dkms
 sudo modprobe acpi_call

2.调用 ACPI 方法:

# 直接调用 WMAC 方法,WMAC 的定义需传入 3 个参数
# Arg0: Instance
# Arg1: Method Id
# Arg2: Parameter
# 下面示例是调用读取 CMOS 方法,传入的 0ffset 是0x00
echo '\_SB.EC.WMAC 0x01 0x01 0x00' | sudo tee /proc/acpi/call
sudo cat /proc/acpi/call  # 获取返回值

从上图中返回的结果可知道,byte 3 是读取到的秒数。

引用链接

[1] Windows Instrumentation: WMI and ACPI: https://learn.microsoft.com/zh-cn/previous-versions/windows/hardware/design/dn614028(v=vs.85)
[2] Windows-driver-samples: https://github.com/microsoft/Windows-driver-samples/tree/main/wmi/wmiacpi

版权声明:
作者:bin
链接:https://ay123.net/mystudy/bios/1863/
来源:爱影博客
文章版权归作者所有,未经允许请勿转载。

THE END
分享
二维码
海报
BIOS开发笔记 15 – WMI 在系统中的集成及应用(下)
一、前言 上一篇了解了 WMI 的基础知识,这篇则通过实例来巩固一下。下面以读写 CMOS 为例,通过 WMI 直接在操作系统进行读写。 二、编写 MOF 和 ASL 文件 首……
<<上一篇
下一篇>>
文章目录
关闭
目 录