I want to read the mouse pointer position within the UEFI. I found a protocol called SimplePointerProtocol
which should allow me to do that.
I have the following Zig code with many comments so that Zig illiterates understand.
// Some imports. The Zig standard library covers the UEFI API.
const std = @import("std");
const uefi = std.os.uefi;
// The console output protocol
var con_out: *uefi.protocols.SimpleTextOutputProtocol = undefined;
// Printing facilities. You can ignore this.
var buf: [256]u8 = undefined;
fn printf(comptime format: []const u8, args: anytype) void {
const formatted_buf = std.fmt.bufPrint(buf[0..], format, args) catch unreachable;
for (formatted_buf) |c| {
const c_ = [2]u16{ c, 0 };
_ = con_out.outputString(@ptrCast(*const [1:0]u16, &c_));
}
}
pub fn main() void {
const boot_services = uefi.system_table.boot_services.?;
// Obtain the simple pointer protocol
var simple_pointer_protocol: *uefi.protocols.SimplePointerProtocol = undefined;
_ = boot_services.locateProtocol(&uefi.protocols.SimplePointerProtocol.guid, null, @ptrCast(*?*anyopaque, &simple_pointer_protocol));
// Obtain the console output protocol
con_out = uefi.system_table.con_out.?;
// Clear the screen
_ = con_out.reset(false);
printf("{s}", .{"waiting for mouse input..."});
// Await events
var index: usize = undefined; // This is unused
var simple_pointer_state: uefi.protocols.SimplePointerState = undefined;
while (boot_services.waitForEvent(1, @ptrCast([*]uefi.Event, &simple_pointer_protocol.wait_for_input), &index) == uefi.Status.Success) {
printf("{s}", .{"data received"});
// Get the mouse pointer state and print it
_ = simple_pointer_protocol.getState(&simple_pointer_state);
printf("X: {}, Y: {}", .{ simple_pointer_state.relative_movement_x, simple_pointer_state.relative_movement_y });
}
}
This code compiles and seems to work.
The problem is that it never emits any event.
I allow QEMU to grab my mouse but no matter whether I move the mouse, press buttons or anything, it seems to wait at waitForEvent
forever:
Now I believe this is actually more of a problem with QEMU and or OVMF itself.
Here is how I start QEMU:
qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hdd fat:rw:. -serial stdio
Am I missing any flags for this to work?
I also tried this:
qemu-system-x86_64 -bios /usr/share/ovmf/OVMF.fd -hdd fat:rw:. -serial stdio -usb -device usb-mouse -device usb-kbd -show-cursor
and other combinations. Nothing seems to do the trick.
How can I read the mouse pointer position within the UEFI using QEMU or any other UEFI emulator?
As an alternative, does anyone have good resources for using the USB protocols/interfaces provided by UEFI (EFI_USB2_HC_PROTOCOL
, EFI_USB_IO_PROTOCOL
etc.) and read the mouse data myself?