From nobody Fri May 17 16:21:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+103991+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103991+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1683205928; cv=none; d=zohomail.com; s=zohoarc; b=D9nZ/sGrRTOMYCcYdfpX3Zm5rEHKyTsr0fTz/sq/9nlfOFe25fqF+AFc/7pOHDekilyh/1r9NxCcsHRCNyw9764EXjFCwWtOseOGJzSj0iqeywNGSh/i1LyOyDx3KQe8TrRWik3HnRCZpTU6EdBGWG0oHV/PxChvbEQd0ZfLAjY= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1683205928; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=FTZU1ESeyIrUvhf0kUa9PsLu5Eb9sCjvkm+PfNB8Io4=; b=PwyoGhNqf4nBJiMBqN7xPbhx/rQT6wRyV8cmSSBFt1eQKfC1NkDID/tjjyN/MNwY4LkkWG77UNfLoc1Fspm/DKn3ugkYE9Zf0vBaUYe9czMzB1cZWQUGvg5xpP98f6/s/JPdmF2lPKp8BUDMkaE4xALgerCZadoNglPMtrDMIbM= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103991+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1683205928964300.17046530023333; Thu, 4 May 2023 06:12:08 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id VMbCYY1788612x9NLIXM6XV8; Thu, 04 May 2023 06:12:08 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.groups.io with SMTP id smtpd.web10.49476.1683205927554591568 for ; Thu, 04 May 2023 06:12:07 -0700 X-Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-241-2lBB16yLPHWppZOy-22ohQ-1; Thu, 04 May 2023 09:12:03 -0400 X-MC-Unique: 2lBB16yLPHWppZOy-22ohQ-1 X-Received: from smtp.corp.redhat.com (int-mx09.intmail.prod.int.rdu2.redhat.com [10.11.54.9]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 01BC285A588; Thu, 4 May 2023 13:12:03 +0000 (UTC) X-Received: from sirius.home.kraxel.org (unknown [10.39.192.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id AF99F492C1B; Thu, 4 May 2023 13:12:02 +0000 (UTC) X-Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 25C1D180092D; Thu, 4 May 2023 15:12:01 +0200 (CEST) From: "Gerd Hoffmann" To: devel@edk2.groups.io Cc: Oliver Steffen , Stefan Berger , Anthony Perard , Jiewen Yao , Julien Grall , Pawel Polawski , Jordan Justen , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 1/4] OvmfPkg: add IndustryStandard/VirtioSerial.h Date: Thu, 4 May 2023 15:11:58 +0200 Message-Id: <20230504131201.1026585-2-kraxel@redhat.com> In-Reply-To: <20230504131201.1026585-1-kraxel@redhat.com> References: <20230504131201.1026585-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.9 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,kraxel@redhat.com X-Gm-Message-State: bMUTOgkopMhEpGJGvx7YgXoGx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1683205928; bh=fHcsu9IooSmoT2T0Mlwm3FKNoj3Gg5XjYJ1JLmmcMOg=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=sFROIFR1lGR/AiRCUZay4l/p/ZlKUE4B0QOIUbWdXf0hUJf0rYwSEw7jAOQy909qErj uP44Q3R6j9RP7sGoLTvZehc5JmCS/SFizPV/ViDDQGAo2X73tSy7feQjzahMnD42Ku1vh i4qk9hgzK3FBEv03fHQ3EGdPfc8jd+S5AR0= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1683205929247100002 Content-Type: text/plain; charset="utf-8"; x-default="true" Add header files with structs and defines for the virtio serial device. The virtio serial device also known as virtio console device because initially it had only support for a single tty, intended to be used as console. Support for multiple streams and named data ports has been added later on. https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.html#x= 1-2900003 Signed-off-by: Gerd Hoffmann --- .../Include/IndustryStandard/VirtioSerial.h | 64 +++++++++++++++++++ 1 file changed, 64 insertions(+) create mode 100644 OvmfPkg/Include/IndustryStandard/VirtioSerial.h diff --git a/OvmfPkg/Include/IndustryStandard/VirtioSerial.h b/OvmfPkg/Incl= ude/IndustryStandard/VirtioSerial.h new file mode 100644 index 000000000000..ffc8f84d03cc --- /dev/null +++ b/OvmfPkg/Include/IndustryStandard/VirtioSerial.h @@ -0,0 +1,64 @@ +/** @file + Virtio Serial Device specific type and macro definitions. + + Copyright (C) 2013-2016, Red Hat, Inc. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIO_SERIAL_H_ +#define _VIRTIO_SERIAL_H_ + +#include +#include + +// +// Device Configuration +// +typedef struct { + UINT16 Cols; + UINT16 Rows; + UINT32 MaxPorts; + UINT32 EmergWrite; +} VIRTIO_SERIAL_CONFIG; + +// +// Control Queue +// +typedef struct { + UINT32 Id; + UINT16 Event; + UINT16 Value; +} VIRTIO_SERIAL_CONTROL; + +// +// Queue Identifiers +// +#define VIRTIO_SERIAL_Q_RX_PORT0 0 +#define VIRTIO_SERIAL_Q_TX_PORT0 1 +#define VIRTIO_SERIAL_Q_RX_CTRL 2 +#define VIRTIO_SERIAL_Q_TX_CTRL 3 +#define VIRTIO_SERIAL_Q_RX_BASE 4 +#define VIRTIO_SERIAL_Q_TX_BASE 5 + +// +// Feature Bits +// +#define VIRTIO_SERIAL_F_SIZE BIT0 +#define VIRTIO_SERIAL_F_MULTIPORT BIT1 +#define VIRTIO_SERIAL_F_EMERG_WRITE BIT2 + +// +// Events +// +#define VIRTIO_SERIAL_DEVICE_READY 0 +#define VIRTIO_SERIAL_DEVICE_ADD 1 +#define VIRTIO_SERIAL_DEVICE_REMOVE 2 +#define VIRTIO_SERIAL_PORT_READY 3 +#define VIRTIO_SERIAL_CONSOLE_PORT 4 +#define VIRTIO_SERIAL_RESIZE 5 +#define VIRTIO_SERIAL_PORT_OPEN 6 +#define VIRTIO_SERIAL_PORT_NAME 7 + +#endif /* _VIRTIO_SERIAL_H_ */ --=20 2.40.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103991): https://edk2.groups.io/g/devel/message/103991 Mute This Topic: https://groups.io/mt/98683331/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri May 17 16:21:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+103993+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103993+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1683205931; cv=none; d=zohomail.com; s=zohoarc; b=YjGSXOinSUyf9WOK6WiW8p4NGK7/fsHeZp/rUtOvQ9X626UnneZMLP0gX+mJCAk3gooFDE47EkRvx52T6eNgN3lsQLxjAcgIFM2psQaccOzoWKWC/HgvEUSBZkbmx5ltnXmDcbxMxX0fCzHfC/mOItd0DmqoROmdyI7wcuq+qaE= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1683205931; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=cy2AAptxtRbLvrBUxLolcd5KM3+5Eyb8kuDbUBzEBus=; b=Uipsh1/df+po7mfwInTzE3MabPuR+SbmxrjWoz5kOqPI9PW2Ml6No1taZawbhb68FhI344AJJHBKkhDzCRoxdeLeizmp9BHBQxLh+aJkaZyyPSLFgdxBH29kpxuNU0lDfNgYuVa7Smz9oU57d0d2Ea9C4uK4swb4Q2sAXT6Hmuo= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103993+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 168320593193830.763699399575444; Thu, 4 May 2023 06:12:11 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id nLVEYY1788612xSLJzzAF3Ed; Thu, 04 May 2023 06:12:11 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.groups.io with SMTP id smtpd.web10.49478.1683205930789476275 for ; Thu, 04 May 2023 06:12:11 -0700 X-Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-31-_VAC1ZnJMvmuQSSIoMvstg-1; Thu, 04 May 2023 09:12:05 -0400 X-MC-Unique: _VAC1ZnJMvmuQSSIoMvstg-1 X-Received: from smtp.corp.redhat.com (int-mx02.intmail.prod.int.rdu2.redhat.com [10.11.54.2]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id 4CA0B800047; Thu, 4 May 2023 13:12:05 +0000 (UTC) X-Received: from sirius.home.kraxel.org (unknown [10.39.192.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 82CF14020960; Thu, 4 May 2023 13:12:04 +0000 (UTC) X-Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 2AF311800931; Thu, 4 May 2023 15:12:01 +0200 (CEST) From: "Gerd Hoffmann" To: devel@edk2.groups.io Cc: Oliver Steffen , Stefan Berger , Anthony Perard , Jiewen Yao , Julien Grall , Pawel Polawski , Jordan Justen , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 2/4] OvmfPkg/VirtioSerialDxe: add driver Date: Thu, 4 May 2023 15:11:59 +0200 Message-Id: <20230504131201.1026585-3-kraxel@redhat.com> In-Reply-To: <20230504131201.1026585-1-kraxel@redhat.com> References: <20230504131201.1026585-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.2 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,kraxel@redhat.com X-Gm-Message-State: U6HCg5ZxnebObuiesiCn9xBex1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1683205931; bh=3oFy1WqVNcU7BKmygJOyBsVC9VWlSLqudVdKs2Qa+zc=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=wNdlol4AOw59I3N39asLI+b3Wuhe7Ewd1y1e7vsWkTKmswkJSlH9GV6gnClyT1uO/EV dLDahp6UaDJaIUmMmgkRjEz3R0rA3nkuS4Gg+AIjRmQe0O7V+Spw0JW59YIEFrfHsqURm qU3H8FGhVEz13iVfzou7P3pnSZXPFOfvegI= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1683205932431100009 Content-Type: text/plain; charset="utf-8"; x-default="true" Add a driver for the virtio serial device. The virtio serial device also known as virtio console device because initially it had only support for a single tty, intended to be used as console. Support for multiple streams and named data ports has been added later on. The driver supports tty ports only, they are registered as SerialIo UART in the system. Named ports are detected and logged, but not exposed as devices. They are usually used by guest agents to communicate with the host. It's not clear whenever it makes sense for the firmware to run such agents and if so which efi protocol could be to expose the ports. So leaving that for another day. Signed-off-by: Gerd Hoffmann --- OvmfPkg/VirtioSerialDxe/VirtioSerial.inf | 40 + OvmfPkg/VirtioSerialDxe/VirtioSerial.h | 226 ++++++ OvmfPkg/VirtioSerialDxe/VirtioSerial.c | 808 +++++++++++++++++++++ OvmfPkg/VirtioSerialDxe/VirtioSerialPort.c | 465 ++++++++++++ OvmfPkg/VirtioSerialDxe/VirtioSerialRing.c | 345 +++++++++ 5 files changed, 1884 insertions(+) create mode 100644 OvmfPkg/VirtioSerialDxe/VirtioSerial.inf create mode 100644 OvmfPkg/VirtioSerialDxe/VirtioSerial.h create mode 100644 OvmfPkg/VirtioSerialDxe/VirtioSerial.c create mode 100644 OvmfPkg/VirtioSerialDxe/VirtioSerialPort.c create mode 100644 OvmfPkg/VirtioSerialDxe/VirtioSerialRing.c diff --git a/OvmfPkg/VirtioSerialDxe/VirtioSerial.inf b/OvmfPkg/VirtioSeria= lDxe/VirtioSerial.inf new file mode 100644 index 000000000000..d63a08b928c0 --- /dev/null +++ b/OvmfPkg/VirtioSerialDxe/VirtioSerial.inf @@ -0,0 +1,40 @@ +## @file +# This driver produces FIXME instances for virtio-serial devices. +# +# Copyright (C) 2016, Linaro Ltd. +# +# SPDX-License-Identifier: BSD-2-Clause-Patent +# +## + +[Defines] + INF_VERSION =3D 0x00010005 + BASE_NAME =3D VirtioSerialDxe + FILE_GUID =3D 23CACE14-EBA4-49F6-9681-C697FF0B649E + MODULE_TYPE =3D UEFI_DRIVER + VERSION_STRING =3D 1.0 + ENTRY_POINT =3D VirtioSerialEntryPoint + +[Sources] + VirtioSerial.h + VirtioSerial.c + VirtioSerialPort.c + VirtioSerialRing.c + +[Packages] + MdePkg/MdePkg.dec + OvmfPkg/OvmfPkg.dec + +[LibraryClasses] + BaseMemoryLib + DebugLib + DevicePathLib + MemoryAllocationLib + UefiBootServicesTableLib + UefiDriverEntryPoint + UefiLib + VirtioLib + +[Protocols] + gVirtioDeviceProtocolGuid ## TO_START + gEfiSerialIoProtocolGuid diff --git a/OvmfPkg/VirtioSerialDxe/VirtioSerial.h b/OvmfPkg/VirtioSerialD= xe/VirtioSerial.h new file mode 100644 index 000000000000..e626fdf43095 --- /dev/null +++ b/OvmfPkg/VirtioSerialDxe/VirtioSerial.h @@ -0,0 +1,226 @@ +/** @file + + Private definitions of the VirtioRng RNG driver + + Copyright (C) 2016, Linaro Ltd. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#ifndef _VIRTIO_SERIAL_DXE_H_ +#define _VIRTIO_SERIAL_DXE_H_ + +#include +#include +#include + +#include +#include + +#define VIRTIO_SERIAL_SIG SIGNATURE_32 ('V', 'S', 'I', 'O') + +#define MAX_PORTS 8 +#define MAX_RINGS (MAX_PORTS * 2 + 2) + +#define CTRL_RX_BUFSIZE 128 +#define CTRL_TX_BUFSIZE sizeof(VIRTIO_SERIAL_CONTROL) +#define PORT_RX_BUFSIZE 128 +#define PORT_TX_BUFSIZE 128 + +// +// Data structures +// + +typedef struct _VIRTIO_SERIAL_DEV VIRTIO_SERIAL_DEV; +typedef struct _VIRTIO_SERIAL_RING VIRTIO_SERIAL_RING; +typedef struct _VIRTIO_SERIAL_PORT VIRTIO_SERIAL_PORT; +typedef struct _VIRTIO_SERIAL_IO_PROTOCOL VIRTIO_SERIAL_IO_PROTOCOL; + +struct _VIRTIO_SERIAL_RING { + 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; +}; + +struct _VIRTIO_SERIAL_PORT { + BOOLEAN Ready; + BOOLEAN Console; + BOOLEAN DeviceOpen; + + CHAR16 Name[32]; + + VIRTIO_SERIAL_IO_PROTOCOL *SerialIo; +}; + +struct _VIRTIO_SERIAL_DEV { + UINT32 Signature; + LIST_ENTRY Link; + + EFI_HANDLE DriverBindingHandle; + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + VIRTIO_DEVICE_PROTOCOL *VirtIo; + EFI_EVENT ExitBoot; + VIRTIO_SERIAL_CONFIG Config; + VIRTIO_SERIAL_PORT Ports[MAX_PORTS]; + VIRTIO_SERIAL_RING Rings[MAX_RINGS]; + EFI_EVENT Timer; + + UINT32 NumPorts; + UINT32 NumConsoles; + UINT32 NumNamedPorts; +}; + +struct _VIRTIO_SERIAL_IO_PROTOCOL { + EFI_SERIAL_IO_PROTOCOL SerialIo; + EFI_SERIAL_IO_MODE SerialIoMode; + + EFI_HANDLE DeviceHandle; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + VIRTIO_SERIAL_DEV *Dev; + UINT32 PortId; + + UINT8 ReadBuffer[PORT_RX_BUFSIZE]; + UINT32 ReadOffset; + UINT32 ReadSize; + + UINT8 WriteBuffer[PORT_TX_BUFSIZE]; + UINT32 WriteOffset; +}; + +// +// VirtioSerial.c +// + +VOID +EFIAPI +LogDevicePath ( + UINT32 Level, + const CHAR8 *Func, + CHAR16 *Note, + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ); + +EFI_STATUS +EFIAPI +VirtioSerialTxControl ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 Id, + IN UINT16 Event, + IN UINT16 Value + ); + +// +// VirtioSerialRing.c +// + +EFI_STATUS +EFIAPI +VirtioSerialInitRing ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + IN UINT32 BufferSize + ); + +VOID +EFIAPI +VirtioSerialUninitRing ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ); + +VOID +EFIAPI +VirtioSerialRingFillRx ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ); + +VOID +EFIAPI +VirtioSerialRingClearTx ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ); + +EFI_STATUS +EFIAPI +VirtioSerialRingSendBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + IN VOID *Data, + IN UINT32 DataSize, + IN BOOLEAN Notify + ); + +BOOLEAN +EFIAPI +VirtioSerialRingHasBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ); + +BOOLEAN +EFIAPI +VirtioSerialRingGetBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + OUT VOID *Data, + OUT UINT32 *DataSize + ); + +// +// VirtioSerialPort.c +// + +EFI_STATUS +EFIAPI +VirtioSerialPortAdd ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ); + +VOID +EFIAPI +VirtioSerialPortSetConsole ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ); + +VOID +EFIAPI +VirtioSerialPortSetName ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId, + IN UINT8 *Name + ); + +VOID +EFIAPI +VirtioSerialPortSetDeviceOpen ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId, + IN UINT16 Value + ); + +VOID +EFIAPI +VirtioSerialPortRemove ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ); + +#endif diff --git a/OvmfPkg/VirtioSerialDxe/VirtioSerial.c b/OvmfPkg/VirtioSerialD= xe/VirtioSerial.c new file mode 100644 index 000000000000..bfb2b324eadf --- /dev/null +++ b/OvmfPkg/VirtioSerialDxe/VirtioSerial.c @@ -0,0 +1,808 @@ +/** @file + + Driver for virtio-serial devices. + + The virtio serial device also known as virtio console device because + initially it had only support for a single tty, intended to be used + as console. Support for multiple streams and named data ports has + been added later on. + + https://docs.oasis-open.org/virtio/virtio/v1.2/cs01/virtio-v1.2-cs01.htm= l#x1-2900003 + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include + +#include "VirtioSerial.h" + +STATIC LIST_ENTRY mVirtioSerialList; + +STATIC CONST CHAR8 *EventNames[] =3D { + [VIRTIO_SERIAL_DEVICE_READY] =3D "device-ready", + [VIRTIO_SERIAL_DEVICE_ADD] =3D "device-add", + [VIRTIO_SERIAL_DEVICE_REMOVE] =3D "device-remove", + [VIRTIO_SERIAL_PORT_READY] =3D "port-ready", + [VIRTIO_SERIAL_CONSOLE_PORT] =3D "console-port", + [VIRTIO_SERIAL_RESIZE] =3D "resize", + [VIRTIO_SERIAL_PORT_OPEN] =3D "port-open", + [VIRTIO_SERIAL_PORT_NAME] =3D "port-name", +}; + +VOID +EFIAPI +LogDevicePath ( + UINT32 Level, + const CHAR8 *Func, + CHAR16 *Note, + EFI_DEVICE_PATH_PROTOCOL *DevicePath + ) +{ + CHAR16 *Str; + + Str =3D ConvertDevicePathToText (DevicePath, FALSE, FALSE); + if (!Str) { + DEBUG ((DEBUG_INFO, "ConvertDevicePathToText failed\n")); + return; + } + + DEBUG ((Level, "%a: %s%s%s\n", Func, Note ? Note : L"", Note ? L": " : L= "", Str)); + FreePool (Str); +} + +EFI_STATUS +EFIAPI +VirtioSerialTxControl ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 Id, + IN UINT16 Event, + IN UINT16 Value + ) +{ + VIRTIO_SERIAL_CONTROL Control =3D { + .Id =3D Id, + .Event =3D Event, + .Value =3D Value, + }; + + DEBUG (( + DEBUG_INFO, + "%a:%d: >>> event %a, port-id %d, value %d\n", + __func__, + __LINE__, + EventNames[Control.Event], + Control.Id, + Control.Value + )); + + VirtioSerialRingClearTx (Dev, VIRTIO_SERIAL_Q_TX_CTRL); + return VirtioSerialRingSendBuffer (Dev, VIRTIO_SERIAL_Q_TX_CTRL, &Contro= l, sizeof (Control), TRUE); +} + +STATIC +VOID +EFIAPI +VirtioSerialRxControl ( + IN OUT VIRTIO_SERIAL_DEV *Dev + ) +{ + UINT8 Data[CTRL_RX_BUFSIZE+1]; + UINT32 DataSize; + VIRTIO_SERIAL_CONTROL Control; + EFI_STATUS Status; + BOOLEAN HasData; + UINT16 Ready; + + for ( ; ;) { + HasData =3D VirtioSerialRingGetBuffer (Dev, VIRTIO_SERIAL_Q_RX_CTRL, D= ata, &DataSize); + if (!HasData) { + return; + } + + if (DataSize < sizeof (Control)) { + DEBUG (( + DEBUG_ERROR, + "%a:%d: length mismatch: %d !=3D %d\n", + __func__, + __LINE__, + DataSize, + sizeof (Control) + )); + continue; + } + + CopyMem (&Control, Data, sizeof (Control)); + + if (Control.Event < ARRAY_SIZE (EventNames)) { + DEBUG (( + DEBUG_INFO, + "%a:%d: <<< event %a, port-id %d, value %d\n", + __func__, + __LINE__, + EventNames[Control.Event], + Control.Id, + Control.Value + )); + } else { + DEBUG (( + DEBUG_ERROR, + "%a:%d: unknown event: %d\n", + __func__, + __LINE__, + Control.Event + )); + } + + switch (Control.Event) { + case VIRTIO_SERIAL_DEVICE_ADD: + if (Control.Id < MAX_PORTS) { + Status =3D VirtioSerialPortAdd (Dev, Control.Id); + Ready =3D (Status =3D=3D EFI_SUCCESS) ? 1 : 0; + } else { + Ready =3D 0; + } + + VirtioSerialTxControl (Dev, Control.Id, VIRTIO_SERIAL_PORT_READY, = Ready); + if (Ready) { + Dev->NumPorts++; + } + + break; + case VIRTIO_SERIAL_DEVICE_REMOVE: + if (Control.Id < MAX_PORTS) { + VirtioSerialPortRemove (Dev, Control.Id); + } + + break; + case VIRTIO_SERIAL_CONSOLE_PORT: + if (Control.Id < MAX_PORTS) { + VirtioSerialPortSetConsole (Dev, Control.Id); + Dev->NumConsoles++; + } + + break; + case VIRTIO_SERIAL_PORT_NAME: + if (Control.Id < MAX_PORTS) { + Data[DataSize] =3D 0; + VirtioSerialPortSetName (Dev, Control.Id, Data + sizeof (Control= )); + Dev->NumNamedPorts++; + } + + break; + case VIRTIO_SERIAL_PORT_OPEN: + if (Control.Id < MAX_PORTS) { + VirtioSerialPortSetDeviceOpen (Dev, Control.Id, Control.Value); + } + + break; + default: + break; + } + } +} + +STATIC +VOID +EFIAPI +VirtioSerialTimer ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_SERIAL_DEV *Dev =3D Context; + + VirtioSerialRxControl (Dev); +} + +STATIC +VOID +EFIAPI +VirtioSerialUninitAllRings ( + IN OUT VIRTIO_SERIAL_DEV *Dev + ) +{ + UINT16 Index; + + for (Index =3D 0; Index < MAX_RINGS; Index++) { + VirtioSerialUninitRing (Dev, Index); + } +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialInit ( + IN OUT VIRTIO_SERIAL_DEV *Dev + ) +{ + UINT8 NextDevStat; + EFI_STATUS Status; + UINT64 Features; + UINTN Retries; + + // + // Execute virtio-0.9.5, 2.2.1 Device Initialization Sequence. + // + NextDevStat =3D 0; // step 1 -- reset device + Status =3D Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |=3D VSTAT_ACK; // step 2 -- acknowledge device presence + Status =3D Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + NextDevStat |=3D VSTAT_DRIVER; // step 3 -- we know how to drive it + Status =3D Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // Set Page Size - MMIO VirtIo Specific + // + Status =3D Dev->VirtIo->SetPageSize (Dev->VirtIo, EFI_PAGE_SIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // step 4a -- retrieve and validate features + // + Status =3D Dev->VirtIo->GetDeviceFeatures (Dev->VirtIo, &Features); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Features &=3D (VIRTIO_F_VERSION_1 | + VIRTIO_F_IOMMU_PLATFORM | + VIRTIO_SERIAL_F_MULTIPORT); + + // + // In virtio-1.0, feature negotiation is expected to complete before que= ue + // discovery, and the device can also reject the selected set of feature= s. + // + if (Dev->VirtIo->Revision >=3D VIRTIO_SPEC_REVISION (1, 0, 0)) { + Status =3D Virtio10WriteFeatures (Dev->VirtIo, Features, &NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + DEBUG (( + DEBUG_INFO, + "%a:%d: features ok:%a%a%a\n", + __func__, + __LINE__, + (Features & VIRTIO_F_VERSION_1) ? " v1.0" : "", + (Features & VIRTIO_F_IOMMU_PLATFORM) ? " iommu" : "", + (Features & VIRTIO_SERIAL_F_MULTIPORT) ? " multiport" : "" + )); + + if (Features & VIRTIO_SERIAL_F_MULTIPORT) { + Dev->VirtIo->ReadDevice ( + Dev->VirtIo, + OFFSET_OF (VIRTIO_SERIAL_CONFIG, MaxPorts), + sizeof (Dev->Config.MaxPorts), + sizeof (Dev->Config.MaxPorts), + &Dev->Config.MaxPorts + ); + DEBUG (( + DEBUG_INFO, + "%a:%d: max device ports: %d\n", + __func__, + __LINE__, + Dev->Config.MaxPorts + )); + } + + Status =3D VirtioSerialInitRing (Dev, VIRTIO_SERIAL_Q_RX_CTRL, CTRL_RX_B= UFSIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status =3D VirtioSerialInitRing (Dev, VIRTIO_SERIAL_Q_TX_CTRL, CTRL_TX_B= UFSIZE); + 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 &=3D ~(UINT64)(VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM); + Status =3D Dev->VirtIo->SetGuestFeatures (Dev->VirtIo, Features); + if (EFI_ERROR (Status)) { + goto Failed; + } + } + + // + // step 6 -- initialization complete + // + NextDevStat |=3D VSTAT_DRIVER_OK; + Status =3D Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + if (EFI_ERROR (Status)) { + goto Failed; + } + + VirtioSerialRingFillRx (Dev, VIRTIO_SERIAL_Q_RX_CTRL); + VirtioSerialTxControl (Dev, 0, VIRTIO_SERIAL_DEVICE_READY, 1); + for (Retries =3D 0; Retries < 100; Retries++) { + gBS->Stall (1000); + VirtioSerialRxControl (Dev); + if (Dev->NumPorts && (Dev->NumConsoles + Dev->NumNamedPorts =3D=3D Dev= ->NumPorts)) { + // port discovery complete + break; + } + } + + Status =3D gBS->CreateEvent ( + EVT_TIMER | EVT_NOTIFY_SIGNAL, + TPL_NOTIFY, + VirtioSerialTimer, + Dev, + &Dev->Timer + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status =3D gBS->SetTimer ( + Dev->Timer, + TimerPeriodic, + EFI_TIMER_PERIOD_MILLISECONDS (10) + ); + if (EFI_ERROR (Status)) { + goto Failed; + } + + DEBUG (( + DEBUG_INFO, + "%a:%d: OK, %d consoles, %d named ports\n", + __func__, + __LINE__, + Dev->NumConsoles, + Dev->NumNamedPorts + )); + return EFI_SUCCESS; + +Failed: + VirtioSerialUninitAllRings (Dev); + + // + // Notify the host about our failure to setup: virtio-0.9.5, 2.2.2.1 Dev= ice + // Status. VirtIo access failure here should not mask the original error. + // + NextDevStat |=3D VSTAT_FAILED; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, NextDevStat); + + DEBUG ((DEBUG_INFO, "%a:%d: ERROR: %r\n", __func__, __LINE__, Status)); + return Status; // reached only via Failed above +} + +STATIC +VOID +EFIAPI +VirtioSerialUninit ( + IN OUT VIRTIO_SERIAL_DEV *Dev + ) +{ + UINT32 PortId; + + gBS->CloseEvent (Dev->Timer); + + // + // 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 f= rom + // the old comms area. + // + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); + + for (PortId =3D 0; PortId < MAX_PORTS; PortId++) { + VirtioSerialPortRemove (Dev, PortId); + } + + VirtioSerialUninitAllRings (Dev); +} + +// +// Event notification function enqueued by ExitBootServices(). +// + +STATIC +VOID +EFIAPI +VirtioSerialExitBoot ( + IN EFI_EVENT Event, + IN VOID *Context + ) +{ + VIRTIO_SERIAL_DEV *Dev; + + DEBUG ((DEBUG_INFO, "%a: Context=3D0x%p\n", __func__, Context)); + // + // Reset the device. This causes the hypervisor to forget about the virt= io + // ring. + // + // We allocated said ring in EfiBootServicesData type memory, and code + // executing after ExitBootServices() is permitted to overwrite it. + // + Dev =3D Context; + Dev->VirtIo->SetDeviceStatus (Dev->VirtIo, 0); +} + +STATIC +VIRTIO_SERIAL_DEV * +VirtioSerialFind ( + EFI_HANDLE DeviceHandle + ) +{ + VIRTIO_SERIAL_DEV *Dev; + LIST_ENTRY *Entry; + + BASE_LIST_FOR_EACH (Entry, &mVirtioSerialList) { + Dev =3D CR (Entry, VIRTIO_SERIAL_DEV, Link, VIRTIO_SERIAL_SIG); + if (DeviceHandle =3D=3D Dev->DeviceHandle) { + return Dev; + } + } + return NULL; +} + +// +// Probe, start and stop functions of this driver, called by the DXE core = for +// specific devices. +// +// The following specifications document these interfaces: +// - Driver Writer's Guide for UEFI 2.3.1 v1.01, 9 Driver Binding Protocol +// - UEFI Spec 2.3.1 + Errata C, 10.1 EFI Driver Binding Protocol +// +// The implementation follows: +// - Driver Writer's Guide for UEFI 2.3.1 v1.01 +// - 5.1.3.4 OpenProtocol() and CloseProtocol() +// - UEFI Spec 2.3.1 + Errata C +// - 6.3 Protocol Handler Services +// + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialDriverBindingSupported ( + 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 succ= ess, + // the protocol is "instantiated" for the VirtIo device. Covers duplicate + // open attempts (EFI_ALREADY_STARTED). + // + Status =3D gBS->OpenProtocol ( + DeviceHandle, // candidate device + &gVirtioDeviceProtocolGuid, // for generic VirtIo access + (VOID **)&VirtIo, // handle to instantiate + This->DriverBindingHandle, // requestor driver identity + DeviceHandle, // ControllerHandle, accordi= ng to + // the UEFI Driver Model + EFI_OPEN_PROTOCOL_BY_DRIVER // get exclusive VirtIo acce= ss to + // the device; to be released + ); + if (EFI_ERROR (Status)) { + return Status; + } + + if (VirtIo->SubSystemDeviceId !=3D VIRTIO_SUBSYSTEM_CONSOLE) { + Status =3D EFI_UNSUPPORTED; + } + + DEBUG ((DEBUG_INFO, "%a:%d: subsystem %d -> %r\n", __func__, __LINE__, V= irtIo->SubSystemDeviceId, Status)); + + // + // We needed VirtIo access only transitorily, to see whether we support = the + // device or not. + // + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialDriverBindingStart ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath + ) +{ + VIRTIO_SERIAL_DEV *Dev; + EFI_STATUS Status; + + Dev =3D (VIRTIO_SERIAL_DEV *)AllocateZeroPool (sizeof *Dev); + if (Dev =3D=3D NULL) { + return EFI_OUT_OF_RESOURCES; + } + + Status =3D gBS->OpenProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID **)&Dev->DevicePath, + This->DriverBindingHandle, + DeviceHandle, + EFI_OPEN_PROTOCOL_GET_PROTOCOL + ); + if (EFI_ERROR (Status)) { + goto FreeVirtioSerial; + } + + Status =3D gBS->OpenProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, + This->DriverBindingHandle, + DeviceHandle, + EFI_OPEN_PROTOCOL_BY_DRIVER + ); + if (EFI_ERROR (Status)) { + goto FreeVirtioSerial; + } + + LogDevicePath (DEBUG_INFO, __func__, L"Dev", Dev->DevicePath); + + // + // VirtIo access granted, configure virtio-serial device. + // + Dev->Signature =3D VIRTIO_SERIAL_SIG; + Dev->DriverBindingHandle =3D This->DriverBindingHandle; + Dev->DeviceHandle =3D DeviceHandle; + Status =3D VirtioSerialInit (Dev); + if (EFI_ERROR (Status)) { + goto CloseVirtIo; + } + + Status =3D gBS->CreateEvent ( + EVT_SIGNAL_EXIT_BOOT_SERVICES, + TPL_CALLBACK, + &VirtioSerialExitBoot, + Dev, + &Dev->ExitBoot + ); + if (EFI_ERROR (Status)) { + goto UninitDev; + } + + InsertTailList (&mVirtioSerialList, &(Dev->Link)); + return EFI_SUCCESS; + +UninitDev: + VirtioSerialUninit (Dev); + +CloseVirtIo: + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + +FreeVirtioSerial: + FreePool (Dev); + + return Status; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialDriverBindingStop ( + IN EFI_DRIVER_BINDING_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN UINTN NumberOfChildren, + IN EFI_HANDLE *ChildHandleBuffer + ) +{ + VIRTIO_SERIAL_DEV *Dev; + UINT32 PortId; + UINT32 Child; + + Dev =3D VirtioSerialFind (DeviceHandle); + if (!Dev) { + return EFI_SUCCESS; + } + + if (NumberOfChildren) { + for (Child =3D 0; Child < NumberOfChildren; Child++) { + DEBUG ((DEBUG_INFO, "%a:%d: child handle 0x%x\n", __func__, __LINE__= , ChildHandleBuffer[Child])); + for (PortId =3D 0; PortId < MAX_PORTS; PortId++) { + if (Dev->Ports[PortId].Ready && + Dev->Ports[PortId].SerialIo && + (Dev->Ports[PortId].SerialIo->DeviceHandle =3D=3D ChildHandleB= uffer[Child])) + { + VirtioSerialPortRemove (Dev, PortId); + } + } + } + + return EFI_SUCCESS; + } + + DEBUG ((DEBUG_INFO, "%a:%d: controller handle 0x%x\n", __func__, __LINE_= _, DeviceHandle)); + + gBS->CloseEvent (Dev->ExitBoot); + + VirtioSerialUninit (Dev); + + gBS->CloseProtocol ( + DeviceHandle, + &gVirtioDeviceProtocolGuid, + This->DriverBindingHandle, + DeviceHandle + ); + + RemoveEntryList (&(Dev->Link)); + ZeroMem (Dev, sizeof (*Dev)); + FreePool (Dev); + + return EFI_SUCCESS; +} + +// +// The static object that groups the Supported() (ie. probe), Start() and +// Stop() functions of the driver together. Refer to UEFI Spec 2.3.1 + Err= ata +// C, 10.1 EFI Driver Binding Protocol. +// +STATIC EFI_DRIVER_BINDING_PROTOCOL gDriverBinding =3D { + &VirtioSerialDriverBindingSupported, + &VirtioSerialDriverBindingStart, + &VirtioSerialDriverBindingStop, + 0x10, // Version, must be in [0x10 .. 0xFFFFFFEF] for IHV-developed driv= ers + NULL, // ImageHandle, to be overwritten by + // EfiLibInstallDriverBindingComponentName2() in VirtioSerialEntry= Point() + NULL // DriverBindingHandle, ditto +}; + +// +// The purpose of the following scaffolding (EFI_COMPONENT_NAME_PROTOCOL a= nd +// EFI_COMPONENT_NAME2_PROTOCOL implementation) is to format the driver's = name +// in English, for display on standard console devices. This is recommende= d for +// UEFI drivers that follow the UEFI Driver Model. Refer to the Driver Wri= ter's +// Guide for UEFI 2.3.1 v1.01, 11 UEFI Driver and Controller Names. +// + +STATIC +EFI_UNICODE_STRING_TABLE mDriverNameTable[] =3D { + { "eng;en", L"Virtio Serial Driver" }, + { NULL, NULL } +}; + +STATIC +EFI_UNICODE_STRING_TABLE mDeviceNameTable[] =3D { + { "eng;en", L"Virtio Serial Device" }, + { NULL, NULL } +}; + +STATIC +EFI_UNICODE_STRING_TABLE mPortNameTable[] =3D { + { "eng;en", L"Virtio Serial Port" }, + { NULL, NULL } +}; + +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName; + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialGetDriverName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN CHAR8 *Language, + OUT CHAR16 **DriverName + ) +{ + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + mDriverNameTable, + DriverName, + (BOOLEAN)(This =3D=3D &gComponentName) // Iso639Language + ); +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialGetDeviceName ( + IN EFI_COMPONENT_NAME_PROTOCOL *This, + IN EFI_HANDLE DeviceHandle, + IN EFI_HANDLE ChildHandle, + IN CHAR8 *Language, + OUT CHAR16 **ControllerName + ) +{ + EFI_UNICODE_STRING_TABLE *Table; + VIRTIO_SERIAL_DEV *Dev; + UINT32 PortId; + + Dev =3D VirtioSerialFind (DeviceHandle); + if (!Dev) { + return EFI_UNSUPPORTED; + } + + if (ChildHandle) { + for (PortId =3D 0; PortId < MAX_PORTS; PortId++) { + if (Dev->Ports[PortId].Ready && + Dev->Ports[PortId].SerialIo && + (Dev->Ports[PortId].SerialIo->DeviceHandle =3D=3D ChildHandle)) + { + *ControllerName =3D Dev->Ports[PortId].Name; + return EFI_SUCCESS; + } + } + + Table =3D mPortNameTable; + } else { + Table =3D mDeviceNameTable; + } + + return LookupUnicodeString2 ( + Language, + This->SupportedLanguages, + Table, + ControllerName, + (BOOLEAN)(This =3D=3D &gComponentName) + ); +} + +STATIC +EFI_COMPONENT_NAME_PROTOCOL gComponentName =3D { + &VirtioSerialGetDriverName, + &VirtioSerialGetDeviceName, + "eng" // SupportedLanguages, ISO 639-2 language codes +}; + +STATIC +EFI_COMPONENT_NAME2_PROTOCOL gComponentName2 =3D { + (EFI_COMPONENT_NAME2_GET_DRIVER_NAME)&VirtioSerialGetDriverName, + (EFI_COMPONENT_NAME2_GET_CONTROLLER_NAME)&VirtioSerialGetDeviceName, + "en" // SupportedLanguages, RFC 4646 language codes +}; + +// +// Entry point of this driver. +// +EFI_STATUS +EFIAPI +VirtioSerialEntryPoint ( + IN EFI_HANDLE ImageHandle, + IN EFI_SYSTEM_TABLE *SystemTable + ) +{ + InitializeListHead (&mVirtioSerialList); + return EfiLibInstallDriverBindingComponentName2 ( + ImageHandle, + SystemTable, + &gDriverBinding, + ImageHandle, + &gComponentName, + &gComponentName2 + ); +} diff --git a/OvmfPkg/VirtioSerialDxe/VirtioSerialPort.c b/OvmfPkg/VirtioSer= ialDxe/VirtioSerialPort.c new file mode 100644 index 000000000000..522b25e9698c --- /dev/null +++ b/OvmfPkg/VirtioSerialDxe/VirtioSerialPort.c @@ -0,0 +1,465 @@ +/** @file + + Driver for virtio-serial devices. + + Helper functions to manage virtio serial ports. + Console ports will be registered as SerialIo UARTs. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "VirtioSerial.h" + +ACPI_HID_DEVICE_PATH mAcpiSerialDevNode =3D { + { + ACPI_DEVICE_PATH, + ACPI_DP, + { + (UINT8)(sizeof (ACPI_HID_DEVICE_PATH)), + (UINT8)((sizeof (ACPI_HID_DEVICE_PATH)) >> 8) + }, + }, + EISA_PNP_ID (0x0501), + 0 +}; + +UART_DEVICE_PATH mUartDevNode =3D { + { + MESSAGING_DEVICE_PATH, + MSG_UART_DP, + { + (UINT8)(sizeof (UART_DEVICE_PATH)), + (UINT8)((sizeof (UART_DEVICE_PATH)) >> 8) + } + }, + 0, // Reserved + 115200, // Speed + 8, 1, 1 // 8n1 +}; + +STATIC +UINT16 +PortRx ( + IN UINT32 PortId + ) +{ + ASSERT (PortId < MAX_PORTS); + + if (PortId >=3D 1) { + return (UINT16)(VIRTIO_SERIAL_Q_RX_BASE + (PortId - 1) * 2); + } + + return VIRTIO_SERIAL_Q_RX_PORT0; +} + +STATIC +UINT16 +PortTx ( + IN UINT32 PortId + ) +{ + ASSERT (PortId < MAX_PORTS); + + if (PortId >=3D 1) { + return (UINT16)(VIRTIO_SERIAL_Q_TX_BASE + (PortId - 1) * 2); + } + + return VIRTIO_SERIAL_Q_TX_PORT0; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoReset ( + IN EFI_SERIAL_IO_PROTOCOL *This + ) +{ + DEBUG ((DEBUG_VERBOSE, "%a:%d:\n", __func__, __LINE__)); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoSetAttributes ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT64 BaudRate, + IN UINT32 ReceiveFifoDepth, + IN UINT32 Timeout, + IN EFI_PARITY_TYPE Parity, + IN UINT8 DataBits, + IN EFI_STOP_BITS_TYPE StopBits + ) +{ + DEBUG (( + DEBUG_VERBOSE, + "%a:%d: Rate %ld, Fifo %d, Bits %d\n", + __func__, + __LINE__, + BaudRate, + ReceiveFifoDepth, + DataBits + )); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoSetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN UINT32 Control + ) +{ + DEBUG ((DEBUG_INFO, "%a:%d: Control 0x%x\n", __func__, __LINE__, Control= )); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoGetControl ( + IN EFI_SERIAL_IO_PROTOCOL *This, + OUT UINT32 *Control + ) +{ + DEBUG ((DEBUG_VERBOSE, "%a:%d: Control 0x%x\n", __func__, __LINE__, *Con= trol)); + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoWrite ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + IN VOID *Buffer + ) +{ + VIRTIO_SERIAL_IO_PROTOCOL *SerialIo =3D (VIRTIO_SERIAL_IO_PROTOCOL *)Th= is; + VIRTIO_SERIAL_PORT *Port =3D SerialIo->Dev->Ports + SerialIo= ->PortId; + UINT32 Length; + EFI_TPL OldTpl; + + if (!Port->DeviceOpen) { + *BufferSize =3D 0; + return EFI_SUCCESS; + } + + VirtioSerialRingClearTx (SerialIo->Dev, PortTx (SerialIo->PortId)); + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + if (SerialIo->WriteOffset && + (SerialIo->WriteOffset + *BufferSize > PORT_TX_BUFSIZE)) + { + DEBUG ((DEBUG_VERBOSE, "%a:%d: WriteFlush %d\n", __func__, __LINE__, S= erialIo->WriteOffset)); + VirtioSerialRingSendBuffer ( + SerialIo->Dev, + PortTx (SerialIo->PortId), + SerialIo->WriteBuffer, + SerialIo->WriteOffset, + TRUE + ); + SerialIo->WriteOffset =3D 0; + } + + Length =3D MIN ((UINT32)(*BufferSize), PORT_TX_BUFSIZE - SerialIo->Write= Offset); + CopyMem (SerialIo->WriteBuffer + SerialIo->WriteOffset, Buffer, Length); + SerialIo->WriteOffset +=3D Length; + *BufferSize =3D Length; + gBS->RestoreTPL (OldTpl); + + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoRead ( + IN EFI_SERIAL_IO_PROTOCOL *This, + IN OUT UINTN *BufferSize, + OUT VOID *Buffer + ) +{ + VIRTIO_SERIAL_IO_PROTOCOL *SerialIo =3D (VIRTIO_SERIAL_IO_PROTOCOL *)Th= is; + VIRTIO_SERIAL_PORT *Port =3D SerialIo->Dev->Ports + SerialIo= ->PortId; + BOOLEAN HasData; + UINT32 Length; + EFI_TPL OldTpl; + + if (!Port->DeviceOpen) { + goto NoData; + } + + OldTpl =3D gBS->RaiseTPL (TPL_CALLBACK); + if (SerialIo->WriteOffset) { + DEBUG ((DEBUG_VERBOSE, "%a:%d: WriteFlush %d\n", __func__, __LINE__, S= erialIo->WriteOffset)); + VirtioSerialRingSendBuffer ( + SerialIo->Dev, + PortTx (SerialIo->PortId), + SerialIo->WriteBuffer, + SerialIo->WriteOffset, + TRUE + ); + SerialIo->WriteOffset =3D 0; + } + + gBS->RestoreTPL (OldTpl); + + if (SerialIo->ReadOffset =3D=3D SerialIo->ReadSize) { + HasData =3D VirtioSerialRingGetBuffer ( + SerialIo->Dev, + PortRx (SerialIo->PortId), + &SerialIo->ReadBuffer, + &SerialIo->ReadSize + ); + if (!HasData) { + goto NoData; + } + + SerialIo->ReadOffset =3D 0; + } + + if (SerialIo->ReadOffset < SerialIo->ReadSize) { + Length =3D SerialIo->ReadSize - SerialIo->ReadOffset; + if (Length > *BufferSize) { + Length =3D (UINT32)(*BufferSize); + } + + CopyMem (Buffer, SerialIo->ReadBuffer + SerialIo->ReadOffset, Length); + SerialIo->ReadOffset +=3D Length; + *BufferSize =3D Length; + return EFI_SUCCESS; + } + +NoData: + *BufferSize =3D 0; + return EFI_SUCCESS; +} + +STATIC +EFI_STATUS +EFIAPI +VirtioSerialIoInit ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + VIRTIO_SERIAL_IO_PROTOCOL *SerialIo; + EFI_STATUS Status; + + SerialIo =3D (VIRTIO_SERIAL_IO_PROTOCOL *)AllocateZeroPool (sizeof= *SerialIo); + Port->SerialIo =3D SerialIo; + + SerialIo->SerialIo.Revision =3D EFI_SERIAL_IO_PROTOCOL_REVISION; + SerialIo->SerialIo.Reset =3D VirtioSerialIoReset; + SerialIo->SerialIo.SetAttributes =3D VirtioSerialIoSetAttributes; + SerialIo->SerialIo.SetControl =3D VirtioSerialIoSetControl; + SerialIo->SerialIo.GetControl =3D VirtioSerialIoGetControl; + SerialIo->SerialIo.Write =3D VirtioSerialIoWrite; + SerialIo->SerialIo.Read =3D VirtioSerialIoRead; + SerialIo->SerialIo.Mode =3D &SerialIo->SerialIoMode; + SerialIo->Dev =3D Dev; + SerialIo->PortId =3D PortId; + + SerialIo->DevicePath =3D DuplicateDevicePath (Dev->DevicePath); + mAcpiSerialDevNode.UID =3D PortId; + SerialIo->DevicePath =3D AppendDevicePathNode ( + SerialIo->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&mAcpiSerialDevNo= de + ); + SerialIo->DevicePath =3D AppendDevicePathNode ( + SerialIo->DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&mUartDevNode + ); + + LogDevicePath (DEBUG_INFO, __func__, L"UART", SerialIo->DevicePath); + + Status =3D gBS->InstallMultipleProtocolInterfaces ( + &SerialIo->DeviceHandle, + &gEfiDevicePathProtocolGuid, + SerialIo->DevicePath, + &gEfiSerialIoProtocolGuid, + &SerialIo->SerialIo, + NULL + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d: ERROR: %r\n", __func__, __LINE__, Status)); + goto FreeSerialIo; + } + + Status =3D gBS->OpenProtocol ( + Dev->DeviceHandle, + &gVirtioDeviceProtocolGuid, + (VOID **)&Dev->VirtIo, + Dev->DriverBindingHandle, + SerialIo->DeviceHandle, + EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER + ); + if (EFI_ERROR (Status)) { + DEBUG ((DEBUG_INFO, "%a:%d: ERROR: %r\n", __func__, __LINE__, Status)); + goto UninstallProtocol; + } + + return EFI_SUCCESS; + +UninstallProtocol: + gBS->UninstallMultipleProtocolInterfaces ( + SerialIo->DeviceHandle, + &gEfiDevicePathProtocolGuid, + SerialIo->DevicePath, + &gEfiSerialIoProtocolGuid, + &SerialIo->SerialIo, + NULL + ); + +FreeSerialIo: + FreePool (Port->SerialIo); + Port->SerialIo =3D NULL; + return Status; +} + +STATIC +VOID +EFIAPI +VirtioSerialIoUninit ( + VIRTIO_SERIAL_IO_PROTOCOL *SerialIo + ) +{ + VIRTIO_SERIAL_DEV *Dev =3D SerialIo->Dev; + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + SerialIo->PortId; + + DEBUG ((DEBUG_INFO, "%a:%d: %s\n", __func__, __LINE__, Port->Name)); + + gBS->CloseProtocol ( + Dev->DeviceHandle, + &gVirtioDeviceProtocolGuid, + Dev->DriverBindingHandle, + SerialIo->DeviceHandle + ); + + gBS->UninstallMultipleProtocolInterfaces ( + SerialIo->DeviceHandle, + &gEfiDevicePathProtocolGuid, + SerialIo->DevicePath, + &gEfiSerialIoProtocolGuid, + &SerialIo->SerialIo, + NULL + ); + + FreePool (SerialIo); + Port->SerialIo =3D NULL; +} + +EFI_STATUS +EFIAPI +VirtioSerialPortAdd ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + EFI_STATUS Status; + + if (Port->Ready) { + return EFI_SUCCESS; + } + + Status =3D VirtioSerialInitRing (Dev, PortRx (PortId), PORT_RX_BUFSIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status =3D VirtioSerialInitRing (Dev, PortTx (PortId), PORT_TX_BUFSIZE); + if (EFI_ERROR (Status)) { + goto Failed; + } + + UnicodeSPrint (Port->Name, sizeof (Port->Name), L"Port #%d", PortId); + VirtioSerialRingFillRx (Dev, PortRx (PortId)); + Port->Ready =3D TRUE; + + return EFI_SUCCESS; + +Failed: + VirtioSerialUninitRing (Dev, PortRx (PortId)); + return Status; +} + +VOID +EFIAPI +VirtioSerialPortSetConsole ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + + Port->Console =3D TRUE; + UnicodeSPrint (Port->Name, sizeof (Port->Name), L"Console #%d", PortId); + VirtioSerialIoInit (Dev, PortId); +} + +VOID +EFIAPI +VirtioSerialPortSetName ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId, + IN UINT8 *Name + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + + DEBUG ((DEBUG_INFO, "%a:%d: \"%a\"\n", __func__, __LINE__, Name)); + UnicodeSPrint (Port->Name, sizeof (Port->Name), L"NamedPort #%d (%a)", P= ortId, Name); +} + +VOID +EFIAPI +VirtioSerialPortSetDeviceOpen ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId, + IN UINT16 Value + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + + Port->DeviceOpen =3D (BOOLEAN)Value; + if (Port->DeviceOpen) { + VirtioSerialTxControl (Dev, PortId, VIRTIO_SERIAL_PORT_OPEN, 1); + } +} + +VOID +EFIAPI +VirtioSerialPortRemove ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT32 PortId + ) +{ + VIRTIO_SERIAL_PORT *Port =3D Dev->Ports + PortId; + + if (!Port->Ready) { + return; + } + + if (Port->SerialIo) { + VirtioSerialIoUninit (Port->SerialIo); + Port->SerialIo =3D NULL; + } + + VirtioSerialUninitRing (Dev, PortRx (PortId)); + VirtioSerialUninitRing (Dev, PortTx (PortId)); + Port->Ready =3D FALSE; +} diff --git a/OvmfPkg/VirtioSerialDxe/VirtioSerialRing.c b/OvmfPkg/VirtioSer= ialDxe/VirtioSerialRing.c new file mode 100644 index 000000000000..936e1507a3b6 --- /dev/null +++ b/OvmfPkg/VirtioSerialDxe/VirtioSerialRing.c @@ -0,0 +1,345 @@ +/** @file + + Driver for virtio-serial devices. + + Helper functions to manage virtio rings. + + SPDX-License-Identifier: BSD-2-Clause-Patent + +**/ + +#include +#include +#include +#include +#include +#include + +#include "VirtioSerial.h" + +STATIC +VOID * +BufferPtr ( + IN VIRTIO_SERIAL_RING *Ring, + IN UINT32 BufferNr + ) +{ + return Ring->Buffers + Ring->BufferSize * BufferNr; +} + +STATIC +EFI_PHYSICAL_ADDRESS +BufferAddr ( + IN VIRTIO_SERIAL_RING *Ring, + IN UINT32 BufferNr + ) +{ + return Ring->DeviceAddress + Ring->BufferSize * BufferNr; +} + +STATIC +UINT32 +BufferNext ( + IN VIRTIO_SERIAL_RING *Ring + ) +{ + return Ring->Indices.NextDescIdx % Ring->Ring.QueueSize; +} + +EFI_STATUS +EFIAPI +VirtioSerialInitRing ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + IN UINT32 BufferSize + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + EFI_STATUS Status; + UINT16 QueueSize; + UINT64 RingBaseShift; + + // + // step 4b -- allocate request virtqueue + // + Status =3D Dev->VirtIo->SetQueueSel (Dev->VirtIo, Index); + if (EFI_ERROR (Status)) { + goto Failed; + } + + Status =3D Dev->VirtIo->GetQueueNumMax (Dev->VirtIo, &QueueSize); + if (EFI_ERROR (Status)) { + goto Failed; + } + + // + // VirtioSerial uses one descriptor + // + if (QueueSize < 1) { + Status =3D EFI_UNSUPPORTED; + goto Failed; + } + + Status =3D 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 =3D 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 resource= s. + // + Status =3D Dev->VirtIo->SetQueueNum (Dev->VirtIo, QueueSize); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status =3D 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 =3D Dev->VirtIo->SetQueueAddress ( + Dev->VirtIo, + &Ring->Ring, + RingBaseShift + ); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Ring->BufferCount =3D QueueSize; + Ring->BufferSize =3D BufferSize; + Ring->BufferPages =3D EFI_SIZE_TO_PAGES (Ring->BufferCount * Ring->Buffe= rSize); + + Status =3D Dev->VirtIo->AllocateSharedPages (Dev->VirtIo, Ring->BufferPa= ges, (VOID **)&Ring->Buffers); + if (EFI_ERROR (Status)) { + goto UnmapQueue; + } + + Status =3D 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 =3D TRUE; + + return EFI_SUCCESS; + +ReleasePages: + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + Ring->BufferPages, + Ring->Buffers + ); + Ring->Buffers =3D NULL; + +UnmapQueue: + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->RingMap); + Ring->RingMap =3D NULL; + +ReleaseQueue: + VirtioRingUninit (Dev->VirtIo, &Ring->Ring); + +Failed: + return Status; +} + +VOID +EFIAPI +VirtioSerialUninitRing ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + + if (Ring->BufferMap) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->BufferMap); + Ring->BufferMap =3D NULL; + } + + if (Ring->Buffers) { + Dev->VirtIo->FreeSharedPages ( + Dev->VirtIo, + Ring->BufferPages, + Ring->Buffers + ); + Ring->Buffers =3D NULL; + } + + if (!Ring->RingMap) { + Dev->VirtIo->UnmapSharedBuffer (Dev->VirtIo, Ring->RingMap); + Ring->RingMap =3D NULL; + } + + if (Ring->Ring.Base) { + VirtioRingUninit (Dev->VirtIo, &Ring->Ring); + } + + ZeroMem (Ring, sizeof (*Ring)); +} + +VOID +EFIAPI +VirtioSerialRingFillRx ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + UINT32 BufferNr; + + for (BufferNr =3D 0; BufferNr < Ring->BufferCount; BufferNr++) { + VirtioSerialRingSendBuffer (Dev, Index, NULL, Ring->BufferSize, FALSE); + } + + Dev->VirtIo->SetQueueNotify (Dev->VirtIo, Index); +} + +VOID +EFIAPI +VirtioSerialRingClearTx ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ) +{ + while (VirtioSerialRingGetBuffer (Dev, Index, NULL, NULL)) { + /* nothing */ } +} + +EFI_STATUS +EFIAPI +VirtioSerialRingSendBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + IN VOID *Data, + IN UINT32 DataSize, + IN BOOLEAN Notify + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + UINT32 BufferNr =3D BufferNext (Ring); + UINT16 Idx =3D *Ring->Ring.Avail.Idx; + UINT16 Flags =3D 0; + + ASSERT (DataSize <=3D Ring->BufferSize); + + if (Data) { + /* driver -> device */ + CopyMem (BufferPtr (Ring, BufferNr), Data, DataSize); + } else { + /* device -> driver */ + Flags |=3D VRING_DESC_F_WRITE; + } + + VirtioAppendDesc ( + &Ring->Ring, + BufferAddr (Ring, BufferNr), + DataSize, + Flags, + &Ring->Indices + ); + + Ring->Ring.Avail.Ring[Idx % Ring->Ring.QueueSize] =3D + Ring->Indices.HeadDescIdx % Ring->Ring.QueueSize; + Ring->Indices.HeadDescIdx =3D Ring->Indices.NextDescIdx; + Idx++; + + MemoryFence (); + *Ring->Ring.Avail.Idx =3D Idx; + MemoryFence (); + + if (Notify) { + Dev->VirtIo->SetQueueNotify (Dev->VirtIo, Index); + } + + return EFI_SUCCESS; +} + +BOOLEAN +EFIAPI +VirtioSerialRingHasBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + UINT16 UsedIdx =3D *Ring->Ring.Used.Idx; + + if (!Ring->Ready) { + return FALSE; + } + + if (Ring->LastUsedIdx =3D=3D UsedIdx) { + return FALSE; + } + + return TRUE; +} + +BOOLEAN +EFIAPI +VirtioSerialRingGetBuffer ( + IN OUT VIRTIO_SERIAL_DEV *Dev, + IN UINT16 Index, + OUT VOID *Data, + OUT UINT32 *DataSize + ) +{ + VIRTIO_SERIAL_RING *Ring =3D Dev->Rings + Index; + UINT16 UsedIdx =3D *Ring->Ring.Used.Idx; + volatile VRING_USED_ELEM *UsedElem; + + if (!Ring->Ready) { + return FALSE; + } + + if (Ring->LastUsedIdx =3D=3D UsedIdx) { + return FALSE; + } + + UsedElem =3D 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 =3D 0; + } + + if (Data && DataSize) { + CopyMem (Data, BufferPtr (Ring, UsedElem->Id), UsedElem->Len); + *DataSize =3D UsedElem->Len; + } + + if (Index % 2 =3D=3D 0) { + /* RX - re-queue buffer */ + VirtioSerialRingSendBuffer (Dev, Index, NULL, Ring->BufferSize, FALSE); + } + + Ring->LastUsedIdx++; + return TRUE; +} --=20 2.40.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103993): https://edk2.groups.io/g/devel/message/103993 Mute This Topic: https://groups.io/mt/98683333/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri May 17 16:21:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+103994+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103994+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1683205934; cv=none; d=zohomail.com; s=zohoarc; b=LrZ1RuqPDCRp1lAsIPugjBnUNkeCx5jywj+Cdb0rlh/5SeTJdvR77LJJvEsuH4adTmnA5XaJRAl8lCnupLZpfDnHzj/4eBxE97wIdmjJT+26YF77iED4UC6eWD1EffylEY+IoUkxiB2eiUbQ/69ar8NOkiBqFRuZrPXeFAdn+H8= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1683205934; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=4GLHWCXxbjzCo1YZCQcvIAVGkRqrIZYlvI6DkpQDeNM=; b=L81/M6D9kKWPWO+nN+dgJt1clYae1M+5KKiu+2pQR4mT27Jfk9Y4pI9Dczl70aYgmHFVEA2pVGJ0aeXwsAra2YfVXAWrio4q7PejtD+X5fLVf9ekFY2A0ScElB/vspHcNN2+2nNVrxMmsLQF760ir1T9dv03l4sKVmPNUOMxfrY= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103994+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1683205934512619.2620169383598; Thu, 4 May 2023 06:12:14 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id MzTMYY1788612xBrt4PBrkmK; Thu, 04 May 2023 06:12:14 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.133.124]) by mx.groups.io with SMTP id smtpd.web10.49482.1683205933600409662 for ; Thu, 04 May 2023 06:12:13 -0700 X-Received: from mimecast-mx02.redhat.com (mx3-rdu2.redhat.com [66.187.233.73]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-460-RDvyLyLpOo6fEVn3WeMHZA-1; Thu, 04 May 2023 09:12:11 -0400 X-MC-Unique: RDvyLyLpOo6fEVn3WeMHZA-1 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id DC0611C060D5; Thu, 4 May 2023 13:12:10 +0000 (UTC) X-Received: from sirius.home.kraxel.org (unknown [10.39.192.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id 7E091C15BAD; Thu, 4 May 2023 13:12:04 +0000 (UTC) X-Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 2EFF31800936; Thu, 4 May 2023 15:12:01 +0200 (CEST) From: "Gerd Hoffmann" To: devel@edk2.groups.io Cc: Oliver Steffen , Stefan Berger , Anthony Perard , Jiewen Yao , Julien Grall , Pawel Polawski , Jordan Justen , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 3/4] OvmfPkg/VirtioSerialDxe: wire up in OvmfPkg* Date: Thu, 4 May 2023 15:12:00 +0200 Message-Id: <20230504131201.1026585-4-kraxel@redhat.com> In-Reply-To: <20230504131201.1026585-1-kraxel@redhat.com> References: <20230504131201.1026585-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,kraxel@redhat.com X-Gm-Message-State: w6SPBSWgfrY5Tr5tOMwwqWLrx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1683205934; bh=PmtD+0pr/Fr1LUeuAPhYgw41UwF2Sdw0uMTLhZ8rTA4=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=JCCB3ji0Ap3KKSZZGv9xFSgi9qX+asm8fHPwtNeCO9f0flzPpYDc0XhGRBqq99urvrg 44iaFVmMM7lWhVWT/RF73TOswiUqQ88bTkypURnkcqqVruvxaYZqFnSJNSWqg4d2uoLxZ eZKI/eMzD/J+tYbReYAod8ohm0l7nKN+Iis= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1683205934813100001 Content-Type: text/plain; charset="utf-8"; x-default="true" Add the driver to the ovmf builds. Signed-off-by: Gerd Hoffmann --- OvmfPkg/Microvm/MicrovmX64.dsc | 1 + OvmfPkg/OvmfPkgIa32.dsc | 1 + OvmfPkg/OvmfPkgIa32X64.dsc | 1 + OvmfPkg/OvmfPkgX64.dsc | 1 + OvmfPkg/Microvm/MicrovmX64.fdf | 1 + OvmfPkg/OvmfPkgIa32.fdf | 1 + OvmfPkg/OvmfPkgIa32X64.fdf | 1 + OvmfPkg/OvmfPkgX64.fdf | 1 + 8 files changed, 8 insertions(+) diff --git a/OvmfPkg/Microvm/MicrovmX64.dsc b/OvmfPkg/Microvm/MicrovmX64.dsc index e9aab515592f..3da60875516a 100644 --- a/OvmfPkg/Microvm/MicrovmX64.dsc +++ b/OvmfPkg/Microvm/MicrovmX64.dsc @@ -751,6 +751,7 @@ [Components] OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioRngDxe/VirtioRng.inf + OvmfPkg/VirtioSerialDxe/VirtioSerial.inf MdeModulePkg/Universal/WatchdogTimerDxe/WatchdogTimer.inf MdeModulePkg/Universal/MonotonicCounterRuntimeDxe/MonotonicCounterRuntim= eDxe.inf MdeModulePkg/Universal/CapsuleRuntimeDxe/CapsuleRuntimeDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32.dsc b/OvmfPkg/OvmfPkgIa32.dsc index 86177bb94899..d0d63ba8b92b 100644 --- a/OvmfPkg/OvmfPkgIa32.dsc +++ b/OvmfPkg/OvmfPkgIa32.dsc @@ -802,6 +802,7 @@ [Components] OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioRngDxe/VirtioRng.inf + OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.dsc b/OvmfPkg/OvmfPkgIa32X64.dsc index 065b54450647..a6d1ebabb783 100644 --- a/OvmfPkg/OvmfPkgIa32X64.dsc +++ b/OvmfPkg/OvmfPkgIa32X64.dsc @@ -816,6 +816,7 @@ [Components.X64] OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioRngDxe/VirtioRng.inf + OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.dsc b/OvmfPkg/OvmfPkgX64.dsc index 3d405cd4ade0..3a4aa913c2a4 100644 --- a/OvmfPkg/OvmfPkgX64.dsc +++ b/OvmfPkg/OvmfPkgX64.dsc @@ -890,6 +890,7 @@ [Components] OvmfPkg/VirtioBlkDxe/VirtioBlk.inf OvmfPkg/VirtioScsiDxe/VirtioScsi.inf OvmfPkg/VirtioRngDxe/VirtioRng.inf + OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/Microvm/MicrovmX64.fdf b/OvmfPkg/Microvm/MicrovmX64.fdf index b83fd1e6e4fe..0d44e8dfbae8 100644 --- a/OvmfPkg/Microvm/MicrovmX64.fdf +++ b/OvmfPkg/Microvm/MicrovmX64.fdf @@ -205,6 +205,7 @@ [FV.DXEFV] INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioRngDxe/VirtioRng.inf +INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf =20 !if $(SECURE_BOOT_ENABLE) =3D=3D TRUE INF SecurityPkg/VariableAuthenticated/SecureBootConfigDxe/SecureBootCon= figDxe.inf diff --git a/OvmfPkg/OvmfPkgIa32.fdf b/OvmfPkg/OvmfPkgIa32.fdf index 5451bfb84525..15a25f1be5e5 100644 --- a/OvmfPkg/OvmfPkgIa32.fdf +++ b/OvmfPkg/OvmfPkgIa32.fdf @@ -238,6 +238,7 @@ [FV.DXEFV] INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioRngDxe/VirtioRng.inf +INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgIa32X64.fdf b/OvmfPkg/OvmfPkgIa32X64.fdf index 4c5bd0dbc3b0..138cbd382d4e 100644 --- a/OvmfPkg/OvmfPkgIa32X64.fdf +++ b/OvmfPkg/OvmfPkgIa32X64.fdf @@ -239,6 +239,7 @@ [FV.DXEFV] INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioRngDxe/VirtioRng.inf +INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif diff --git a/OvmfPkg/OvmfPkgX64.fdf b/OvmfPkg/OvmfPkgX64.fdf index 16666ba24440..4f24051ae994 100644 --- a/OvmfPkg/OvmfPkgX64.fdf +++ b/OvmfPkg/OvmfPkgX64.fdf @@ -264,6 +264,7 @@ [FV.DXEFV] INF OvmfPkg/VirtioBlkDxe/VirtioBlk.inf INF OvmfPkg/VirtioScsiDxe/VirtioScsi.inf INF OvmfPkg/VirtioRngDxe/VirtioRng.inf +INF OvmfPkg/VirtioSerialDxe/VirtioSerial.inf !if $(PVSCSI_ENABLE) =3D=3D TRUE INF OvmfPkg/PvScsiDxe/PvScsiDxe.inf !endif --=20 2.40.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103994): https://edk2.groups.io/g/devel/message/103994 Mute This Topic: https://groups.io/mt/98683334/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- From nobody Fri May 17 16:21:45 2024 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) client-ip=66.175.222.108; envelope-from=bounce+27952+103995+1787277+3901457@groups.io; helo=mail02.groups.io; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103995+1787277+3901457@groups.io; dmarc=fail(p=none dis=none) header.from=redhat.com ARC-Seal: i=1; a=rsa-sha256; t=1683205941; cv=none; d=zohomail.com; s=zohoarc; b=aI/noCUz0pevpbGGW24C2W5sr1+bACyTZ7jb0tyqHpLdDASiyuXTbN4LQbf7A7YRNaiL7Xyj+aFcmXToJf2/P8Ywmk/KvgRT36oWnchbAWE07jGXLG4BV8P8TcvbStRroPgSng78vnD/DLV0LHT+Rh27AYlcrV8m1CcSjgU3Xuo= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1683205941; h=Content-Type:Content-Transfer-Encoding:Cc:Date:From:In-Reply-To:List-Subscribe:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Reply-To:References:Sender:Subject:To; bh=pam40O+/UwxOwMMyWd/7JWHNsd6+M2GEDmaeRlj6Z1M=; b=Mdo9sNaQmiDXSmQni1huQDy6ScUFeDFpxj6dfHctRHOBAKthBwbtmWkSB0Mum7AXlw3ehNk6UHZJJkaQHZTiF3z+UtmI3JDb6MjyowjRN0/TYMZ2j42mY+35/Ht29EtAlhw46YYB31EdCutV3l1DxSduP+xb9KAd4pVR4+ICB1o= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of groups.io designates 66.175.222.108 as permitted sender) smtp.mailfrom=bounce+27952+103995+1787277+3901457@groups.io; dmarc=fail header.from= (p=none dis=none) Received: from mail02.groups.io (mail02.groups.io [66.175.222.108]) by mx.zohomail.com with SMTPS id 1683205941675462.03498858764635; Thu, 4 May 2023 06:12:21 -0700 (PDT) Return-Path: X-Received: by 127.0.0.2 with SMTP id TzaVYY1788612xDNCLYCCJc1; Thu, 04 May 2023 06:12:21 -0700 X-Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by mx.groups.io with SMTP id smtpd.web10.49488.1683205940669330954 for ; Thu, 04 May 2023 06:12:20 -0700 X-Received: from mimecast-mx02.redhat.com (mimecast-mx02.redhat.com [66.187.233.88]) by relay.mimecast.com with ESMTP with STARTTLS (version=TLSv1.2, cipher=TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384) id us-mta-103-MIV9o6RjPxya27ck1BiI_g-1; Thu, 04 May 2023 09:12:11 -0400 X-MC-Unique: MIV9o6RjPxya27ck1BiI_g-1 X-Received: from smtp.corp.redhat.com (int-mx08.intmail.prod.int.rdu2.redhat.com [10.11.54.8]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx02.redhat.com (Postfix) with ESMTPS id C14D7800B35; Thu, 4 May 2023 13:12:10 +0000 (UTC) X-Received: from sirius.home.kraxel.org (unknown [10.39.192.48]) by smtp.corp.redhat.com (Postfix) with ESMTPS id C8B33C15BAE; Thu, 4 May 2023 13:12:06 +0000 (UTC) X-Received: by sirius.home.kraxel.org (Postfix, from userid 1000) id 332EE1800986; Thu, 4 May 2023 15:12:01 +0200 (CEST) From: "Gerd Hoffmann" To: devel@edk2.groups.io Cc: Oliver Steffen , Stefan Berger , Anthony Perard , Jiewen Yao , Julien Grall , Pawel Polawski , Jordan Justen , =?UTF-8?q?Marc-Andr=C3=A9=20Lureau?= , Gerd Hoffmann , Ard Biesheuvel Subject: [edk2-devel] [PATCH v2 4/4] OvmfPkg/PlatformBootManagerLib: setup virtio serial console Date: Thu, 4 May 2023 15:12:01 +0200 Message-Id: <20230504131201.1026585-5-kraxel@redhat.com> In-Reply-To: <20230504131201.1026585-1-kraxel@redhat.com> References: <20230504131201.1026585-1-kraxel@redhat.com> MIME-Version: 1.0 X-Scanned-By: MIMEDefang 3.1 on 10.11.54.8 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com Precedence: Bulk List-Unsubscribe: List-Subscribe: List-Help: Sender: devel@edk2.groups.io List-Id: Mailing-List: list devel@edk2.groups.io; contact devel+owner@edk2.groups.io Reply-To: devel@edk2.groups.io,kraxel@redhat.com X-Gm-Message-State: KgyPnkLGdMWmAOzRd1Te1qDgx1787277AA= Content-Transfer-Encoding: quoted-printable DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=groups.io; q=dns/txt; s=20140610; t=1683205941; bh=J1uiB2HAkBxC3UmjJBeEdJCp3d9HK35QQuDPZslBFgI=; h=Cc:Content-Type:Date:From:Reply-To:Subject:To; b=chmUDzq2Lay5IqY6pMoCOhAnxe8nZ3mUplhBe8YqtMR9HhKBp1kQQUwsiFsu9q2aHDt 5h2/0Gnfyya4IYT1qXvFYucFNr2uakMRrmzDaU5o7ACy5XwOY8EsDVQCb31i8s9Mv4Nud 8UqU+yKVNQ2nNPad2vPrRKlUWlWGxnh50dM= X-ZohoMail-DKIM: pass (identity @groups.io) X-ZM-MESSAGEID: 1683205942903100002 Content-Type: text/plain; charset="utf-8"; x-default="true" In case a virtio-serial device is present in the system register the first serial port as console. Signed-off-by: Gerd Hoffmann --- .../PlatformBootManagerLib/BdsPlatform.c | 47 +++++++++++++++++++ 1 file changed, 47 insertions(+) diff --git a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c b/OvmfPkg= /Library/PlatformBootManagerLib/BdsPlatform.c index a90076c9e672..3b7dc53e9f86 100644 --- a/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c +++ b/OvmfPkg/Library/PlatformBootManagerLib/BdsPlatform.c @@ -976,6 +976,45 @@ PreparePciSerialDevicePath ( return EFI_SUCCESS; } =20 +EFI_STATUS +PrepareVirtioSerialDevicePath ( + IN EFI_HANDLE DeviceHandle + ) +{ + EFI_STATUS Status; + EFI_DEVICE_PATH_PROTOCOL *DevicePath; + + DevicePath =3D NULL; + Status =3D gBS->HandleProtocol ( + DeviceHandle, + &gEfiDevicePathProtocolGuid, + (VOID *)&DevicePath + ); + if (EFI_ERROR (Status)) { + return Status; + } + + gPnp16550ComPortDeviceNode.UID =3D 0; + DevicePath =3D AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gPnp1655= 0ComPortDeviceNode + ); + DevicePath =3D AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gUartDeviceNode + ); + DevicePath =3D AppendDevicePathNode ( + DevicePath, + (EFI_DEVICE_PATH_PROTOCOL *)&gTerminalTypeDeviceNode + ); + + EfiBootManagerUpdateConsoleVariable (ConOut, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ConIn, DevicePath, NULL); + EfiBootManagerUpdateConsoleVariable (ErrOut, DevicePath, NULL); + + return EFI_SUCCESS; +} + EFI_STATUS VisitAllInstancesOfProtocol ( IN EFI_GUID *Id, @@ -1144,6 +1183,14 @@ DetectAndPreparePlatformPciDevicePath ( return EFI_SUCCESS; } =20 + if (((Pci->Hdr.VendorId =3D=3D 0x1af4) && (Pci->Hdr.DeviceId =3D=3D 0x10= 03)) || + ((Pci->Hdr.VendorId =3D=3D 0x1af4) && (Pci->Hdr.DeviceId =3D=3D 0x10= 43))) + { + DEBUG ((DEBUG_INFO, "Found virtio serial device\n")); + PrepareVirtioSerialDevicePath (Handle); + return EFI_SUCCESS; + } + return Status; } =20 --=20 2.40.1 -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D- Groups.io Links: You receive all messages sent to this group. View/Reply Online (#103995): https://edk2.groups.io/g/devel/message/103995 Mute This Topic: https://groups.io/mt/98683338/1787277 Group Owner: devel+owner@edk2.groups.io Unsubscribe: https://edk2.groups.io/g/devel/unsub [importer@patchew.org] -=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-=3D-