Step to UEFI (296)虚拟机下的假电池

电池作为现在笔记本必不可少的部件,通过 ACPI 和 Windows 进行交互。

对此,ACPI Spec 定义了几个 Table。换一句话说,Windows 只要能够正确读取出 Table,那么就可以根据上面的信息展示给客户一个电池。

第一个是 _BIX (Battery Information Extended) (特别注意ACPI 4.0定义的 _BIF (Battery Information)已经废止 ),其中给出了电池的信息。

偏移名称大小解释
RevisionDWORD目前版本号为 1
Power UnitDWORD电池容量单位: 0 – [mWh], 同时充放电速度将会以[mW]为单位 1 – [mAh], 同时充放电速度将会以[mA]为单位
Design CapacityDWORD设计容量,单位由上面的 Power Unit 给出 取值范围: 0x00000000-0x7FFF FFFF 0xFFFFFFFF 未知容量
Last Full Charge CapacityDWORD充满后的预期容量 取值范围: 0x00000000-0x7FFF FFFF 0xFFFFFFFF 未知容量
Battery TechnologyDWORD电池位置 0x0000 0000 主电池 0x0000 0001 第二块电池
Design VoltageDWORD设计电压, 取值范围 0x000000000 – 0x7FFFFFFF in [mV] 0xFFFFFFFF – 未知电压
Design Capacity of WarningDWORDOEM 设置的告警容量值 取值范围 0x000000000 – 0x7FFFFFFF in [mWh] or [mAh]
Design Capacity of LowDWORDOEM 设置的低容量值 取值范围 0x000000000 – 0x7FFFFFFF in [mWh] or [mAh]
Cycle CountDWORD充电循环次数 取值范围 0x000000000 – 0xFFFFFFFF
Measurement AccuracyDWORD电池容量测量准确度,以1/1000为单位,比如:80000表示80%
Max Sampling TimeDWORD_BST 中两次测量的最大间隔时间,比如,当前电池容量,放电速度或者剩余容量。以为毫秒单位。0xFFFFFFFF表示该位置无效。
Min Sampling TimeDWORD_BST 中两次测量的最小间隔时间。以为毫秒单位。0xFFFFFFFF表示该位置无效。
Max Averaging IntervalDWORD_BST 中两次测量的平均最大间隔时间。
Min Averaging IntervalDWORDBST 中两次测量的平均最小间隔时间。
Battery Capacity Granularity 1DWORD电池在告警容量值和低容量值之间的颗粒度
Battery Capacity Granularity 2DWORD电池在告警容量值和充满容量值之间的颗粒度
Model Number零结尾ASCII字符串OEM 定义的电池型号
Serial Number零结尾ASCII字符串OEM 定义的电池序列号
Battery Type零结尾ASCII字符串OEM 定义的电池类型
OEM Information零结尾ASCII字符串OEM 定义的在UI上展示的电池OEM信息
Battery Swapping CapabilityDWORD0x0 不可更换电池,例如,内部密封电池,用户无法接触到 0x1关机之后可更换电池 0x10 热插拔电池
上述根据ACPI Spec翻译,如果有错误欢迎指出,会进行订正

第二个是 _BST (Battery Status), 这个用于报告当前电池的状态信息。

偏移名称大小解释
Battery StateDWORDBit0 为1表示正在放电 Bit1  为1表示正在充电 Bit2  为1表示电池预警  
Battery Present RateDWORD电池充放电速度 取值范围 0x000000000 – 0x7FFFFFFF以[mW]或者[mA]为单位 0xFFFFFFFF – 未知速度    
Battery Remaining CapacityDWORD电池剩余容量 取值范围 0x000000000 – 0x7FFFFFFF以[mWh]或者[mAh]为单位 0xFFFFFFFF – 未知容量  
Battery Present VoltageDWORD电池电压 取值范围 0x000000000 – 0x7FFFFFFF以[mV]为单位 0xFFFFFFFF – 未知电压  

以本人的电脑(HP 840 G6)为例,设备管理器中可以看到电池:

使用 HE 直接读取 ACPI Table:

根据上面的整理出两个对应的Table, 放在 BAT0 设备中

Device (BAT0)
        {
            Name (_HID, EisaId ("PNP0C0A") /* Control Method Battery */)  // _HID: Hardware ID
            Name (_UID, One)  // _UID: Unique ID
            Method (_DSM, 4, Serialized)  // _DSM: Device-Specific Method
            {
                If (LEqual (Arg0, ToUUID ("4c2067e3-887d-475c-9720-4af1d3ed602e") /* Battery Thermal Limit */))
                {
                    Switch (ToInteger (Arg2))
                    {
                        Case (0x03)
                        {
                            Return (Package (0x01)
                            {
                                0x1E
                            })
                        }

                    }
                }
                Else
                {
                    Return (Package (0x01)
                    {
                        Zero
                    })
                }
            }

            Method (_STA, 0, NotSerialized)  // _STA: Status
            {
                Return (0x1F)
            }

            Method (_BIX, 0, NotSerialized)  // _BIX: Battery Information Extended
            {
                Return ( Package (0x15)
						{
							1, 
							1, 
							20000, 
							20000, 
							0, 
							4300, 
							2000, 
							1000, 
							10, 
							80000, 
							1000, 
							500, 
							750, 
							500, 
							0x64, 
							0x64, 
							"LABZBAT0", 
							"202410", 
							"MODOL1", 
							"LABZBAT0", 
							One
						})
            }

            Method (_BST, 0, NotSerialized)  // _BST: Battery Status
            {
                Return ( Package (0x04)	{
               			 1, 
               			 100, 
                		 10000, 
                		 4200
           			   })
            }

        }

     }

接下来选择使用 VirtualBox 虚拟机,根据【参考1】,替换内部的 ACPI Table, 最终效果如下:

就是说,我们成功的在这个虚拟机中安装了一块电量为 50% 的电池。

本文提到的修改后的 ACPI 源代码可以在这里下载:

参考:

1.https://www.lab-z.com/arcpi/