You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

类DOS EFI操作系统0x01-0x1F键值捕获异常及ESC/ENTER问题修复咨询

EFI按键捕获模块修复:控制键捕获+ESC/ENTER异常处理

问题原因拆解

  1. 无法捕获0x01-0x1F控制键:
    这类控制键的UnicodeChar对应ASCII控制码,直接用printf("%c")输出会显示不可见字符,且原代码仅通过ScanCode判断功能键,遗漏了仅靠UnicodeChar标识的Ctrl组合键(如Ctrl+A的ScanCode为0,UnicodeChar为0x01)。

  2. ESC键触发时复制之前输入的字符:
    ESC键的UnicodeChar是0x1B(而非空),若原代码逻辑误将ESC的处理放在输出之后,会输出该字符并触发终端异常回显;另外未对功能键的输出做过滤,导致终端行为混乱。

  3. ENTER键触发时光标回到行首:
    ENTER键的UnicodeChar是0x0D(回车符),仅输出这个字符只会让光标回到行首,不会换行;且原代码未在终止前跳过该字符的输出。

修复方案及代码

调整逻辑顺序,区分功能键、控制键和普通字符的处理:

#include "uefi/uefi.h"

// 若uefi.h未定义扫描码,手动添加常用键定义
#define SCAN_ESC    0x01
#define SCAN_RETURN 0x1C

int main(int argc, char **argv) {
    efi_input_key_t ch;
    char command[1024] = "";
    int len = 0;

    while (1) {
        // 等待按键事件
        ST->BootServices->WaitForEvent(1, &(ST->ConIn->WaitForKey), NULL);
        ST->ConIn->ReadKeyStroke(ST->ConIn, &ch);

        // 先处理终止键,避免误输出
        if (ch.ScanCode == SCAN_ESC) {
            break;
        }
        if (ch.ScanCode == SCAN_RETURN) {
            // 输出完整换行,解决光标回行首问题
            printf("\r\n");
            // 若要把ENTER设为终止键,取消下面的注释
            // break;
            // 否则将换行符存入缓冲区(可选)
            if (len < sizeof(command) - 1) {
                command[len++] = '\n';
                command[len] = '\0';
            }
            continue;
        }

        // 处理0x01-0x1F的控制键,转为^A、^B等可见形式
        if (ch.UnicodeChar >= 0x01 && ch.UnicodeChar <= 0x1F) {
            printf("^%c", ch.UnicodeChar + '@');
            // 可选:将控制键的可见形式存入缓冲区
            if (len < sizeof(command) - 2) {
                command[len++] = '^';
                command[len++] = ch.UnicodeChar + '@';
                command[len] = '\0';
            }
            continue;
        }

        // 仅处理可打印的ASCII字符(0x20-0x7E)
        if (ch.UnicodeChar >= 0x20 && ch.UnicodeChar <= 0x7E) {
            printf("%c", ch.UnicodeChar);
            if (len < sizeof(command) - 1) {
                command[len++] = ch.UnicodeChar;
                command[len] = '\0';
            }
        }
    }

    return 0;
}

关键修改点

  • 终止键优先判断:把ESC/ENTER的判断放在最前面,彻底避免功能键的Unicode字符被误输出
  • 控制键可视化:将0x01-0x1F的控制键转为^A这类可见标识,既解决捕获问题,又方便调试
  • ENTER键正确换行:输出\r\n实现DOS风格的换行,避免光标停在行首
  • 过滤无效字符:仅处理可打印字符,防止乱码或终端异常行为

内容的提问来源于stack exchange,提问作者user14683910

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.03 12:30:54