\r
**/\r
\r
-#include <IndustryStandard/VirtioGpu.h>\r
#include <Library/VirtioLib.h>\r
\r
#include "VirtioGpu.h"\r
VgpuDev = Context;\r
VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);\r
}\r
+\r
+/**\r
+ Internal utility function that sends a request to the VirtIo GPU device\r
+ model, awaits the answer from the host, and returns a status.\r
+\r
+ @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
+ device. The caller is responsible to have\r
+ successfully invoked VirtioGpuInit() on VgpuDev\r
+ previously, while VirtioGpuUninit() must not have\r
+ been called on VgpuDev.\r
+\r
+ @param[in] RequestType The type of the request. The caller is responsible\r
+ for providing a VirtioGpuCmd* RequestType which, on\r
+ success, elicits a VirtioGpuRespOkNodata response\r
+ from the host.\r
+\r
+ @param[in] Fence Whether to enable fencing for this request. Fencing\r
+ forces the host to complete the command before\r
+ producing a response. If Fence is TRUE, then\r
+ VgpuDev->FenceId is consumed, and incremented.\r
+\r
+ @param[in,out] Header Pointer to the caller-allocated request object. The\r
+ request must start with VIRTIO_GPU_CONTROL_HEADER.\r
+ This function overwrites all fields of Header before\r
+ submitting the request to the host:\r
+\r
+ - it sets Type from RequestType,\r
+\r
+ - it sets Flags and FenceId based on Fence,\r
+\r
+ - it zeroes CtxId and Padding.\r
+\r
+ @param[in] RequestSize Size of the entire caller-allocated request object,\r
+ including the leading VIRTIO_GPU_CONTROL_HEADER.\r
+\r
+ @retval EFI_SUCCESS Operation successful.\r
+\r
+ @retval EFI_DEVICE_ERROR The host rejected the request. The host error\r
+ code has been logged on the EFI_D_ERROR level.\r
+\r
+ @return Codes for unexpected errors in VirtIo\r
+ messaging.\r
+**/\r
+STATIC\r
+EFI_STATUS\r
+VirtioGpuSendCommand (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN VIRTIO_GPU_CONTROL_TYPE RequestType,\r
+ IN BOOLEAN Fence,\r
+ IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,\r
+ IN UINTN RequestSize\r
+ )\r
+{\r
+ DESC_INDICES Indices;\r
+ volatile VIRTIO_GPU_CONTROL_HEADER Response;\r
+ EFI_STATUS Status;\r
+ UINT32 ResponseSize;\r
+\r
+ //\r
+ // Initialize Header.\r
+ //\r
+ Header->Type = RequestType;\r
+ if (Fence) {\r
+ Header->Flags = VIRTIO_GPU_FLAG_FENCE;\r
+ Header->FenceId = VgpuDev->FenceId++;\r
+ } else {\r
+ Header->Flags = 0;\r
+ Header->FenceId = 0;\r
+ }\r
+ Header->CtxId = 0;\r
+ Header->Padding = 0;\r
+\r
+ ASSERT (RequestSize >= sizeof *Header);\r
+\r
+ //\r
+ // Compose the descriptor chain.\r
+ //\r
+ VirtioPrepare (&VgpuDev->Ring, &Indices);\r
+ VirtioAppendDesc (&VgpuDev->Ring, (UINTN)Header, RequestSize,\r
+ VRING_DESC_F_NEXT, &Indices);\r
+ VirtioAppendDesc (&VgpuDev->Ring, (UINTN)&Response, sizeof Response,\r
+ VRING_DESC_F_WRITE, &Indices);\r
+\r
+ //\r
+ // Send the command.\r
+ //\r
+ Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,\r
+ &VgpuDev->Ring, &Indices, &ResponseSize);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Parse the response.\r
+ //\r
+ if (ResponseSize != sizeof Response) {\r
+ DEBUG ((EFI_D_ERROR, "%a: malformed response to Request=0x%x\n",\r
+ __FUNCTION__, (UINT32)RequestType));\r
+ return EFI_PROTOCOL_ERROR;\r
+ }\r
+\r
+ if (Response.Type == VirtioGpuRespOkNodata) {\r
+ return EFI_SUCCESS;\r
+ }\r
+\r
+ DEBUG ((EFI_D_ERROR, "%a: Request=0x%x Response=0x%x\n", __FUNCTION__,\r
+ (UINT32)RequestType, Response.Type));\r
+ return EFI_DEVICE_ERROR;\r
+}\r
+\r
+/**\r
+ The following functions send requests to the VirtIo GPU device model, await\r
+ the answer from the host, and return a status. They share the following\r
+ interface details:\r
+\r
+ @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
+ device. The caller is responsible to have\r
+ successfully invoked VirtioGpuInit() on VgpuDev\r
+ previously, while VirtioGpuUninit() must not have\r
+ been called on VgpuDev.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were\r
+ detected by this driver.\r
+\r
+ @retval EFI_SUCCESS Operation successful.\r
+\r
+ @retval EFI_DEVICE_ERROR The host rejected the request. The host error\r
+ code has been logged on the EFI_D_ERROR level.\r
+\r
+ @return Codes for unexpected errors in VirtIo\r
+ messaging.\r
+\r
+ For the command-specific parameters, please consult the GPU Device section of\r
+ the VirtIo 1.0 specification (see references in\r
+ "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").\r
+**/\r
+EFI_STATUS\r
+VirtioGpuResourceCreate2d (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId,\r
+ IN VIRTIO_GPU_FORMATS Format,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.ResourceId = ResourceId;\r
+ Request.Format = (UINT32)Format;\r
+ Request.Width = Width;\r
+ Request.Height = Height;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdResourceCreate2d,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceUnref (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESOURCE_UNREF Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.ResourceId = ResourceId;\r
+ Request.Padding = 0;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdResourceUnref,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceAttachBacking (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId,\r
+ IN VOID *FirstBackingPage,\r
+ IN UINTN NumberOfPages\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.ResourceId = ResourceId;\r
+ Request.NrEntries = 1;\r
+ Request.Entry.Addr = (UINTN)FirstBackingPage;\r
+ Request.Entry.Length = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);\r
+ Request.Entry.Padding = 0;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdResourceAttachBacking,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceDetachBacking (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.ResourceId = ResourceId;\r
+ Request.Padding = 0;\r
+\r
+ //\r
+ // In this case, we set Fence to TRUE, because after this function returns,\r
+ // the caller might reasonably want to repurpose the backing pages\r
+ // immediately. Thus we should ensure that the host releases all references\r
+ // to the backing pages before we return.\r
+ //\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdResourceDetachBacking,\r
+ TRUE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuSetScanout (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT32 ScanoutId,\r
+ IN UINT32 ResourceId\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_SET_SCANOUT Request;\r
+\r
+ //\r
+ // Unlike for most other commands, ResourceId=0 is valid; it\r
+ // is used to disable a scanout.\r
+ //\r
+ Request.Rectangle.X = X;\r
+ Request.Rectangle.Y = Y;\r
+ Request.Rectangle.Width = Width;\r
+ Request.Rectangle.Height = Height;\r
+ Request.ScanoutId = ScanoutId;\r
+ Request.ResourceId = ResourceId;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdSetScanout,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuTransferToHost2d (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT64 Offset,\r
+ IN UINT32 ResourceId\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.Rectangle.X = X;\r
+ Request.Rectangle.Y = Y;\r
+ Request.Rectangle.Width = Width;\r
+ Request.Rectangle.Height = Height;\r
+ Request.Offset = Offset;\r
+ Request.ResourceId = ResourceId;\r
+ Request.Padding = 0;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdTransferToHost2d,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceFlush (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT32 ResourceId\r
+ )\r
+{\r
+ volatile VIRTIO_GPU_RESOURCE_FLUSH Request;\r
+\r
+ if (ResourceId == 0) {\r
+ return EFI_INVALID_PARAMETER;\r
+ }\r
+\r
+ Request.Rectangle.X = X;\r
+ Request.Rectangle.Y = Y;\r
+ Request.Rectangle.Width = Width;\r
+ Request.Rectangle.Height = Height;\r
+ Request.ResourceId = ResourceId;\r
+ Request.Padding = 0;\r
+\r
+ return VirtioGpuSendCommand (\r
+ VgpuDev,\r
+ VirtioGpuCmdResourceFlush,\r
+ FALSE, // Fence\r
+ &Request.Header,\r
+ sizeof Request\r
+ );\r
+}\r
#ifndef _VIRTIO_GPU_DXE_H_\r
#define _VIRTIO_GPU_DXE_H_\r
\r
+#include <IndustryStandard/VirtioGpu.h>\r
#include <Library/DebugLib.h>\r
#include <Library/UefiLib.h>\r
#include <Protocol/VirtioDevice.h>\r
//\r
EFI_EVENT ExitBoot;\r
\r
+ //\r
+ // Common running counter for all VirtIo GPU requests that ask for fencing.\r
+ //\r
+ UINT64 FenceId;\r
+\r
//\r
// The Child field references the GOP wrapper structure. If this pointer is\r
// NULL, then the hybrid driver has bound (i.e., started) the\r
IN VOID *Context\r
);\r
\r
+/**\r
+ The following functions send requests to the VirtIo GPU device model, await\r
+ the answer from the host, and return a status. They share the following\r
+ interface details:\r
+\r
+ @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU\r
+ device. The caller is responsible to have\r
+ successfully invoked VirtioGpuInit() on VgpuDev\r
+ previously, while VirtioGpuUninit() must not have\r
+ been called on VgpuDev.\r
+\r
+ @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were\r
+ detected by this driver.\r
+\r
+ @retval EFI_SUCCESS Operation successful.\r
+\r
+ @retval EFI_DEVICE_ERROR The host rejected the request. The host error\r
+ code has been logged on the EFI_D_ERROR level.\r
+\r
+ @return Codes for unexpected errors in VirtIo\r
+ messaging.\r
+\r
+ For the command-specific parameters, please consult the GPU Device section of\r
+ the VirtIo 1.0 specification (see references in\r
+ "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").\r
+**/\r
+EFI_STATUS\r
+VirtioGpuResourceCreate2d (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId,\r
+ IN VIRTIO_GPU_FORMATS Format,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceUnref (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceAttachBacking (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId,\r
+ IN VOID *FirstBackingPage,\r
+ IN UINTN NumberOfPages\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceDetachBacking (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 ResourceId\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuSetScanout (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT32 ScanoutId,\r
+ IN UINT32 ResourceId\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuTransferToHost2d (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT64 Offset,\r
+ IN UINT32 ResourceId\r
+ );\r
+\r
+EFI_STATUS\r
+VirtioGpuResourceFlush (\r
+ IN OUT VGPU_DEV *VgpuDev,\r
+ IN UINT32 X,\r
+ IN UINT32 Y,\r
+ IN UINT32 Width,\r
+ IN UINT32 Height,\r
+ IN UINT32 ResourceId\r
+ );\r
+\r
#endif // _VIRTIO_GPU_DXE_H_\r