code has been logged on the EFI_D_ERROR level.\r
\r
@return Codes for unexpected errors in VirtIo\r
- messaging.\r
+ messaging, or request/response\r
+ mapping/unmapping.\r
**/\r
STATIC\r
EFI_STATUS\r
volatile VIRTIO_GPU_CONTROL_HEADER Response;\r
EFI_STATUS Status;\r
UINT32 ResponseSize;\r
+ EFI_PHYSICAL_ADDRESS RequestDeviceAddress;\r
+ VOID *RequestMap;\r
+ EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;\r
+ VOID *ResponseMap;\r
\r
//\r
// Initialize Header.\r
ASSERT (RequestSize >= sizeof *Header);\r
ASSERT (RequestSize <= MAX_UINT32);\r
\r
+ //\r
+ // Map request and response to bus master device addresses.\r
+ //\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ VgpuDev->VirtIo,\r
+ VirtioOperationBusMasterRead,\r
+ (VOID *)Header,\r
+ RequestSize,\r
+ &RequestDeviceAddress,\r
+ &RequestMap\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+ Status = VirtioMapAllBytesInSharedBuffer (\r
+ VgpuDev->VirtIo,\r
+ VirtioOperationBusMasterWrite,\r
+ (VOID *)&Response,\r
+ sizeof Response,\r
+ &ResponseDeviceAddress,\r
+ &ResponseMap\r
+ );\r
+ if (EFI_ERROR (Status)) {\r
+ goto UnmapRequest;\r
+ }\r
+\r
//\r
// Compose the descriptor chain.\r
//\r
VirtioPrepare (&VgpuDev->Ring, &Indices);\r
- VirtioAppendDesc (&VgpuDev->Ring, (UINTN)Header, (UINT32)RequestSize,\r
- VRING_DESC_F_NEXT, &Indices);\r
- VirtioAppendDesc (&VgpuDev->Ring, (UINTN)&Response, sizeof Response,\r
- VRING_DESC_F_WRITE, &Indices);\r
+ VirtioAppendDesc (\r
+ &VgpuDev->Ring,\r
+ RequestDeviceAddress,\r
+ (UINT32)RequestSize,\r
+ VRING_DESC_F_NEXT,\r
+ &Indices\r
+ );\r
+ VirtioAppendDesc (\r
+ &VgpuDev->Ring,\r
+ ResponseDeviceAddress,\r
+ (UINT32)sizeof Response,\r
+ VRING_DESC_F_WRITE,\r
+ &Indices\r
+ );\r
\r
//\r
// Send the command.\r
Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,\r
&VgpuDev->Ring, &Indices, &ResponseSize);\r
if (EFI_ERROR (Status)) {\r
- return Status;\r
+ goto UnmapResponse;\r
}\r
\r
//\r
- // Parse the response.\r
+ // Verify response size.\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
+ Status = EFI_PROTOCOL_ERROR;\r
+ goto UnmapResponse;\r
}\r
\r
+ //\r
+ // Unmap response and request, in reverse order of mapping. On error, the\r
+ // respective mapping is invalidated anyway, only the data may not have been\r
+ // committed to system memory (in case of VirtioOperationBusMasterWrite).\r
+ //\r
+ Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);\r
+ if (EFI_ERROR (Status)) {\r
+ goto UnmapRequest;\r
+ }\r
+ Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);\r
+ if (EFI_ERROR (Status)) {\r
+ return Status;\r
+ }\r
+\r
+ //\r
+ // Parse the response.\r
+ //\r
if (Response.Type == VirtioGpuRespOkNodata) {\r
return EFI_SUCCESS;\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
+UnmapResponse:\r
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);\r
+\r
+UnmapRequest:\r
+ VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);\r
+\r
+ return Status;\r
}\r
\r
/**\r