Microsoft 提供的 UEFI 电池充电应用程序的体系结构

本主题提供有关 Microsoft 为运行 Windows 10 Mobile 的设备提供的 UEFI 电池充电应用程序设计的信息。 OEM 可以使用 Microsoft 提供的电池充电应用程序,也可以实现自己的充电应用程序。 实现自己的 UEFI 电池充电应用程序的 OEM 可以使用本主题中的信息作为设计指南。

UEFI 电池充电应用程序是启动过程中运行的首批 Microsoft 拥有的应用程序之一。 UEFI 电池充电应用程序具有以下主要职责:

  • 确保设备有足够的电源来启动。

  • 如果 OEM 启用,则提供关机充电支持。 有关关机充电的详细信息,请参阅启动环境中的电池充电

UEFI 电池充电应用程序使用关键 UEFI 协议,并对相关驱动程序返回的各种状态做出反应。

本主题中的术语 UEFI 电池充电应用程序是指由 mobilestartup.efi 加载的 UEFI 电池充电库。 有关 mobilestartup.efi 的详细信息,请参阅 Boot 和 UEFI

UEFI 电池充电应用程序使用的 UEFI 协议

UEFI 电池充电应用程序(由 Microsoft 拥有)使用以下各节中介绍的协议(由 OEM 实现)。

UEFI 电池充电协议 (EFI_BATTERY_CHARGING_PROTOCOL)

以下步骤介绍了 UEFI 电池充电应用程序如何使用 UEFI 电池充电协议的关键方面:

  1. UEFI 电池充电应用程序使用 EFI_BATTERY_CHARGING_PROTOCOL.GetBatteryInformation 轮询电池硬件的实时状态(在支持 EFI_BATTERY_CHARGING_PROTOCOL 版本 0x00010002 的设备中)或 EFI_BATTERY_CHARGING_PROTOCOL.GetBatteryStatus(在支持 EFI_BATTERY_CHARGING_PROTOCOL 的版本 0x00010001 的设备中)。 重要的是,这些函数尽可能返回准确的充电状态 (SOC) 值。 SOC 是一个 OEM 定义的映射,从基于电池状态(包括容量、电压和温度)的电池电量到从 0 到 100 的值。

  2. OEM 定义启动到主 OS 阈值(从 0 到 100 的值)。 对于不同的设备型号,此值可能不同。 有关启动到主 OS 阈值和其他阈值的详细信息,请参阅启动环境中的电池充电

  3. 电池充电应用程序使用驱动程序中的 SOC,并将其与启动到主 OS 阈值进行比较,以确定它是否需要阻止启动过程才能在 UEFI 中充电或继续启动。 它不会收到有关充电状态的其他信息。

  4. UEFI 电池充电应用程序调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 为设备充电,并等待返回 CompletionEvent 和相应的 EFI_BATTERY_CHARGING_STATUS

有关此协议的详细信息,请参阅 UEFI 电池充电协议

UEFI 显示器电源状态协议 (EFI_DISPLAY_POWER_PROTOCOL)

在 UEFI 电池充电过程中,UEFI 电池充电应用程序会显示一个交替的低功率 UI。 在没有按下电源按钮的情况下 10 秒钟后,应用程序调用 EFI_DISPLAY_POWER_PROTOCOL.SetDisplayPowerState 关闭显示器和背光。 这有助于设备在 UEFI 电池充电期间消耗更少的电量,从而有助于设备充电并更快地进入主 OS。 如果用户在显示器关闭时按下电源按钮,应用程序将再次调用 EFI_DISPLAY_POWER_PROTOCOL.SetDisplayPowerState,以重新打开显示器。 有关更多详细信息,请参阅本主题后面的用户体验

有关此协议的详细信息,请参阅 UEFI 显示器电源状态协议

UEFI USB 函数协议 (EFI_USBFN_IO_PROTOCOL)

