aboutsummaryrefslogtreecommitdiffstats
path: root/roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c
diff options
context:
space:
mode:
Diffstat (limited to 'roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c')
-rw-r--r--roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c767
1 files changed, 767 insertions, 0 deletions
diff --git a/roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c b/roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c
new file mode 100644
index 000000000..1645100a0
--- /dev/null
+++ b/roms/edk2/OvmfPkg/VirtioGpuDxe/Commands.c
@@ -0,0 +1,767 @@
+/** @file
+
+ VirtIo GPU initialization, and commands (primitives) for the GPU device.
+
+ Copyright (C) 2016, Red Hat, Inc.
+ Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
+
+ SPDX-License-Identifier: BSD-2-Clause-Patent
+
+**/
+
+#include <Library/VirtioLib.h>
+
+#include "VirtioGpu.h"
+
+/**
+ Configure the VirtIo GPU device that underlies VgpuDev.
+
+ @param[in,out] VgpuDev The VGPU_DEV object to set up VirtIo messaging for.
+ On input, the caller is responsible for having
+ initialized VgpuDev->VirtIo. On output, VgpuDev->Ring
+ has been initialized, and synchronous VirtIo GPU
+ commands (primitives) can be submitted to the device.
+
+ @retval EFI_SUCCESS VirtIo GPU configuration successful.
+
+ @retval EFI_UNSUPPORTED The host-side configuration of the VirtIo GPU is not
+ supported by this driver.
+
+ @retval Error codes from underlying functions.
+**/
+EFI_STATUS
+VirtioGpuInit (
+ IN OUT VGPU_DEV *VgpuDev
+ )
+{
+ UINT8 NextDevStat;
+ EFI_STATUS Status;
+ UINT64 Features;
+ UINT16 QueueSize;
+ UINT64 RingBaseShift;
+
+ //
+ // Execute virtio-v1.0-cs04, 3.1.1 Driver Requirements: Device
+ // Initialization.
+ //
+ // 1. Reset the device.
+ //
+ NextDevStat = 0;
+ Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 2. Set the ACKNOWLEDGE status bit [...]
+ //
+ NextDevStat |= VSTAT_ACK;
+ Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 3. Set the DRIVER status bit [...]
+ //
+ NextDevStat |= VSTAT_DRIVER;
+ Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 4. Read device feature bits...
+ //
+ Status = VgpuDev->VirtIo->GetDeviceFeatures (VgpuDev->VirtIo, &Features);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ if ((Features & VIRTIO_F_VERSION_1) == 0) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+ //
+ // We only want the most basic 2D features.
+ //
+ Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
+
+ //
+ // ... and write the subset of feature bits understood by the [...] driver to
+ // the device. [...]
+ // 5. Set the FEATURES_OK status bit.
+ // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
+ //
+ Status = Virtio10WriteFeatures (VgpuDev->VirtIo, Features, &NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // 7. Perform device-specific setup, including discovery of virtqueues for
+ // the device [...]
+ //
+ Status = VgpuDev->VirtIo->SetQueueSel (VgpuDev->VirtIo,
+ VIRTIO_GPU_CONTROL_QUEUE);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ Status = VgpuDev->VirtIo->GetQueueNumMax (VgpuDev->VirtIo, &QueueSize);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+
+ //
+ // We implement each VirtIo GPU command that we use with two descriptors:
+ // request, response.
+ //
+ if (QueueSize < 2) {
+ Status = EFI_UNSUPPORTED;
+ goto Failed;
+ }
+
+ //
+ // [...] population of virtqueues [...]
+ //
+ Status = VirtioRingInit (VgpuDev->VirtIo, QueueSize, &VgpuDev->Ring);
+ if (EFI_ERROR (Status)) {
+ goto Failed;
+ }
+ //
+ // If anything fails from here on, we have to release the ring.
+ //
+ Status = VirtioRingMap (
+ VgpuDev->VirtIo,
+ &VgpuDev->Ring,
+ &RingBaseShift,
+ &VgpuDev->RingMap
+ );
+ if (EFI_ERROR (Status)) {
+ goto ReleaseQueue;
+ }
+ //
+ // If anything fails from here on, we have to unmap the ring.
+ //
+ Status = VgpuDev->VirtIo->SetQueueAddress (
+ VgpuDev->VirtIo,
+ &VgpuDev->Ring,
+ RingBaseShift
+ );
+ if (EFI_ERROR (Status)) {
+ goto UnmapQueue;
+ }
+
+ //
+ // 8. Set the DRIVER_OK status bit.
+ //
+ NextDevStat |= VSTAT_DRIVER_OK;
+ Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
+ if (EFI_ERROR (Status)) {
+ goto UnmapQueue;
+ }
+
+ return EFI_SUCCESS;
+
+UnmapQueue:
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
+
+ReleaseQueue:
+ VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
+
+Failed:
+ //
+ // If any of these steps go irrecoverably wrong, the driver SHOULD set the
+ // FAILED status bit to indicate that it has given up on the device (it can
+ // reset the device later to restart if desired). [...]
+ //
+ // VirtIo access failure here should not mask the original error.
+ //
+ NextDevStat |= VSTAT_FAILED;
+ VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
+
+ return Status;
+}
+
+/**
+ De-configure the VirtIo GPU device that underlies VgpuDev.
+
+ @param[in,out] VgpuDev The VGPU_DEV object to tear down VirtIo messaging
+ for. On input, the caller is responsible for having
+ called VirtioGpuInit(). On output, VgpuDev->Ring has
+ been uninitialized; VirtIo GPU commands (primitives)
+ can no longer be submitted to the device.
+**/
+VOID
+VirtioGpuUninit (
+ IN OUT VGPU_DEV *VgpuDev
+ )
+{
+ //
+ // Resetting the VirtIo device makes it release its resources and forget its
+ // configuration.
+ //
+ VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
+ VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
+}
+
+/**
+ Allocate, zero and map memory, for bus master common buffer operation, to be
+ attached as backing store to a host-side VirtIo GPU resource.
+
+ @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
+ device.
+
+ @param[in] NumberOfPages The number of whole pages to allocate and map.
+
+ @param[out] HostAddress The system memory address of the allocated area.
+
+ @param[out] DeviceAddress The bus master device address of the allocated
+ area. The VirtIo GPU device may be programmed to
+ access the allocated area through DeviceAddress;
+ DeviceAddress is to be passed to the
+ VirtioGpuResourceAttachBacking() function, as the
+ BackingStoreDeviceAddress parameter.
+
+ @param[out] Mapping A resulting token to pass to
+ VirtioGpuUnmapAndFreeBackingStore().
+
+ @retval EFI_SUCCESS The requested number of pages has been allocated, zeroed
+ and mapped.
+
+ @return Status codes propagated from
+ VgpuDev->VirtIo->AllocateSharedPages() and
+ VirtioMapAllBytesInSharedBuffer().
+**/
+EFI_STATUS
+VirtioGpuAllocateZeroAndMapBackingStore (
+ IN VGPU_DEV *VgpuDev,
+ IN UINTN NumberOfPages,
+ OUT VOID **HostAddress,
+ OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
+ OUT VOID **Mapping
+ )
+{
+ EFI_STATUS Status;
+ VOID *NewHostAddress;
+
+ Status = VgpuDev->VirtIo->AllocateSharedPages (
+ VgpuDev->VirtIo,
+ NumberOfPages,
+ &NewHostAddress
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Avoid exposing stale data to the device even temporarily: zero the area
+ // before mapping it.
+ //
+ ZeroMem (NewHostAddress, EFI_PAGES_TO_SIZE (NumberOfPages));
+
+ Status = VirtioMapAllBytesInSharedBuffer (
+ VgpuDev->VirtIo, // VirtIo
+ VirtioOperationBusMasterCommonBuffer, // Operation
+ NewHostAddress, // HostAddress
+ EFI_PAGES_TO_SIZE (NumberOfPages), // NumberOfBytes
+ DeviceAddress, // DeviceAddress
+ Mapping // Mapping
+ );
+ if (EFI_ERROR (Status)) {
+ goto FreeSharedPages;
+ }
+
+ *HostAddress = NewHostAddress;
+ return EFI_SUCCESS;
+
+FreeSharedPages:
+ VgpuDev->VirtIo->FreeSharedPages (
+ VgpuDev->VirtIo,
+ NumberOfPages,
+ NewHostAddress
+ );
+ return Status;
+}
+
+/**
+ Unmap and free memory originally allocated and mapped with
+ VirtioGpuAllocateZeroAndMapBackingStore().
+
+ If the memory allocated and mapped with
+ VirtioGpuAllocateZeroAndMapBackingStore() was attached to a host-side VirtIo
+ GPU resource with VirtioGpuResourceAttachBacking(), then the caller is
+ responsible for detaching the backing store from the same resource, with
+ VirtioGpuResourceDetachBacking(), before calling this function.
+
+ @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
+ device.
+
+ @param[in] NumberOfPages The NumberOfPages parameter originally passed to
+ VirtioGpuAllocateZeroAndMapBackingStore().
+
+ @param[in] HostAddress The HostAddress value originally output by
+ VirtioGpuAllocateZeroAndMapBackingStore().
+
+ @param[in] Mapping The token that was originally output by
+ VirtioGpuAllocateZeroAndMapBackingStore().
+**/
+VOID
+VirtioGpuUnmapAndFreeBackingStore (
+ IN VGPU_DEV *VgpuDev,
+ IN UINTN NumberOfPages,
+ IN VOID *HostAddress,
+ IN VOID *Mapping
+ )
+{
+ VgpuDev->VirtIo->UnmapSharedBuffer (
+ VgpuDev->VirtIo,
+ Mapping
+ );
+ VgpuDev->VirtIo->FreeSharedPages (
+ VgpuDev->VirtIo,
+ NumberOfPages,
+ HostAddress
+ );
+}
+
+/**
+ EFI_EVENT_NOTIFY function for the VGPU_DEV.ExitBoot event. It resets the
+ VirtIo device, causing it to release its resources and to forget its
+ configuration.
+
+ This function may only be called (that is, VGPU_DEV.ExitBoot may only be
+ signaled) after VirtioGpuInit() returns and before VirtioGpuUninit() is
+ called.
+
+ @param[in] Event Event whose notification function is being invoked.
+
+ @param[in] Context Pointer to the associated VGPU_DEV object.
+**/
+VOID
+EFIAPI
+VirtioGpuExitBoot (
+ IN EFI_EVENT Event,
+ IN VOID *Context
+ )
+{
+ VGPU_DEV *VgpuDev;
+
+ DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
+ VgpuDev = Context;
+ VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
+}
+
+/**
+ Internal utility function that sends a request to the VirtIo GPU device
+ model, awaits the answer from the host, and returns a status.
+
+ @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
+ device. The caller is responsible to have
+ successfully invoked VirtioGpuInit() on VgpuDev
+ previously, while VirtioGpuUninit() must not have
+ been called on VgpuDev.
+
+ @param[in] RequestType The type of the request. The caller is responsible
+ for providing a VirtioGpuCmd* RequestType which, on
+ success, elicits a VirtioGpuRespOkNodata response
+ from the host.
+
+ @param[in] Fence Whether to enable fencing for this request. Fencing
+ forces the host to complete the command before
+ producing a response. If Fence is TRUE, then
+ VgpuDev->FenceId is consumed, and incremented.
+
+ @param[in,out] Header Pointer to the caller-allocated request object. The
+ request must start with VIRTIO_GPU_CONTROL_HEADER.
+ This function overwrites all fields of Header before
+ submitting the request to the host:
+
+ - it sets Type from RequestType,
+
+ - it sets Flags and FenceId based on Fence,
+
+ - it zeroes CtxId and Padding.
+
+ @param[in] RequestSize Size of the entire caller-allocated request object,
+ including the leading VIRTIO_GPU_CONTROL_HEADER.
+
+ @retval EFI_SUCCESS Operation successful.
+
+ @retval EFI_DEVICE_ERROR The host rejected the request. The host error
+ code has been logged on the DEBUG_ERROR level.
+
+ @return Codes for unexpected errors in VirtIo
+ messaging, or request/response
+ mapping/unmapping.
+**/
+STATIC
+EFI_STATUS
+VirtioGpuSendCommand (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN VIRTIO_GPU_CONTROL_TYPE RequestType,
+ IN BOOLEAN Fence,
+ IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,
+ IN UINTN RequestSize
+ )
+{
+ DESC_INDICES Indices;
+ volatile VIRTIO_GPU_CONTROL_HEADER Response;
+ EFI_STATUS Status;
+ UINT32 ResponseSize;
+ EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
+ VOID *RequestMap;
+ EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;
+ VOID *ResponseMap;
+
+ //
+ // Initialize Header.
+ //
+ Header->Type = RequestType;
+ if (Fence) {
+ Header->Flags = VIRTIO_GPU_FLAG_FENCE;
+ Header->FenceId = VgpuDev->FenceId++;
+ } else {
+ Header->Flags = 0;
+ Header->FenceId = 0;
+ }
+ Header->CtxId = 0;
+ Header->Padding = 0;
+
+ ASSERT (RequestSize >= sizeof *Header);
+ ASSERT (RequestSize <= MAX_UINT32);
+
+ //
+ // Map request and response to bus master device addresses.
+ //
+ Status = VirtioMapAllBytesInSharedBuffer (
+ VgpuDev->VirtIo,
+ VirtioOperationBusMasterRead,
+ (VOID *)Header,
+ RequestSize,
+ &RequestDeviceAddress,
+ &RequestMap
+ );
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+ Status = VirtioMapAllBytesInSharedBuffer (
+ VgpuDev->VirtIo,
+ VirtioOperationBusMasterWrite,
+ (VOID *)&Response,
+ sizeof Response,
+ &ResponseDeviceAddress,
+ &ResponseMap
+ );
+ if (EFI_ERROR (Status)) {
+ goto UnmapRequest;
+ }
+
+ //
+ // Compose the descriptor chain.
+ //
+ VirtioPrepare (&VgpuDev->Ring, &Indices);
+ VirtioAppendDesc (
+ &VgpuDev->Ring,
+ RequestDeviceAddress,
+ (UINT32)RequestSize,
+ VRING_DESC_F_NEXT,
+ &Indices
+ );
+ VirtioAppendDesc (
+ &VgpuDev->Ring,
+ ResponseDeviceAddress,
+ (UINT32)sizeof Response,
+ VRING_DESC_F_WRITE,
+ &Indices
+ );
+
+ //
+ // Send the command.
+ //
+ Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,
+ &VgpuDev->Ring, &Indices, &ResponseSize);
+ if (EFI_ERROR (Status)) {
+ goto UnmapResponse;
+ }
+
+ //
+ // Verify response size.
+ //
+ if (ResponseSize != sizeof Response) {
+ DEBUG ((DEBUG_ERROR, "%a: malformed response to Request=0x%x\n",
+ __FUNCTION__, (UINT32)RequestType));
+ Status = EFI_PROTOCOL_ERROR;
+ goto UnmapResponse;
+ }
+
+ //
+ // Unmap response and request, in reverse order of mapping. On error, the
+ // respective mapping is invalidated anyway, only the data may not have been
+ // committed to system memory (in case of VirtioOperationBusMasterWrite).
+ //
+ Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
+ if (EFI_ERROR (Status)) {
+ goto UnmapRequest;
+ }
+ Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
+ if (EFI_ERROR (Status)) {
+ return Status;
+ }
+
+ //
+ // Parse the response.
+ //
+ if (Response.Type == VirtioGpuRespOkNodata) {
+ return EFI_SUCCESS;
+ }
+
+ DEBUG ((DEBUG_ERROR, "%a: Request=0x%x Response=0x%x\n", __FUNCTION__,
+ (UINT32)RequestType, Response.Type));
+ return EFI_DEVICE_ERROR;
+
+UnmapResponse:
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
+
+UnmapRequest:
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
+
+ return Status;
+}
+
+/**
+ The following functions send requests to the VirtIo GPU device model, await
+ the answer from the host, and return a status. They share the following
+ interface details:
+
+ @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
+ device. The caller is responsible to have
+ successfully invoked VirtioGpuInit() on VgpuDev
+ previously, while VirtioGpuUninit() must not have
+ been called on VgpuDev.
+
+ @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were
+ detected by this driver.
+
+ @retval EFI_SUCCESS Operation successful.
+
+ @retval EFI_DEVICE_ERROR The host rejected the request. The host error
+ code has been logged on the DEBUG_ERROR level.
+
+ @return Codes for unexpected errors in VirtIo
+ messaging.
+
+ For the command-specific parameters, please consult the GPU Device section of
+ the VirtIo 1.0 specification (see references in
+ "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
+**/
+EFI_STATUS
+VirtioGpuResourceCreate2d (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 ResourceId,
+ IN VIRTIO_GPU_FORMATS Format,
+ IN UINT32 Width,
+ IN UINT32 Height
+ )
+{
+ volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.ResourceId = ResourceId;
+ Request.Format = (UINT32)Format;
+ Request.Width = Width;
+ Request.Height = Height;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdResourceCreate2d,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuResourceUnref (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 ResourceId
+ )
+{
+ volatile VIRTIO_GPU_RESOURCE_UNREF Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.ResourceId = ResourceId;
+ Request.Padding = 0;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdResourceUnref,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuResourceAttachBacking (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 ResourceId,
+ IN EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress,
+ IN UINTN NumberOfPages
+ )
+{
+ volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.ResourceId = ResourceId;
+ Request.NrEntries = 1;
+ Request.Entry.Addr = BackingStoreDeviceAddress;
+ Request.Entry.Length = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);
+ Request.Entry.Padding = 0;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdResourceAttachBacking,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuResourceDetachBacking (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 ResourceId
+ )
+{
+ volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.ResourceId = ResourceId;
+ Request.Padding = 0;
+
+ //
+ // In this case, we set Fence to TRUE, because after this function returns,
+ // the caller might reasonably want to repurpose the backing pages
+ // immediately. Thus we should ensure that the host releases all references
+ // to the backing pages before we return.
+ //
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdResourceDetachBacking,
+ TRUE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuSetScanout (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 X,
+ IN UINT32 Y,
+ IN UINT32 Width,
+ IN UINT32 Height,
+ IN UINT32 ScanoutId,
+ IN UINT32 ResourceId
+ )
+{
+ volatile VIRTIO_GPU_SET_SCANOUT Request;
+
+ //
+ // Unlike for most other commands, ResourceId=0 is valid; it
+ // is used to disable a scanout.
+ //
+ Request.Rectangle.X = X;
+ Request.Rectangle.Y = Y;
+ Request.Rectangle.Width = Width;
+ Request.Rectangle.Height = Height;
+ Request.ScanoutId = ScanoutId;
+ Request.ResourceId = ResourceId;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdSetScanout,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuTransferToHost2d (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 X,
+ IN UINT32 Y,
+ IN UINT32 Width,
+ IN UINT32 Height,
+ IN UINT64 Offset,
+ IN UINT32 ResourceId
+ )
+{
+ volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.Rectangle.X = X;
+ Request.Rectangle.Y = Y;
+ Request.Rectangle.Width = Width;
+ Request.Rectangle.Height = Height;
+ Request.Offset = Offset;
+ Request.ResourceId = ResourceId;
+ Request.Padding = 0;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdTransferToHost2d,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}
+
+EFI_STATUS
+VirtioGpuResourceFlush (
+ IN OUT VGPU_DEV *VgpuDev,
+ IN UINT32 X,
+ IN UINT32 Y,
+ IN UINT32 Width,
+ IN UINT32 Height,
+ IN UINT32 ResourceId
+ )
+{
+ volatile VIRTIO_GPU_RESOURCE_FLUSH Request;
+
+ if (ResourceId == 0) {
+ return EFI_INVALID_PARAMETER;
+ }
+
+ Request.Rectangle.X = X;
+ Request.Rectangle.Y = Y;
+ Request.Rectangle.Width = Width;
+ Request.Rectangle.Height = Height;
+ Request.ResourceId = ResourceId;
+ Request.Padding = 0;
+
+ return VirtioGpuSendCommand (
+ VgpuDev,
+ VirtioGpuCmdResourceFlush,
+ FALSE, // Fence
+ &Request.Header,
+ sizeof Request
+ );
+}