如何在GNU-UEFI中处理timer、keyboard等外设的中断?
GNU UEFI 下设备中断处理方案
首先明确核心前提:UEFI Boot Services 运行阶段,固件已经完成了中断控制器初始化、IDT配置与中断路由的管理,不允许用户程序直接调用lidt指令重写IDT,所有中断相关操作需要通过UEFI提供的官方Boot Services接口或者设备协议实现。
常见设备中断处理方式
1. 定时器中断
UEFI封装了定时器事件接口,不需要直接处理硬件定时器中断,直接创建事件绑定回调即可:
// 初始化定时器事件 EFI_EVENT timer_event; EFI_STATUS status = uefi_call_wrapper(gBS->CreateEvent, 5, EVT_TIMER | EVT_NOTIFY_SIGNAL, TPL_CALLBACK, 你的回调函数指针, NULL, &timer_event); // 设置1秒触发一次的周期性定时器 status = uefi_call_wrapper(gBS->SetTimer, 3, timer_event, TimerPeriodic, 10000000); // 单位为100纳秒,10^7对应1秒
2. 键盘输入中断
UEFI提供了EFI_SIMPLE_TEXT_INPUT_PROTOCOL协议处理键盘输入,异步响应按键可以直接监听WaitForKey事件:
// 监听按键事件 EFI_EVENT key_events[1] = {gST->ConIn->WaitForKey}; UINTN index; while(1) { status = uefi_call_wrapper(gBS->WaitForEvent, 3, 1, key_events, &index); if (EFI_ERROR(status)) break; EFI_INPUT_KEY key; status = uefi_call_wrapper(gST->ConIn->ReadKeyStroke, 2, gST->ConIn, &key); if (!EFI_ERROR(status)) { // 此处处理按键逻辑,比如打印按键码 Print(L"收到按键:ScanCode %04x, UnicodeChar %04x\n", key.ScanCode, key.UnicodeChar); } }
3. 自定义硬件设备的中断处理
如果你需要处理非标准设备的原生中断,可以通过RegisterInterruptHandler接口注册中断回调:
// 注册中断处理函数,vector是你要处理的中断向量号 EFI_STATUS status = uefi_call_wrapper(gBS->RegisterInterruptHandler, 3, vector, 你的中断处理函数指针, NULL);
注册自定义中断注意事项:
- 中断处理函数运行在高任务优先级(TPL_HIGH_LEVEL),不能调用大部分Boot Services接口,只能做简单的中断响应、清中断操作
- 中断处理完成后需要向中断控制器发送EOI(中断结束)信号
- 调用
ExitBootServices()之后,固件会交出所有硬件控制权,此时你可以自行初始化中断控制器、重写IDT,和BIOS裸机开发的逻辑完全一致
内容的提问来源于stack exchange,提问作者Elhadede
相关产品推荐
相关产品推荐