UEFI 电池充电应用程序完全依赖于 EFI_USBFN_IO_PROTOCOL.DetectPort,来确定连接的端口类型。 应用程序根据端口类型调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery,具有 1500 毫安或 500 毫安。

有关此协议的详细信息,请参阅 UEFI USB 函数协议

应用程序逻辑

下图描述了 UEFI 电池充电应用程序的逻辑过程。

uefi battery charging logic.

以下注释扩展了逻辑的一些关键部分:

  • 调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 之前,应用程序调用 EFI_USBFN_IO_PROTOCOL.DetectPort,以确定 USB 充电器可提供的最大电流:

    • 如果存在端口,则应用程序将 1500 mA 用于专用壁式充电器,或 500 mA 用于其他端口。

    • 如果没有端口,应用程序将使用 500 mA。 无线充电器应忽略此值。

    • 如果没有充电器,应用程序将使用 500 mA。 但是,应用程序需要 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 返回状态为 EfiBatteryChargingSourceNotDetectedEFI_BATTERY_CHARGING_COMPLETION_TOKEN

  • 在任何情况下,OEM 都必须确保设备和充电器保持在安全运行区域内。

  • 如果设备中没有电池,但有连接的电源,则当应用程序调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 对电池充电,UEFI 电池充电驱动程序会返回 EfiBatteryChargingStatusBatteryNotDetected。 该应用程序会通过显示错误 UI 并关闭设备来处理此错误。

  • 除了 EfiBatteryChargingStatusSuccess 之外,EFI_BATTERY_CHARGING_STATUS 值在阈值充电关机充电模式中采用相同的方式进行解释。 有关这些充电模式的详细信息,请参阅启动环境中的电池充电

  • 当设备处于充电模式时,断开电源的连接将导致使用 EfiBatteryChargingSourceNotDetected 向应用程序发出固件信号,这将导致应用程序关闭设备。

  • 如果固件向应用程序发出状态为 EfiBatteryChargingStatusOverheatEfiBatteryChargingStatusTimeout 的信号,则设备会暂停充电 5 分钟(但应用程序仍会以大约 1 秒的间隔调用 EFI_BATTERY_CHARGING_PROTOCOL.GetBatteryInformationEFI_BATTERY_CHARGING_PROTOCOL.GetBatteryStatus)。 5 分钟后,设备通过调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 恢复充电。 在这 5 分钟内,固件仍应以适当的 EFI_BATTERY_CHARGING_STATUS 值向应用程序提供的事件发出信号(例如,源断开连接应向 EfiBatteryChargingSourceNotDetected 发出信号)。

  • 在这两种充电模式下,在上图标有 Stay in app 的方框中都会显示相应的动画 UI。

  • 关机充电模式下,如果固件发出事件信号并提供 EfiBatteryChargingStatusSuccess 的状态,则 UEFI 电池充电应用程序不会启动到主 OS,直到用户按住电源按钮 3 秒钟。 但是,如果应用程序检测到 USB 电缆此时已断开连接,则会关闭设备电源。 UEFI 电池充电应用程序要求驱动程序在关机充电模式下保持电池充满。

  • 关机充电模式下,只要固件未发出错误或成功事件信号,UEFI 电池充电应用程序就不会关闭设备的电源。

错误处理。

每次调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 时,都会指定 EFI_BATTERY_CHARGING_COMPLETION_TOKEN。 如果驱动程序遇到错误,则令牌中的事件会发出 EFI_BATTERY_CHARGING_STATUS 信号。 下表说明了 UEFI 电池充电应用程序在不同情况下对不同状态值的反应。

