From 8ae99a83d455c04446437bec7d88aafcc95501ec Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Mon, 29 Jul 2024 10:50:55 +0200 Subject: [PATCH 1/5] OvmfPkg: Add virtio keyboard device hooks MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This commit adds: - missing virtio subsystem ID for input device - PrepareVirtioKeyboardDevicePath() handler to boot manager library Signed-off-by: Paweł Poławski --- OvmfPkg/Include/IndustryStandard/Virtio10.h | 1 + .../PlatformBootManagerLib/BdsPlatform.c | 29 +++++++++++++++++++ 2 files changed, 30 insertions(+) diff --git a/OvmfPkg/Include/IndustryStandard/Virtio10.h b/OvmfPkg/Include/IndustryStandard/Virtio10.h index c47bcbd41ab7..601a26a476d8 100644 --- a/OvmfPkg/Include/IndustryStandard/Virtio10.h +++ b/OvmfPkg/Include/IndustryStandard/Virtio10.h @@ -17,6 +17,7 @@ // Subsystem Device IDs (to be) introduced in VirtIo 1.0 // #define VIRTIO_SUBSYSTEM_GPU_DEVICE 16 +#define VIRTIO_SUBSYSTEM_INPUT 18 // // Subsystem Device IDs from the VirtIo spec at git commit 87fa6b5d8155; // . diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c index a44e45df8f6b..9f93bdfacd51 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -1060,6 +1060,28 @@ PrepareVirtioSerialDevicePath ( return EFI_SUCCESS; } +EFI_STATUS +PrepareVirtioKeyboardDevicePath ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath = NULL; + Status = gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID *)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + return EFI_SUCCESS; +} + EFI_STATUS VisitAllInstancesOfProtocol ( IN EFI_GUID *Id, @@ -1236,6 +1258,13 @@ DetectAndPreparePlatformPciDevicePath ( return EFI_SUCCESS; } + if ((Pci->Hdr.VendorId == 0x1af4) && (Pci->Hdr.DeviceId == 0x1052)) + { + DEBUG ((DEBUG_INFO, "Found virtio keyboard device\n")); + PrepareVirtioKeyboardDevicePath (Handle); + return EFI_SUCCESS; + } + return Status; } From 9d6306664ef4ff9145394401a1d78dcc9a8b60fa Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Thu, 19 Dec 2024 01:30:10 +0100 Subject: [PATCH 2/5] OvmfPkg: Virtio based keyboard driver implementation MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This is virtio based keyboard driver designed to be used on ARM platform. The driver implements basic and extended text input interface. UEFI shell requires only basic text input interface, but Grub needs extended text input to work on. Signed-off-by: Paweł Poławski --- OvmfPkg/VirtioKeyboardDxe/VirtioKeyCodes.h | 294 ++++ OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.c | 1520 ++++++++++++++++++ OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.h | 209 +++ OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf | 41 + 4 files changed, 2064 insertions(+) create mode 100644 OvmfPkg/VirtioKeyboardDxe/VirtioKeyCodes.h create mode 100644 OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.c create mode 100644 OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.h create mode 100644 OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf diff --git a/OvmfPkg/VirtioKeyboardDxe/VirtioKeyCodes.h b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyCodes.h new file mode 100644 index 000000000000..457911c268ae --- /dev/null +++ b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyCodes.h @@ -0,0 +1,294 @@ +/** @file + + Key codes definitions for the VirtioKeyboard driver + + This is a fork of common Linux key codes: + https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h + + Copyright (C) 2024, Red Hat + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIO_KEYBOARD_KEY_CODES_H_ +#define _VIRTIO_KEYBOARD_KEY_CODES_H_ + +/* + * Event types + */ +#define EV_SYN 0x00 +#define EV_KEY 0x01 + +/* + * Keys and buttons + */ +#define KEY_RESERVED 0 +#define KEY_ESC 1 +#define KEY_1 2 +#define KEY_2 3 +#define KEY_3 4 +#define KEY_4 5 +#define KEY_5 6 +#define KEY_6 7 +#define KEY_7 8 +#define KEY_8 9 +#define KEY_9 10 +#define KEY_0 11 +#define KEY_MINUS 12 +#define KEY_EQUAL 13 +#define KEY_BACKSPACE 14 +#define KEY_TAB 15 +#define KEY_Q 16 +#define KEY_W 17 +#define KEY_E 18 +#define KEY_R 19 +#define KEY_T 20 +#define KEY_Y 21 +#define KEY_U 22 +#define KEY_I 23 +#define KEY_O 24 +#define KEY_P 25 +#define KEY_LEFTBRACE 26 +#define KEY_RIGHTBRACE 27 +#define KEY_ENTER 28 +#define KEY_LEFTCTRL 29 +#define KEY_A 30 +#define KEY_S 31 +#define KEY_D 32 +#define KEY_F 33 +#define KEY_G 34 +#define KEY_H 35 +#define KEY_J 36 +#define KEY_K 37 +#define KEY_L 38 +#define KEY_SEMICOLON 39 +#define KEY_APOSTROPHE 40 +#define KEY_GRAVE 41 +#define KEY_LEFTSHIFT 42 +#define KEY_BACKSLASH 43 +#define KEY_Z 44 +#define KEY_X 45 +#define KEY_C 46 +#define KEY_V 47 +#define KEY_B 48 +#define KEY_N 49 +#define KEY_M 50 +#define KEY_COMMA 51 +#define KEY_DOT 52 +#define KEY_SLASH 53 +#define KEY_RIGHTSHIFT 54 +#define KEY_KPASTERISK 55 +#define KEY_LEFTALT 56 +#define KEY_SPACE 57 +#define KEY_CAPSLOCK 58 +#define KEY_F1 59 +#define KEY_F2 60 +#define KEY_F3 61 +#define KEY_F4 62 +#define KEY_F5 63 +#define KEY_F6 64 +#define KEY_F7 65 +#define KEY_F8 66 +#define KEY_F9 67 +#define KEY_F10 68 +#define KEY_NUMLOCK 69 +#define KEY_SCROLLLOCK 70 +#define KEY_KP7 71 +#define KEY_KP8 72 +#define KEY_KP9 73 +#define KEY_KPMINUS 74 +#define KEY_KP4 75 +#define KEY_KP5 76 +#define KEY_KP6 77 +#define KEY_KPPLUS 78 +#define KEY_KP1 79 +#define KEY_KP2 80 +#define KEY_KP3 81 +#define KEY_KP0 82 +#define KEY_KPDOT 83 + +#define KEY_ZENKAKUHANKAKU 85 +#define KEY_102ND 86 +#define KEY_F11 87 +#define KEY_F12 88 +#define KEY_RO 89 +#define KEY_KATAKANA 90 +#define KEY_HIRAGANA 91 +#define KEY_HENKAN 92 +#define KEY_KATAKANAHIRAGANA 93 +#define KEY_MUHENKAN 94 +#define KEY_KPJPCOMMA 95 +#define KEY_KPENTER 96 +#define KEY_RIGHTCTRL 97 +#define KEY_KPSLASH 98 +#define KEY_SYSRQ 99 +#define KEY_RIGHTALT 100 +#define KEY_LINEFEED 101 +#define KEY_HOME 102 +#define KEY_UP 103 +#define KEY_PAGEUP 104 +#define KEY_LEFT 105 +#define KEY_RIGHT 106 +#define KEY_END 107 +#define KEY_DOWN 108 +#define KEY_PAGEDOWN 109 +#define KEY_INSERT 110 +#define KEY_DELETE 111 +#define KEY_MACRO 112 +#define KEY_MUTE 113 +#define KEY_VOLUMEDOWN 114 +#define KEY_VOLUMEUP 115 +#define KEY_POWER 116 /* SC System Power Down */ +#define KEY_KPEQUAL 117 +#define KEY_KPPLUSMINUS 118 +#define KEY_PAUSE 119 +#define KEY_SCALE 120 /* AL Compiz Scale (Expose) */ + +#define KEY_KPCOMMA 121 +#define KEY_HANGEUL 122 +#define KEY_HANGUEL KEY_HANGEUL +#define KEY_HANJA 123 +#define KEY_YEN 124 +#define KEY_LEFTMETA 125 +#define KEY_RIGHTMETA 126 +#define KEY_COMPOSE 127 + +#define KEY_STOP 128 /* AC Stop */ +#define KEY_AGAIN 129 +#define KEY_PROPS 130 /* AC Properties */ +#define KEY_UNDO 131 /* AC Undo */ +#define KEY_FRONT 132 +#define KEY_COPY 133 /* AC Copy */ +#define KEY_OPEN 134 /* AC Open */ +#define KEY_PASTE 135 /* AC Paste */ +#define KEY_FIND 136 /* AC Search */ +#define KEY_CUT 137 /* AC Cut */ +#define KEY_HELP 138 /* AL Integrated Help Center */ +#define KEY_MENU 139 /* Menu (show menu) */ +#define KEY_CALC 140 /* AL Calculator */ +#define KEY_SETUP 141 +#define KEY_SLEEP 142 /* SC System Sleep */ +#define KEY_WAKEUP 143 /* System Wake Up */ +#define KEY_FILE 144 /* AL Local Machine Browser */ +#define KEY_SENDFILE 145 +#define KEY_DELETEFILE 146 +#define KEY_XFER 147 +#define KEY_PROG1 148 +#define KEY_PROG2 149 +#define KEY_WWW 150 /* AL Internet Browser */ +#define KEY_MSDOS 151 +#define KEY_COFFEE 152 /* AL Terminal Lock/Screensaver */ +#define KEY_SCREENLOCK KEY_COFFEE +#define KEY_ROTATE_DISPLAY 153 /* Display orientation for e.g. tablets */ +#define KEY_DIRECTION KEY_ROTATE_DISPLAY +#define KEY_CYCLEWINDOWS 154 +#define KEY_MAIL 155 +#define KEY_BOOKMARKS 156 /* AC Bookmarks */ +#define KEY_COMPUTER 157 +#define KEY_BACK 158 /* AC Back */ +#define KEY_FORWARD 159 /* AC Forward */ +#define KEY_CLOSECD 160 +#define KEY_EJECTCD 161 +#define KEY_EJECTCLOSECD 162 +#define KEY_NEXTSONG 163 +#define KEY_PLAYPAUSE 164 +#define KEY_PREVIOUSSONG 165 +#define KEY_STOPCD 166 +#define KEY_RECORD 167 +#define KEY_REWIND 168 +#define KEY_PHONE 169 /* Media Select Telephone */ +#define KEY_ISO 170 +#define KEY_CONFIG 171 /* AL Consumer Control Configuration */ +#define KEY_HOMEPAGE 172 /* AC Home */ +#define KEY_REFRESH 173 /* AC Refresh */ +#define KEY_EXIT 174 /* AC Exit */ +#define KEY_MOVE 175 +#define KEY_EDIT 176 +#define KEY_SCROLLUP 177 +#define KEY_SCROLLDOWN 178 +#define KEY_KPLEFTPAREN 179 +#define KEY_KPRIGHTPAREN 180 +#define KEY_NEW 181 /* AC New */ +#define KEY_REDO 182 /* AC Redo/Repeat */ + +#define KEY_F13 183 +#define KEY_F14 184 +#define KEY_F15 185 +#define KEY_F16 186 +#define KEY_F17 187 +#define KEY_F18 188 +#define KEY_F19 189 +#define KEY_F20 190 +#define KEY_F21 191 +#define KEY_F22 192 +#define KEY_F23 193 +#define KEY_F24 194 + +#define KEY_PLAYCD 200 +#define KEY_PAUSECD 201 +#define KEY_PROG3 202 +#define KEY_PROG4 203 +#define KEY_ALL_APPLICATIONS 204 /* AC Desktop Show All Applications */ +#define KEY_DASHBOARD KEY_ALL_APPLICATIONS +#define KEY_SUSPEND 205 +#define KEY_CLOSE 206 /* AC Close */ +#define KEY_PLAY 207 +#define KEY_FASTFORWARD 208 +#define KEY_BASSBOOST 209 +#define KEY_PRINT 210 /* AC Print */ +#define KEY_HP 211 +#define KEY_CAMERA 212 +#define KEY_SOUND 213 +#define KEY_QUESTION 214 +#define KEY_EMAIL 215 +#define KEY_CHAT 216 +#define KEY_SEARCH 217 +#define KEY_CONNECT 218 +#define KEY_FINANCE 219 /* AL Checkbook/Finance */ +#define KEY_SPORT 220 +#define KEY_SHOP 221 +#define KEY_ALTERASE 222 +#define KEY_CANCEL 223 /* AC Cancel */ +#define KEY_BRIGHTNESSDOWN 224 +#define KEY_BRIGHTNESSUP 225 +#define KEY_MEDIA 226 + +#define KEY_SWITCHVIDEOMODE 227 /* Cycle between available video + outputs (Monitor/LCD/TV-out/etc) */ +#define KEY_KBDILLUMTOGGLE 228 +#define KEY_KBDILLUMDOWN 229 +#define KEY_KBDILLUMUP 230 + +#define KEY_SEND 231 /* AC Send */ +#define KEY_REPLY 232 /* AC Reply */ +#define KEY_FORWARDMAIL 233 /* AC Forward Msg */ +#define KEY_SAVE 234 /* AC Save */ +#define KEY_DOCUMENTS 235 + +#define KEY_BATTERY 236 + +#define KEY_BLUETOOTH 237 +#define KEY_WLAN 238 +#define KEY_UWB 239 + +#define KEY_UNKNOWN 240 + +#define KEY_VIDEO_NEXT 241 /* drive next video source */ +#define KEY_VIDEO_PREV 242 /* drive previous video source */ +#define KEY_BRIGHTNESS_CYCLE 243 /* brightness up, after max is min */ +#define KEY_BRIGHTNESS_AUTO 244 /* Set Auto Brightness: manual + brightness control is off, + rely on ambient */ +#define KEY_BRIGHTNESS_ZERO KEY_BRIGHTNESS_AUTO +#define KEY_DISPLAY_OFF 245 /* display device to off state */ + +#define KEY_WWAN 246 /* Wireless WAN (LTE, UMTS, GSM, etc.) */ +#define KEY_WIMAX KEY_WWAN +#define KEY_RFKILL 247 /* Key that controls all radios */ + +#define KEY_MICMUTE 248 /* Mute / unmute the microphone */ + +/* Code 255 is reserved for special needs of AT keyboard driver */ + +#endif diff --git a/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.c b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.c new file mode 100644 index 000000000000..837aeb113579 --- /dev/null +++ b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.c @@ -0,0 +1,1520 @@ +/** @file + + This driver produces EFI_SIMPLE_TEXT_INPUT_PROTOCOL for virtarm devices. + + Copyright (C) 2024, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include +#include + +// ----------------------------------------------------------------------------- +// Return buffer pointer out of the ring buffer +STATIC +VOID * +BufferPtr ( + IN VIRTIO_KBD_RING *Ring, + IN UINT32 BufferNr + ) +{ + return Ring->Buffers + Ring->BufferSize * BufferNr; +} + +// ----------------------------------------------------------------------------- +// Return buffer physical address out of the ring buffer +STATIC +EFI_PHYSICAL_ADDRESS +BufferAddr ( + IN VIRTIO_KBD_RING *Ring, + IN UINT32 BufferNr + ) +{ + return Ring->DeviceAddress + Ring->BufferSize * BufferNr; +} + +// Return next buffer from ring +STATIC +UINT32 +BufferNext ( + IN VIRTIO_KBD_RING *Ring + ) +{ + return Ring->Indices.NextDescIdx % Ring->Ring.QueueSize; +} + +// ----------------------------------------------------------------------------- +// Push the buffer to the device +EFI_STATUS +EFIAPI +VirtioKeyboardRingSendBuffer ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index, + IN VOID *Data, + IN UINT32 DataSize, + IN BOOLEAN Notify + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + UINT32 BufferNr = BufferNext (Ring); + UINT16 Idx = *Ring->Ring.Avail.Idx; + UINT16 Flags = 0; + + ASSERT (DataSize <= Ring->BufferSize); + + if (Data) { + /* driver -> device */ + CopyMem (BufferPtr (Ring, BufferNr), Data, DataSize); + } else { + /* device -> driver */ + Flags |= VRING_DESC_F_WRITE; + } + + VirtioAppendDesc ( + &Ring->Ring, + BufferAddr (Ring, BufferNr), + DataSize, + Flags, + &Ring->Indices + ); + + Ring->Ring.Avail.Ring[Idx % Ring->Ring.QueueSize] = + Ring->Indices.HeadDescIdx % Ring->Ring.QueueSize; + Ring->Indices.HeadDescIdx = Ring->Indices.NextDescIdx; + Idx++; + + // Force compiler to not optimize this code + MemoryFence (); + *Ring->Ring.Avail.Idx = Idx; + MemoryFence (); + + if (Notify) { + Dev->VirtIo->SetQueueNotify (Dev->VirtIo, Index); + } + + return EFI_SUCCESS; +} + +// ----------------------------------------------------------------------------- +// Look for buffer ready to be processed +BOOLEAN +EFIAPI +VirtioKeyboardRingHasBuffer ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + UINT16 UsedIdx = *Ring->Ring.Used.Idx; + + if (!Ring->Ready) { + return FALSE; + } + + if (Ring->LastUsedIdx == UsedIdx) { + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------- +// Get data from buffer which is marked as ready from device +BOOLEAN +EFIAPI +VirtioKeyboardRingGetBuffer ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index, + OUT VOID *Data, + OUT UINT32 *DataSize + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + UINT16 UsedIdx = *Ring->Ring.Used.Idx; + volatile VRING_USED_ELEM *UsedElem; + + if (!Ring->Ready) { + return FALSE; + } + + if (Ring->LastUsedIdx == UsedIdx) { + return FALSE; + } + + UsedElem = Ring->Ring.Used.UsedElem + (Ring->LastUsedIdx % Ring->Ring.QueueSize); + + if (UsedElem->Len > Ring->BufferSize) { + DEBUG ((DEBUG_ERROR, "%a:%d: %d: invalid length\n", __func__, __LINE__, Index)); + UsedElem->Len = 0; + } + + if (Data && DataSize) { + CopyMem (Data, BufferPtr (Ring, UsedElem->Id), UsedElem->Len); + *DataSize = UsedElem->Len; + } + + if (Index % 2 == 0) { + /* RX - re-queue buffer */ + VirtioKeyboardRingSendBuffer (Dev, Index, NULL, Ring->BufferSize, FALSE); + } + + Ring->LastUsedIdx++; + return TRUE; +} + +// ----------------------------------------------------------------------------- +// Initialize ring buffer +EFI_STATUS +EFIAPI +VirtioKeyboardInitRing ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index, + IN UINT32 BufferSize + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + EFI_STATUS Status; + UINT16 QueueSize; + UINT64 RingBaseShift; + + // + // step 4b -- allocate request virtqueue + // + Status = Dev->VirtIo->SetQueueSel (Dev->VirtIo, Index); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status = Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // VirtioKeyboard uses one descriptor + // + if (QueueSize < 1) { + Status = EFI_UNSUPPORTED; + goto Failed; + } + + Status = VirtioRingInit (Dev->VirtIo, QueueSize, &Ring->Ring); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // If anything fails from here on, we must release the ring resources. + // + Status = VirtioRingMap ( + Dev->VirtIo, + &Ring->Ring, + &RingBaseShift, + &Ring->RingMap + ); + if (EFI_ERROR (Status)) { + goto ReleaseQueue; + } + + // + // Additional steps for MMIO: align the queue appropriately, and set the + // size. If anything fails from here on, we must unmap the ring resources. + // + Status = Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status = Dev->VirtIo->SetQueueAlign (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + // + // step 4c -- Report GPFN (guest-physical frame number) of queue. + // + Status = Dev->VirtIo->SetQueueAddress ( + Dev->VirtIo, + &Ring->Ring, + RingBaseShift + ); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Ring->BufferCount = QueueSize; + Ring->BufferSize = BufferSize; + Ring->BufferPages = EFI_SIZE_TO_PAGES (Ring->BufferCount * Ring->BufferSize); + + Status = Dev->VirtIo->AllocateSharedPages (Dev->VirtIo, Ring->BufferPages, (VOID **)&Ring->Buffers); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status = VirtioMapAllBytesInSharedBuffer ( + Dev->VirtIo, + VirtioOperationBusMasterCommonBuffer, + Ring->Buffers, + EFI_PAGES_TO_SIZE (Ring->BufferPages), + &Ring->DeviceAddress, + &Ring->BufferMap + ); + if (EFI_ERROR (Status)) { + goto ReleasePages; + } + + VirtioPrepare (&Ring->Ring, &Ring->Indices); + Ring->Ready = TRUE; + + return EFI_SUCCESS; + +ReleasePages: + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + Ring->BufferPages, + Ring->Buffers + ); + Ring->Buffers = NULL; + +UnmapQueue: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->RingMap); + Ring->RingMap = NULL; + +ReleaseQueue: + VirtioRingUninit (Dev->VirtIo, &Ring->Ring); + +Failed: + return Status; +} + +// ----------------------------------------------------------------------------- +// Deinitialize ring buffer +VOID +EFIAPI +VirtioKeyboardUninitRing ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + + if (Ring->BufferMap) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->BufferMap); + Ring->BufferMap = NULL; + } + + if (Ring->Buffers) { + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + Ring->BufferPages, + Ring->Buffers + ); + Ring->Buffers = NULL; + } + + if (!Ring->RingMap) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->RingMap); + Ring->RingMap = NULL; + } + + if (Ring->Ring.Base) { + VirtioRingUninit (Dev->VirtIo, &Ring->Ring); + } + + ZeroMem (Ring, sizeof (*Ring)); +} + +// ----------------------------------------------------------------------------- +// Deinitialize all rings allocated in driver +STATIC +VOID +EFIAPI +VirtioKeyboardUninitAllRings ( + IN OUT VIRTIO_KBD_DEV *Dev + ) +{ + UINT16 Index; + + for (Index = 0; Index < KEYBOARD_MAX_RINGS; Index++) { + VirtioKeyboardUninitRing (Dev, Index); + } +} + +// ----------------------------------------------------------------------------- +// Mark all buffers as ready to write and push to device +VOID +EFIAPI +VirtioKeyboardRingFillRx ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_KBD_RING *Ring = Dev->Rings + Index; + UINT32 BufferNr; + + for (BufferNr = 0; BufferNr < Ring->BufferCount; BufferNr++) { + VirtioKeyboardRingSendBuffer (Dev, Index, NULL, Ring->BufferSize, FALSE); + } + + Dev->VirtIo->SetQueueNotify (Dev->VirtIo, Index); +} + +// Forward declaration of module Uninit function +STATIC +VOID +EFIAPI +VirtioKeyboardUninit ( + IN OUT VIRTIO_KBD_DEV *Dev + ); + +// Forward declaration of module Init function +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardInit ( + IN OUT VIRTIO_KBD_DEV *Dev + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSimpleTextInputReset ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + VIRTIO_KBD_DEV *Dev; + + Dev = VIRTIO_KEYBOARD_FROM_THIS (This); + VirtioKeyboardUninit (Dev); + VirtioKeyboardInit (Dev); + + return EFI_SUCCESS; +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSimpleTextInputReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ) +{ + VIRTIO_KBD_DEV *Dev; + EFI_TPL OldTpl; + + if (Key == NULL) { + return EFI_INVALID_PARAMETER; + } + + Dev = VIRTIO_KEYBOARD_FROM_THIS (This); + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + if (Dev->KeyReady) { + // Get last key from the buffer + *Key = Dev->LastKey; + + // Mark key as consumed + Dev->KeyReady = FALSE; + + gBS->RestoreTPL (OldTpl); + return EFI_SUCCESS; + } + + gBS->RestoreTPL (OldTpl); + + return EFI_NOT_READY; +} + +// ----------------------------------------------------------------------------- +// Function converting VirtIO key codes to UEFI key codes +STATIC +VOID +EFIAPI +VirtioKeyboardConvertKeyCode ( + IN OUT VIRTIO_KBD_DEV *Dev, + IN UINT16 Code, + OUT EFI_INPUT_KEY *Key + ) +{ + // Key mapping in between Linux and UEFI + // https://github.com/torvalds/linux/blob/master/include/uapi/linux/input-event-codes.h + // https://dox.ipxe.org/SimpleTextIn_8h_source.html#l00048 + // https://uefi.org/specs/UEFI/2.10/Apx_B_Console.html + + static const UINT16 Map[] = { + [KEY_1] = '1', '2', '3', '4', '5', '6', '7', '8', '9', '0', + [KEY_MINUS] = '-', '=', + [KEY_Q] = 'q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', + [KEY_LEFTBRACE] = '[', ']', + [KEY_A] = 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', + [KEY_SEMICOLON] = ';', '\'', '`', + [KEY_BACKSLASH] = '\\', + [KEY_Z] = 'z', 'x', 'c', 'v', 'b', 'n', 'm', + [KEY_COMMA] = ',', '.', '/', + [KEY_SPACE] = ' ', + [MAX_KEYBOARD_CODE] = 0x00 + }; + + static const UINT16 MapShift[] = { + [KEY_1] = '!', '@', '#', '$', '%', '^', '&', '*', '(', ')', + [KEY_MINUS] = '_', '+', + [KEY_Q] = 'Q', 'W', 'E', 'R', 'T', 'Y', 'U', 'I', 'O', 'P', + [KEY_LEFTBRACE] = '{', '}', + [KEY_A] = 'A', 'S', 'D', 'F', 'G', 'H', 'J', 'K', 'L', + [KEY_SEMICOLON] = ':', '\"', '~', + [KEY_BACKSLASH] = '|', + [KEY_Z] = 'Z', 'X', 'C', 'V', 'B', 'N', 'M', + [KEY_COMMA] = '<', '>', '?', + [KEY_SPACE] = ' ', + [MAX_KEYBOARD_CODE] = 0x00 + }; + + // Set default readings + Key->ScanCode = SCAN_NULL; + Key->UnicodeChar = CHAR_NULL; + + // Check if key code is not out of the keyboard mapping boundaries + if (Code >= MAX_KEYBOARD_CODE) { + DEBUG ((DEBUG_INFO, "%a: Key code out of range \n", __func__)); + return; + } + + // Handle F1 - F10 keys + if ((Code >= KEY_F1) && (Code <= KEY_F10)) { + Key->ScanCode = SCAN_F1 + (Code - KEY_F1); + return; + } + + switch (Code) { + case KEY_PAGEUP: + Key->ScanCode = SCAN_PAGE_UP; + break; + + case KEY_PAGEDOWN: + Key->ScanCode = SCAN_PAGE_DOWN; + break; + + case KEY_HOME: + Key->ScanCode = SCAN_HOME; + break; + + case KEY_END: + Key->ScanCode = SCAN_END; + break; + + case KEY_DELETE: + Key->ScanCode = SCAN_DELETE; + break; + + case KEY_INSERT: + Key->ScanCode = SCAN_INSERT; + break; + + case KEY_UP: + Key->ScanCode = SCAN_UP; + break; + + case KEY_LEFT: + Key->ScanCode = SCAN_LEFT; + break; + + case KEY_RIGHT: + Key->ScanCode = SCAN_RIGHT; + break; + + case KEY_DOWN: + Key->ScanCode = SCAN_DOWN; + break; + + case KEY_BACKSPACE: + Key->UnicodeChar = CHAR_BACKSPACE; + break; + + case KEY_TAB: + Key->UnicodeChar = CHAR_TAB; + break; + + case KEY_ENTER: + // Key->UnicodeChar = CHAR_LINEFEED; + Key->UnicodeChar = CHAR_CARRIAGE_RETURN; + break; + + case KEY_ESC: + Key->ScanCode = SCAN_ESC; + break; + + default: + if (Dev->KeyActive[KEY_LEFTSHIFT] || Dev->KeyActive[KEY_RIGHTSHIFT]) { + Key->ScanCode = MapShift[Code]; + Key->UnicodeChar = MapShift[Code]; + } else { + Key->ScanCode = Map[Code]; + Key->UnicodeChar = Map[Code]; + } + + if (Dev->KeyActive[KEY_LEFTCTRL] || Dev->KeyActive[KEY_RIGHTCTRL]) { + // Convert Ctrl+[a-z] and Ctrl+[A-Z] into [1-26] ASCII table entries + Key->UnicodeChar &= 0x1F; + } + + break; + } +} + +// ----------------------------------------------------------------------------- +// Main function processing virtio keyboard events +STATIC +VOID +EFIAPI +VirtioKeyboardGetDeviceData ( + IN OUT VIRTIO_KBD_DEV *Dev + ) +{ + BOOLEAN HasData; + UINT8 Data[KEYBOARD_RX_BUFSIZE + 1]; + UINT32 DataSize; + VIRTIO_KBD_EVENT Event; + EFI_TPL OldTpl; + + for ( ; ; ) { + HasData = VirtioKeyboardRingGetBuffer (Dev, 0, Data, &DataSize); + + // Exit if no new data + if (!HasData) { + return; + } + + if (DataSize < sizeof (Event)) { + continue; + } + + // Clearing last character is not needed as it will be overwritten anyway + // Dev->LastKey.ScanCode = SCAN_NULL; + // Dev->LastKey.UnicodeChar = CHAR_NULL; + + CopyMem (&Event, Data, sizeof (Event)); + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + switch (Event.Type) { + case EV_SYN: + // Sync event received + break; + + case EV_KEY: + // Key press event received + // DEBUG ((DEBUG_INFO, "%a: ---------------------- \nType: %x Code: %x Value: %x\n", + // __func__, Event.Type, Event.Code, Event.Value)); + + if (Event.Value == KEY_PRESSED) { + // Key pressed event received + Dev->KeyActive[(UINT8)Event.Code] = TRUE; + + // Evaluate key + VirtioKeyboardConvertKeyCode (Dev, Event.Code, &Dev->LastKey); + + // Flag that printable character is ready to be send + Dev->KeyReady = TRUE; + } else { + // Key released event received + Dev->KeyActive[(UINT8)Event.Code] = FALSE; + } + + break; + + default: + DEBUG ((DEBUG_INFO, "%a: Unhandled VirtIo event\n", __func__)); + break; + } + + gBS->RestoreTPL (OldTpl); + } +} + +// ----------------------------------------------------------------------------- +// Callback hook for timer interrupt +STATIC +VOID +EFIAPI +VirtioKeyboardTimer ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_KBD_DEV *Dev = Context; + + VirtioKeyboardGetDeviceData (Dev); +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +VOID +EFIAPI +VirtioKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_KBD_DEV *Dev = VIRTIO_KEYBOARD_FROM_THIS (Context); + + // + // Stall 1ms to give a chance to let other driver interrupt this routine + // for their timer event. + // e.g. UI setup or Shell, other drivers which are driven by timer event + // will have a bad performance during this period, + // e.g. usb keyboard driver. + // Add a stall period can greatly increate other driver performance during + // the WaitForKey is recursivly invoked. 1ms delay will make little impact + // to the thunk keyboard driver, and user can not feel the delay at all when + // input. + gBS->Stall (1000); + + // Use TimerEvent callback function to check whether there's any key pressed + VirtioKeyboardTimer (NULL, Dev); + + // If there is a new key ready - send signal + if (Dev->KeyReady) { + gBS->SignalEvent (Event); + } +} + +/// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ) +{ + VIRTIO_KBD_DEV *Dev; + EFI_STATUS Status; + EFI_TPL OldTpl; + + Dev = VIRTIO_KEYBOARD_EX_FROM_THIS (This); + + // Call the reset function from SIMPLE_TEXT_INPUT protocol + Status = Dev->Txt.Reset ( + &Dev->Txt, + ExtendedVerification + ); + + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ) +{ + VIRTIO_KBD_DEV *Dev; + EFI_STATUS Status; + EFI_INPUT_KEY Key; + EFI_KEY_STATE KeyState; + + if (KeyData == NULL) { + return EFI_INVALID_PARAMETER; + } + + Dev = VIRTIO_KEYBOARD_EX_FROM_THIS (This); + + // Get the last pressed key + Status = Dev->Txt.ReadKeyStroke (&Dev->Txt, &Key); + if (EFI_ERROR (Status)) { + return EFI_DEVICE_ERROR; + } + + // Add key state informations + KeyState.KeyShiftState = EFI_SHIFT_STATE_VALID; + KeyState.KeyToggleState = EFI_TOGGLE_STATE_VALID; + + // Shift key modifier + if (Dev->KeyActive[KEY_LEFTSHIFT]) { + KeyState.KeyShiftState |= EFI_LEFT_SHIFT_PRESSED; + } + if (Dev->KeyActive[KEY_RIGHTSHIFT]) { + KeyState.KeyShiftState |= EFI_RIGHT_SHIFT_PRESSED; + } + + // Ctrl key modifier + if (Dev->KeyActive[KEY_LEFTCTRL]) { + KeyState.KeyShiftState |= EFI_LEFT_CONTROL_PRESSED; + } + if (Dev->KeyActive[KEY_RIGHTCTRL]) { + KeyState.KeyShiftState |= EFI_RIGHT_CONTROL_PRESSED; + } + + // ALt key modifier + if (Dev->KeyActive[KEY_LEFTALT]) { + KeyState.KeyShiftState |= EFI_LEFT_ALT_PRESSED; + } + if (Dev->KeyActive[KEY_RIGHTALT]) { + KeyState.KeyShiftState |= EFI_RIGHT_ALT_PRESSED; + } + + // Return value only when there is no failure + KeyData->Key = Key; + KeyData->KeyState = KeyState; + + return EFI_SUCCESS; +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +VOID +EFIAPI +VirtioKeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_KBD_DEV *Dev; + + Dev = VIRTIO_KEYBOARD_EX_FROM_THIS (Context); + VirtioKeyboardWaitForKey (Event, &Dev->Txt); +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ) +{ + if (KeyToggleState == NULL) { + return EFI_INVALID_PARAMETER; + } + + return EFI_SUCCESS; +} + +BOOLEAN +IsKeyRegistered ( + IN EFI_KEY_DATA *RegsiteredData, + IN EFI_KEY_DATA *InputData + ) + +{ + ASSERT (RegsiteredData != NULL && InputData != NULL); + + if ((RegsiteredData->Key.ScanCode != InputData->Key.ScanCode) || + (RegsiteredData->Key.UnicodeChar != InputData->Key.UnicodeChar)) + { + return FALSE; + } + + // + // Assume KeyShiftState/KeyToggleState = 0 in Registered key data means + // these state could be ignored. + // + if ((RegsiteredData->KeyState.KeyShiftState != 0) && + (RegsiteredData->KeyState.KeyShiftState != InputData->KeyState.KeyShiftState)) + { + return FALSE; + } + + if ((RegsiteredData->KeyState.KeyToggleState != 0) && + (RegsiteredData->KeyState.KeyToggleState != InputData->KeyState.KeyToggleState)) + { + return FALSE; + } + + return TRUE; +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ) +{ + EFI_STATUS Status; + VIRTIO_KBD_DEV *Dev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + VIRTIO_KBD_IN_EX_NOTIFY *NewNotify; + VIRTIO_KBD_IN_EX_NOTIFY *CurrentNotify; + + if ((KeyData == NULL) || + (NotifyHandle == NULL) || + (KeyNotificationFunction == NULL)) + { + return EFI_INVALID_PARAMETER; + } + + Dev = VIRTIO_KEYBOARD_EX_FROM_THIS (This); + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + // Check if the (KeyData, NotificationFunction) pair is already registered. + for (Link = Dev->NotifyList.ForwardLink; + Link != &Dev->NotifyList; + Link = Link->ForwardLink) + { + CurrentNotify = CR ( + Link, + VIRTIO_KBD_IN_EX_NOTIFY, + NotifyEntry, + VIRTIO_KBD_SIG + ); + if (IsKeyRegistered (&CurrentNotify->KeyData, KeyData)) { + if (CurrentNotify->KeyNotificationFn == KeyNotificationFunction) { + *NotifyHandle = CurrentNotify; + Status = EFI_SUCCESS; + goto Exit; + } + } + } + + NewNotify = (VIRTIO_KBD_IN_EX_NOTIFY *)AllocateZeroPool (sizeof (VIRTIO_KBD_IN_EX_NOTIFY)); + if (NewNotify == NULL) { + Status = EFI_OUT_OF_RESOURCES; + goto Exit; + } + + NewNotify->Signature = VIRTIO_KBD_SIG; + NewNotify->KeyNotificationFn = KeyNotificationFunction; + CopyMem (&NewNotify->KeyData, KeyData, sizeof (EFI_KEY_DATA)); + InsertTailList (&Dev->NotifyList, &NewNotify->NotifyEntry); + + *NotifyHandle = NewNotify; + Status = EFI_SUCCESS; + +Exit: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ) +{ + EFI_STATUS Status; + VIRTIO_KBD_DEV *Dev; + EFI_TPL OldTpl; + LIST_ENTRY *Link; + VIRTIO_KBD_IN_EX_NOTIFY *CurrentNotify; + + if (NotificationHandle == NULL) { + return EFI_INVALID_PARAMETER; + } + + if (((VIRTIO_KBD_IN_EX_NOTIFY *)NotificationHandle)->Signature != VIRTIO_KBD_SIG) { + return EFI_INVALID_PARAMETER; + } + + Dev = VIRTIO_KEYBOARD_EX_FROM_THIS (This); + + OldTpl = gBS->RaiseTPL (TPL_NOTIFY); + + for (Link = Dev->NotifyList.ForwardLink; + Link != &Dev->NotifyList; + Link = Link->ForwardLink) + { + CurrentNotify = CR ( + Link, + VIRTIO_KBD_IN_EX_NOTIFY, + NotifyEntry, + VIRTIO_KBD_SIG + ); + if (CurrentNotify == NotificationHandle) { + RemoveEntryList (&CurrentNotify->NotifyEntry); + + Status = EFI_SUCCESS; + goto Exit; + } + } + + // Notification has not been found + Status = EFI_INVALID_PARAMETER; + +Exit: + gBS->RestoreTPL (OldTpl); + + return Status; +} + +// ----------------------------------------------------------------------------- +// Driver init +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardInit ( + IN OUT VIRTIO_KBD_DEV *Dev + ) +{ + UINT8 NextDevStat; + EFI_STATUS Status; + UINT64 Features; + + // + // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. + // + NextDevStat = 0; // step 1 -- reset device + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |= VSTAT_ACK; // step 2 -- acknowledge device presence + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |= VSTAT_DRIVER; // step 3 -- we know how to drive it + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status = Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // step 4a -- retrieve and validate features + // + Status = Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM; + + // + // In virtio-1.0, feature negotiation is expected to complete before queue + // discovery, and the device can also reject the selected set of features. + // + if (Dev->VirtIo->Revision >= VIRTIO_SPEC_REVISION (1, 0, 0)) { + Status = Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + Status = VirtioKeyboardInitRing (Dev, 0, KEYBOARD_RX_BUFSIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // step 5 -- Report understood features and guest-tuneables. + // + if (Dev->VirtIo->Revision < VIRTIO_SPEC_REVISION (1, 0, 0)) { + Features &= ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM); + Status = Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + // + // step 6 -- initialization complete + // + NextDevStat |= VSTAT_DRIVER_OK; + Status = Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // populate the exported interface's attributes + // + + // struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { + // EFI_INPUT_RESET Reset; + // EFI_INPUT_READ_KEY ReadKeyStroke; + // EFI_EVENT WaitForKey; + // }; + Dev->Txt.Reset = (EFI_INPUT_RESET)VirtioKeyboardSimpleTextInputReset; + Dev->Txt.ReadKeyStroke = VirtioKeyboardSimpleTextInputReadKeyStroke; + Dev->Txt.WaitForKey = VirtioKeyboardWaitForKey; + + // struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL { + // EFI_INPUT_RESET_EX Reset; + // EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + // EFI_EVENT WaitForKeyEx; + // EFI_SET_STATE SetState; + // EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + // EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; + // } + Dev->TxtEx.Reset = (EFI_INPUT_RESET_EX)VirtioKeyboardResetEx; + Dev->TxtEx.ReadKeyStrokeEx = VirtioKeyboardReadKeyStrokeEx; + Dev->TxtEx.SetState = VirtioKeyboardSetState; + Dev->TxtEx.RegisterKeyNotify = VirtioKeyboardRegisterKeyNotify; + Dev->TxtEx.UnregisterKeyNotify = VirtioKeyboardUnregisterKeyNotify; + InitializeListHead (&Dev->NotifyList); + + // + // Setup the WaitForKey event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + VirtioKeyboardWaitForKey, + &(Dev->Txt), + &((Dev->Txt).WaitForKey) + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Setup the WaitForKeyEx event + // + Status = gBS->CreateEvent ( + EVT_NOTIFY_WAIT, + TPL_NOTIFY, + VirtioKeyboardWaitForKeyEx, + &(Dev->TxtEx), + &((Dev->TxtEx).WaitForKeyEx) + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + VirtioKeyboardRingFillRx (Dev, 0); + + // + // Event for reading key in time intervals + // + Status = gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + VirtioKeyboardTimer, + Dev, + &Dev->KeyReadTimer + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status = gBS->SetTimer ( + Dev->KeyReadTimer, + TimerPeriodic, + EFI_TIMER_PERIOD_MILLISECONDS (KEYBOARD_PROBE_TIME_MS) + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + return EFI_SUCCESS; + +Failed: + VirtioKeyboardUninitAllRings (Dev); + // VirtualKeyboardFreeNotifyList (&VirtualKeyboardPrivate->NotifyList); + + // + // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Device + // Status. VirtIo access failure here should not mask the original error. + // + NextDevStat |= VSTAT_FAILED; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + + return Status; // reached only via Failed above +} + +// ----------------------------------------------------------------------------- +// Deinitialize driver +STATIC +VOID +EFIAPI +VirtioKeyboardUninit ( + IN OUT VIRTIO_KBD_DEV *Dev + ) +{ + gBS->CloseEvent (Dev->KeyReadTimer); + // + // Reset the virtual device -- see virtio-0.9.5, 2.2.2.1 Device Status. When + // VIRTIO_CFG_WRITE() returns, the host will have learned to stay away from + // the old comms area. + // + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); + + VirtioKeyboardUninitAllRings (Dev); +} + +// ----------------------------------------------------------------------------- +// Handle device exit before switch to boot +STATIC +VOID +EFIAPI +VirtioKeyboardExitBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_KBD_DEV *Dev; + + DEBUG ((DEBUG_INFO, "%a: Context=0x%p\n", __func__, Context)); + // + // Reset the device. This causes the hypervisor to forget about the virtio + // ring. + // + // We allocated said ring in EfiBootServicesData type memory, and code + // executing after ExitBootServices() is permitted to overwrite it. + // + Dev = Context; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); +} + +// ----------------------------------------------------------------------------- +// Binding validation function +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardBindingSupported ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + EFI_STATUS Status; + VIRTIO_DEVICE_PROTOCOL *VirtIo; + + // + // Attempt to open the device with the VirtIo set of interfaces. On success, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate + // open attempts (EFI_ALREADY_STARTED). + // + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // ControllerHandle, according to + // the UEFI Driver Model + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo access to + // the device; to be released + ); + if (EFI_ERROR (Status)) { + if (Status != EFI_UNSUPPORTED) { + DEBUG ((DEBUG_INFO, "%a:%d: %r\n", __func__, __LINE__, Status)); + } + + return Status; + } + + DEBUG ((DEBUG_INFO, "%a:%d: 0x%x\n", __func__, __LINE__, VirtIo->SubSystemDeviceId)); + if (VirtIo->SubSystemDeviceId != VIRTIO_SUBSYSTEM_INPUT) { + Status = EFI_UNSUPPORTED; + } + + // + // We needed VirtIo access only transitorily, to see whether we support the + // device or not. + // + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + return Status; +} + +// ----------------------------------------------------------------------------- +// Driver binding function API +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + VIRTIO_KBD_DEV *Dev; + EFI_STATUS Status; + + Dev = (VIRTIO_KBD_DEV *)AllocateZeroPool (sizeof *Dev); + if (Dev == NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status = gBS->OpenProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, + This->DriverBindingHandle, + DeviceHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto FreeVirtioKbd; + } + + // + // VirtIo access granted, configure virtio keyboard device. + // + Status = VirtioKeyboardInit (Dev); + if (EFI_ERROR (Status)) { + goto CloseVirtIo; + } + + Status = gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + &VirtioKeyboardExitBoot, + Dev, + &Dev->ExitBoot + ); + if (EFI_ERROR (Status)) { + goto UninitDev; + } + + // + // Setup complete, attempt to export the driver instance's EFI_SIMPLE_TEXT_INPUT_PROTOCOL + // interface. + // + Dev->Signature = VIRTIO_KBD_SIG; + Status = gBS->InstallMultipleProtocolInterfaces ( + &DeviceHandle, + &gEfiSimpleTextInProtocolGuid, + &Dev->Txt, + &gEfiSimpleTextInputExProtocolGuid, + &Dev->TxtEx, + NULL + ); + if (EFI_ERROR (Status)) { + goto CloseExitBoot; + } + + return EFI_SUCCESS; + +CloseExitBoot: + gBS->CloseEvent (Dev->ExitBoot); + +UninitDev: + VirtioKeyboardUninit (Dev); + +CloseVirtIo: + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + +FreeVirtioKbd: + FreePool (Dev); + + return Status; +} + +// ----------------------------------------------------------------------------- +// Driver unbinding function API +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + EFI_STATUS Status; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL *Txt; + VIRTIO_KBD_DEV *Dev; + + Status = gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gEfiSimpleTextInProtocolGuid, // retrieve the RNG iface + (VOID **)&Txt, // target pointer + This->DriverBindingHandle, // requestor driver ident. + DeviceHandle, // lookup req. for dev. + EFI_OPEN_PROTOCOL_GET_PROTOCOL // lookup only, no new ref. + ); + if (EFI_ERROR (Status)) { + return Status; + } + + Dev = VIRTIO_KEYBOARD_FROM_THIS (Txt); + + // + // Handle Stop() requests for in-use driver instances gracefully. + // + Status = gBS->UninstallMultipleProtocolInterfaces ( + &DeviceHandle, + &gEfiSimpleTextInProtocolGuid, + &Dev->Txt, + &gEfiSimpleTextInputExProtocolGuid, + &Dev->TxtEx, + NULL + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gBS->CloseEvent (Dev->ExitBoot); + + VirtioKeyboardUninit (Dev); + + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + + FreePool (Dev); + + return EFI_SUCCESS; +} + +// ----------------------------------------------------------------------------- +// Forward declaration of global variable +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName; + +// ----------------------------------------------------------------------------- +// Driver name to be displayed +STATIC +EFI_UNICODE_STRING_TABLE mDriverNameTable[] = { + { "eng;en", L"Virtio Keyboard Driver" }, + { NULL, NULL } +}; + +// ----------------------------------------------------------------------------- +// Driver name lookup function +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDriverNameTable, + DriverName, + (BOOLEAN)(This == &gComponentName) // Iso639Language + ); +} + +// ----------------------------------------------------------------------------- +// Device name to be displayed +STATIC +EFI_UNICODE_STRING_TABLE mDeviceNameTable[] = { + { "eng;en", L"RHEL virtio virtual keyboard BOB (Basic Operation Board)" }, + { NULL, NULL } +}; + +// ----------------------------------------------------------------------------- +STATIC +EFI_COMPONENT_NAME_PROTOCOL gDeviceName; + +// ----------------------------------------------------------------------------- +STATIC +EFI_STATUS +EFIAPI +VirtioKeyboardGetDeviceName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDeviceNameTable, + ControllerName, + (BOOLEAN)(This == &gDeviceName) // Iso639Language + ); +} + +// ----------------------------------------------------------------------------- +// General driver UEFI interface for showing driver name +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName = { + &VirtioKeyboardGetDriverName, + &VirtioKeyboardGetDeviceName, + "eng" // SupportedLanguages, ISO 639-2 language codes +}; + +// ----------------------------------------------------------------------------- +// General driver UEFI interface for showing driver name +STATIC +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 = { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioKeyboardGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioKeyboardGetDeviceName, + "en" // SupportedLanguages, RFC 4646 language codes +}; + +// ----------------------------------------------------------------------------- +// General driver UEFI interface for loading / unloading driver +STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding = { + &VirtioKeyboardBindingSupported, + &VirtioKeyboardBindingStart, + &VirtioKeyboardBindingStop, + 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed drivers + NULL, // ImageHandle, to be overwritten by + // EfiLibInstallDriverBindingComponentName2() in VirtioKeyboardEntryPoint() + NULL // DriverBindingHandle, ditto +}; + +// ----------------------------------------------------------------------------- +// Driver entry point set in INF file, registers all driver functions into UEFI +EFI_STATUS +EFIAPI +VirtioKeyboardEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + DEBUG ((DEBUG_INFO, "Virtio keyboard has been loaded.......................\n")); + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); +} diff --git a/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.h b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.h new file mode 100644 index 000000000000..d4cbde97fd66 --- /dev/null +++ b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.h @@ -0,0 +1,209 @@ +/** @file + + Private definitions of the VirtioKeyboard driver + + Copyright (C) 2024, Red Hat + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIO_KEYBOARD_DXE_H_ +#define _VIRTIO_KEYBOARD_DXE_H_ + +#include +#include +#include +#include + +#include + +#define VIRTIO_KBD_SIG SIGNATURE_32 ('V', 'K', 'B', 'D') + +#define KEYBOARD_MAX_RINGS 2 +#define KEYBOARD_RX_BUFSIZE 64 + +// Fetch new key from VirtIO every 50ms +#define KEYBOARD_PROBE_TIME_MS 50 + +// Max range of recognized keyboard codes +#define MAX_KEYBOARD_CODE 255 + +typedef struct { + UINTN Signature; + EFI_KEY_DATA KeyData; + EFI_KEY_NOTIFY_FUNCTION KeyNotificationFn; + LIST_ENTRY NotifyEntry; +} VIRTIO_KBD_IN_EX_NOTIFY; + +// Data structure representing payload delivered from VirtIo +typedef struct { + UINT16 Type; + UINT16 Code; + UINT32 Value; +} VIRTIO_KBD_EVENT; + +// Data structure representing ring buffer +typedef struct { + VRING Ring; + VOID *RingMap; + DESC_INDICES Indices; /* Avail Ring */ + UINT16 LastUsedIdx; /* Used Ring */ + + UINT32 BufferSize; + UINT32 BufferCount; + UINT32 BufferPages; + UINT8 *Buffers; + VOID *BufferMap; + EFI_PHYSICAL_ADDRESS DeviceAddress; + + BOOLEAN Ready; +} VIRTIO_KBD_RING; + +// Declaration of data structure representing driver context +typedef struct { + // Device signature + UINT32 Signature; + + // Hook for the function which shall be caled when driver is closed + // before system state changes to boot + EFI_EVENT ExitBoot; + + // Hooks for functions required by UEFI keyboard API + // struct _EFI_SIMPLE_TEXT_INPUT_PROTOCOL { + // EFI_INPUT_RESET Reset; + // EFI_INPUT_READ_KEY ReadKeyStroke; + // EFI_EVENT WaitForKey; + // }; + EFI_SIMPLE_TEXT_INPUT_PROTOCOL Txt; + + // struct _EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL { + // EFI_INPUT_RESET_EX Reset; + // EFI_INPUT_READ_KEY_EX ReadKeyStrokeEx; + // EFI_EVENT WaitForKeyEx; + // EFI_SET_STATE SetState; + // EFI_REGISTER_KEYSTROKE_NOTIFY RegisterKeyNotify; + // EFI_UNREGISTER_KEYSTROKE_NOTIFY UnregisterKeyNotify; + // } + EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL TxtEx; + + // Virtio device hook + VIRTIO_DEVICE_PROTOCOL *VirtIo; + + // Hook for ring buffer + VIRTIO_KBD_RING Rings[KEYBOARD_MAX_RINGS]; + + // Timer event for checking key presses from VirtIo + EFI_EVENT KeyReadTimer; + + // List for notifications + LIST_ENTRY NotifyList; + EFI_EVENT KeyNotifyTimer; + + // Last pressed key + // typedef struct { + // UINT16 ScanCode; + // CHAR16 UnicodeChar; + // } EFI_INPUT_KEY; + EFI_INPUT_KEY LastKey; + + // Key modifiers + BOOLEAN KeyActive[MAX_KEYBOARD_CODE]; + + // If key is ready + BOOLEAN KeyReady; +} VIRTIO_KBD_DEV; + +// Helper functions to extract VIRTIO_KBD_DEV structure pointers +#define VIRTIO_KEYBOARD_FROM_THIS(KbrPointer) \ + CR (KbrPointer, VIRTIO_KBD_DEV, Txt, VIRTIO_KBD_SIG) +#define VIRTIO_KEYBOARD_EX_FROM_THIS(KbrPointer) \ + CR (KbrPointer, VIRTIO_KBD_DEV, TxtEx, VIRTIO_KBD_SIG) + +// Bellow candidates to be included as Linux header +#define KEY_PRESSED 1 + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSimpleTextInputReset ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSimpleTextInputReadKeyStroke ( + IN EFI_SIMPLE_TEXT_INPUT_PROTOCOL *This, + OUT EFI_INPUT_KEY *Key + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_PROTOCOL API +VOID +EFIAPI +VirtioKeyboardWaitForKey ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardResetEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN BOOLEAN ExtendedVerification + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardReadKeyStrokeEx ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + OUT EFI_KEY_DATA *KeyData + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +VOID +EFIAPI +VirtioKeyboardWaitForKeyEx ( + IN EFI_EVENT Event, + IN VOID *Context + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardSetState ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_TOGGLE_STATE *KeyToggleState + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardRegisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN EFI_KEY_DATA *KeyData, + IN EFI_KEY_NOTIFY_FUNCTION KeyNotificationFunction, + OUT VOID **NotifyHandle + ); + +// ----------------------------------------------------------------------------- +// EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL API +EFI_STATUS +EFIAPI +VirtioKeyboardUnregisterKeyNotify ( + IN EFI_SIMPLE_TEXT_INPUT_EX_PROTOCOL *This, + IN VOID *NotificationHandle + ); + +#endif diff --git a/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf new file mode 100644 index 000000000000..6c35f2a4cef6 --- /dev/null +++ b/OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf @@ -0,0 +1,41 @@ +## @file +# This driver produces EFI_SIMPLE_TEXT_INPUT_PROTOCOL for virt ARM devices. +# +# Copyright (C) 2024, Red Hat +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION = 1.29 + BASE_NAME = VirtioKeyboardDxe + FILE_GUID = F141B1E5-9C7C-44CC-AFAA-E87D7689B113 + MODULE_TYPE = UEFI_DRIVER + VERSION_STRING = 1.0 + ENTRY_POINT = VirtioKeyboardEntryPoint + +[Sources] + VirtioKeyboard.c + VirtioKeyboard.h + VirtioKeyCodes.h + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + VirtioLib + +# Protocols used by this driver +[Protocols] + #gEfiDriverBindingProtocolGuid + gEfiSimpleTextInProtocolGuid + gEfiSimpleTextInputExProtocolGuid + gVirtioDeviceProtocolGuid From 403c6ccd6f23ffcc4daf5e97aa5b1144559d4e54 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Thu, 19 Dec 2024 01:32:55 +0100 Subject: [PATCH 3/5] ArmVirtPkg: Enable virtio keyboard driver for ARM OVMF platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Poławski --- ArmVirtPkg/ArmVirtQemu.dsc | 1 + 1 file changed, 1 insertion(+) diff --git a/ArmVirtPkg/ArmVirtQemu.dsc b/ArmVirtPkg/ArmVirtQemu.dsc index befefd7d0310..0bd8d85cab03 100644 --- a/ArmVirtPkg/ArmVirtQemu.dsc +++ b/ArmVirtPkg/ArmVirtQemu.dsc @@ -457,6 +457,7 @@ OvmfPkg/VirtioNetDxe/VirtioNet.inf OvmfPkg/VirtioRngDxe/VirtioRng.inf OvmfPkg/VirtioSerialDxe/VirtioSerial.inf + OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf # # FAT filesystem + GPT/MBR partitioning + UDF filesystem + virtio-fs From 3d54da21c463e593431069ed5bfe250ed2e05001 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Thu, 19 Dec 2024 01:33:43 +0100 Subject: [PATCH 4/5] OvmfPkg: Enable virtio keyboard driver for X64 OVMF platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Poławski --- OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/OvmfPkgX64.fdf | 1 + 2 files changed, 2 insertions(+) diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 1305dab60da7..8678e62c22b0 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -875,6 +875,7 @@ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioSerialDxe/VirtioSerial.inf + OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf !if $(PVSCSI_ENABLE) == TRUE OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 9405cd732762..2602c3d2febb 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -268,6 +268,7 @@ INF OvmfPkg/Virtio10Dxe/Virtio10.inf INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf +INF OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf !if $(PVSCSI_ENABLE) == TRUE INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif From 4ac96f9f5afe3080c3127710392804bc4e5048d8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Pawe=C5=82=20Po=C5=82awski?= Date: Thu, 19 Dec 2024 01:34:20 +0100 Subject: [PATCH 5/5] OvmfPkg: Enable virtio keyboard driver for Ia32x64 OVMF platform MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Paweł Poławski --- OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.fdf | 1 + 2 files changed, 2 insertions(+) diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index e80522f124cc..5fdf73e29ee6 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -801,6 +801,7 @@ OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioSerialDxe/VirtioSerial.inf + OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf !if $(PVSCSI_ENABLE) == TRUE OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index 98c05e491dee..605d9cd47afa 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -234,6 +234,7 @@ INF OvmfPkg/Virtio10Dxe/Virtio10.inf INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf +INF OvmfPkg/VirtioKeyboardDxe/VirtioKeyboard.inf !if $(PVSCSI_ENABLE) == TRUE INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif