OvmfPkg/VirtioInputDxe: omit partial keystrokes

WaitForKey and ReadKeyStroke of SIMPLE_TEXT_INPUT must omit partial
keystrokes, as they do not return modifier and shift state (thus a
partial keystroke would read as an empty struct). Skip over partial
keystrokes in the key queue, should there be any.

Note that WaitForKeyEx of SIMPLE_TEXT_INPUT_EX must also omit partials,
thus it continues to share the implementation with WaitForKey -- unlike
ReadKeyStrokeEx and ReadKeyStroke.

Signed-off-by: Ivan Shapovalov <intelfx@intelfx.name>
Tested-by: Alexander Mikhalitsyn <aleksandr.mikhalitsyn@futurfusion.io>
This commit is contained in:
Ivan Shapovalov 2026-07-28 08:57:05 +03:00 committed by mergify[bot]
parent 1c05d44715
commit 434239eeab

View file

@ -444,8 +444,22 @@ VirtioKeyboardReadKeyStroke (
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
Status = PopEfikeyBufHead (&Dev->KeyQueue, &KeyData);
*Key = KeyData.Key;
//
// ReadKeyStroke of SIMPLE_TEXT_INPUT must omit partial keystrokes
//
while (TRUE) {
Status = PopEfikeyBufHead (&Dev->KeyQueue, &KeyData);
if (EFI_ERROR (Status)) {
break;
}
if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
continue;
}
*Key = KeyData.Key;
break;
}
gBS->RestoreTPL (OldTpl);
@ -464,6 +478,8 @@ VirtioKeyboardWaitForKey (
{
VIRTIO_INPUT_DEV *Dev = (VIRTIO_INPUT_DEV *)Context;
EFI_TPL OldTpl;
EFI_KEY_DATA KeyData;
EFI_STATUS Status;
//
// Stall 1ms to give a chance to let other driver interrupt this routine
@ -482,9 +498,23 @@ VirtioKeyboardWaitForKey (
OldTpl = gBS->RaiseTPL (TPL_NOTIFY);
//
// If there is a new key ready - send signal
if (!IsEfikeyBufEmpty (&Dev->KeyQueue)) {
// WaitForKey(Ex) must omit partial keystrokes
//
while (TRUE) {
Status = PeekEfikeyBufHead (&Dev->KeyQueue, &KeyData);
if (EFI_ERROR (Status)) {
break;
}
if ((KeyData.Key.ScanCode == SCAN_NULL) && (KeyData.Key.UnicodeChar == CHAR_NULL)) {
(void)PopEfikeyBufHead (&Dev->KeyQueue, NULL);
continue;
}
gBS->SignalEvent (Event);
break;
}
gBS->RestoreTPL (OldTpl);