状态 阈值充电模式 关机充电模式(充电状态达到阈值之前和之后)
EfiBatteryChargingStatusNoneNone 非预期/无效 非预期/无效
EfiBatteryChargingStatusSuccess 启动到 OS 充电状态达到阈值之前:在关机充电模式下继续。 充电状态达到阈值后:保持关机充电模式,直到 USB 断开连接。
EfiBatteryChargingStatusOverheat 暂停充电 5 分钟,然后恢复充电 暂停充电 5 分钟,然后恢复充电
EfiBatteryChargingStatusVoltageOutOfRange 启动到 OS 启动到 OS
EfiBatteryChargingStatusCurrentOutOfRange 启动到 OS 启动到 OS
EfiBatteryChargingStatusTimeout 暂停充电 5 分钟,然后恢复充电 暂停充电 5 分钟,然后恢复充电
EfiBatteryChargingStatusAborted 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingStatusDeviceError 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingStatusExtremeCold 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingStatusBatteryChargingNotSupported 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingStatusBatteryNotDetected 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingSourceNotDetected 关机 关机
EfiBatteryChargingSourceVoltageInvalid 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingSourceCurrentInvalid 显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EfiBatteryChargingErrorRequestShutdown 关机 关机
EfiBatteryChargingErrorRequestReboot 重新启动 重新启动

下表说明了 UEFI 电池充电应用程序如何响应从 EFI_BATTERY_CHARGING_PROTOCOL.GetBatteryInformationEFI_BATTERY_CHARGING_PROTOCOL.GetBatteryStatus 接收的状态值。

状态 阈值充电模式 关机充电模式(充电状态达到阈值之前和之后)
EFI_SUCCESS。
如果未检测到任何错误,则返回此值。
不适用 不适用
EFI_INVALID_PARAMETER。
当输入参数不正确时,将返回此值。 从理论上讲,这在生产环境中是不可能实现的。
显示错误 UI 10 秒,然后关闭 显示错误 UI 10 秒,然后关闭
EFI_DEVICE_ERROR 或 EFI_NOT_READY。
以相同的方式处理这些错误情况。 如果设备由于某些设备错误而无法启动到主 OS,则应由 EFI_BATTERY_CHARGING_PROTOCOL.GetBatteryInformationEFI_BATTERY_CHARGING_PROTOCOL.GetBatteryStatus 返回这些值。 具体而言:

EfiBatteryChargingStatusAborted
EfiBatteryChargingStatusDeviceError
EfiBatteryChargingStatusExtremeCold
EfiBatteryChargingStatusBatteryChargingNotSupported
EfiBatteryChargingStatusBatteryNotDetected
EfiBatteryChargingSourceVoltageInvalid
EfiBatteryChargingSourceCurrentInvalid
EfiBatteryChargingErrorRequestShutdown
EfiBatteryChargingErrorRequestReboot。

引发 EFI_DEVICE_ERROR 或 EFI_NOT_READY,后跟上面列出的错误之一的完成令牌,将导致设备最终关闭。
恢复和调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery 恢复和调用 EFI_BATTERY_CHARGING_PROTOCOL.ChargeBattery

用户体验

下图显示了如果电池电量不足,或者设备处于关机充电模式,UEFI 电池充电应用程序如何将 UI 绘制到屏幕上。

battery charging user experience.

以下步骤描述应用程序如何将 UI 绘制到屏幕:

  • 应用程序通过将背景填充颜色写入帧中的每个像素来清除屏幕。

  • 应用程序通过将位图缓冲区中的像素直接复制到显示器来绘制备用的低功耗 UI 位图。 如果 10 秒钟后未按下电源按钮,应用程序将调用 EFI_DISPLAY_POWER_PROTOCOL.SetDisplayPowerState 关闭显示器和背光。 如果用户按下电源按钮,则调用 EFI_DISPLAY_POWER_PROTOCOL.SetDisplayPowerState 以重新打开显示器。

  • 当应用程序从驱动程序接收到错误时,应用程序通过将背景填充颜色写入帧缓冲区中的每个像素来清除屏幕,然后应用程序通过直接将像素从适当的位图缓冲区复制到显示器来绘制电池错误屏幕。