]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioGpuDxe/Commands.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / VirtioGpuDxe / Commands.c
1 /** @file
2
3 VirtIo GPU initialization, and commands (primitives) for the GPU device.
4
5 Copyright (C) 2016, Red Hat, Inc.
6 Copyright (c) 2017, AMD Inc, All rights reserved.<BR>
7
8 SPDX-License-Identifier: BSD-2-Clause-Patent
9
10 **/
11
12 #include <Library/VirtioLib.h>
13
14 #include "VirtioGpu.h"
15
16 /**
17 Configure the VirtIo GPU device that underlies VgpuDev.
18
19 @param[in,out] VgpuDev The VGPU_DEV object to set up VirtIo messaging for.
20 On input, the caller is responsible for having
21 initialized VgpuDev->VirtIo. On output, VgpuDev->Ring
22 has been initialized, and synchronous VirtIo GPU
23 commands (primitives) can be submitted to the device.
24
25 @retval EFI_SUCCESS VirtIo GPU configuration successful.
26
27 @retval EFI_UNSUPPORTED The host-side configuration of the VirtIo GPU is not
28 supported by this driver.
29
30 @retval Error codes from underlying functions.
31 **/
32 EFI_STATUS
33 VirtioGpuInit (
34 IN OUT VGPU_DEV *VgpuDev
35 )
36 {
37 UINT8 NextDevStat;
38 EFI_STATUS Status;
39 UINT64 Features;
40 UINT16 QueueSize;
41 UINT64 RingBaseShift;
42
43 //
44 // Execute virtio-v1.0-cs04, 3.1.1 Driver Requirements: Device
45 // Initialization.
46 //
47 // 1. Reset the device.
48 //
49 NextDevStat = 0;
50 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
51 if (EFI_ERROR (Status)) {
52 goto Failed;
53 }
54
55 //
56 // 2. Set the ACKNOWLEDGE status bit [...]
57 //
58 NextDevStat |= VSTAT_ACK;
59 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
60 if (EFI_ERROR (Status)) {
61 goto Failed;
62 }
63
64 //
65 // 3. Set the DRIVER status bit [...]
66 //
67 NextDevStat |= VSTAT_DRIVER;
68 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
69 if (EFI_ERROR (Status)) {
70 goto Failed;
71 }
72
73 //
74 // 4. Read device feature bits...
75 //
76 Status = VgpuDev->VirtIo->GetDeviceFeatures (VgpuDev->VirtIo, &Features);
77 if (EFI_ERROR (Status)) {
78 goto Failed;
79 }
80
81 if ((Features & VIRTIO_F_VERSION_1) == 0) {
82 Status = EFI_UNSUPPORTED;
83 goto Failed;
84 }
85
86 //
87 // We only want the most basic 2D features.
88 //
89 Features &= VIRTIO_F_VERSION_1 | VIRTIO_F_IOMMU_PLATFORM;
90
91 //
92 // ... and write the subset of feature bits understood by the [...] driver to
93 // the device. [...]
94 // 5. Set the FEATURES_OK status bit.
95 // 6. Re-read device status to ensure the FEATURES_OK bit is still set [...]
96 //
97 Status = Virtio10WriteFeatures (VgpuDev->VirtIo, Features, &NextDevStat);
98 if (EFI_ERROR (Status)) {
99 goto Failed;
100 }
101
102 //
103 // 7. Perform device-specific setup, including discovery of virtqueues for
104 // the device [...]
105 //
106 Status = VgpuDev->VirtIo->SetQueueSel (
107 VgpuDev->VirtIo,
108 VIRTIO_GPU_CONTROL_QUEUE
109 );
110 if (EFI_ERROR (Status)) {
111 goto Failed;
112 }
113
114 Status = VgpuDev->VirtIo->GetQueueNumMax (VgpuDev->VirtIo, &QueueSize);
115 if (EFI_ERROR (Status)) {
116 goto Failed;
117 }
118
119 //
120 // We implement each VirtIo GPU command that we use with two descriptors:
121 // request, response.
122 //
123 if (QueueSize < 2) {
124 Status = EFI_UNSUPPORTED;
125 goto Failed;
126 }
127
128 //
129 // [...] population of virtqueues [...]
130 //
131 Status = VirtioRingInit (VgpuDev->VirtIo, QueueSize, &VgpuDev->Ring);
132 if (EFI_ERROR (Status)) {
133 goto Failed;
134 }
135
136 //
137 // If anything fails from here on, we have to release the ring.
138 //
139 Status = VirtioRingMap (
140 VgpuDev->VirtIo,
141 &VgpuDev->Ring,
142 &RingBaseShift,
143 &VgpuDev->RingMap
144 );
145 if (EFI_ERROR (Status)) {
146 goto ReleaseQueue;
147 }
148
149 //
150 // If anything fails from here on, we have to unmap the ring.
151 //
152 Status = VgpuDev->VirtIo->SetQueueAddress (
153 VgpuDev->VirtIo,
154 &VgpuDev->Ring,
155 RingBaseShift
156 );
157 if (EFI_ERROR (Status)) {
158 goto UnmapQueue;
159 }
160
161 //
162 // 8. Set the DRIVER_OK status bit.
163 //
164 NextDevStat |= VSTAT_DRIVER_OK;
165 Status = VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
166 if (EFI_ERROR (Status)) {
167 goto UnmapQueue;
168 }
169
170 return EFI_SUCCESS;
171
172 UnmapQueue:
173 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
174
175 ReleaseQueue:
176 VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
177
178 Failed:
179 //
180 // If any of these steps go irrecoverably wrong, the driver SHOULD set the
181 // FAILED status bit to indicate that it has given up on the device (it can
182 // reset the device later to restart if desired). [...]
183 //
184 // VirtIo access failure here should not mask the original error.
185 //
186 NextDevStat |= VSTAT_FAILED;
187 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, NextDevStat);
188
189 return Status;
190 }
191
192 /**
193 De-configure the VirtIo GPU device that underlies VgpuDev.
194
195 @param[in,out] VgpuDev The VGPU_DEV object to tear down VirtIo messaging
196 for. On input, the caller is responsible for having
197 called VirtioGpuInit(). On output, VgpuDev->Ring has
198 been uninitialized; VirtIo GPU commands (primitives)
199 can no longer be submitted to the device.
200 **/
201 VOID
202 VirtioGpuUninit (
203 IN OUT VGPU_DEV *VgpuDev
204 )
205 {
206 //
207 // Resetting the VirtIo device makes it release its resources and forget its
208 // configuration.
209 //
210 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
211 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
212 VirtioRingUninit (VgpuDev->VirtIo, &VgpuDev->Ring);
213 }
214
215 /**
216 Allocate, zero and map memory, for bus master common buffer operation, to be
217 attached as backing store to a host-side VirtIo GPU resource.
218
219 @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
220 device.
221
222 @param[in] NumberOfPages The number of whole pages to allocate and map.
223
224 @param[out] HostAddress The system memory address of the allocated area.
225
226 @param[out] DeviceAddress The bus master device address of the allocated
227 area. The VirtIo GPU device may be programmed to
228 access the allocated area through DeviceAddress;
229 DeviceAddress is to be passed to the
230 VirtioGpuResourceAttachBacking() function, as the
231 BackingStoreDeviceAddress parameter.
232
233 @param[out] Mapping A resulting token to pass to
234 VirtioGpuUnmapAndFreeBackingStore().
235
236 @retval EFI_SUCCESS The requested number of pages has been allocated, zeroed
237 and mapped.
238
239 @return Status codes propagated from
240 VgpuDev->VirtIo->AllocateSharedPages() and
241 VirtioMapAllBytesInSharedBuffer().
242 **/
243 EFI_STATUS
244 VirtioGpuAllocateZeroAndMapBackingStore (
245 IN VGPU_DEV *VgpuDev,
246 IN UINTN NumberOfPages,
247 OUT VOID **HostAddress,
248 OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
249 OUT VOID **Mapping
250 )
251 {
252 EFI_STATUS Status;
253 VOID *NewHostAddress;
254
255 Status = VgpuDev->VirtIo->AllocateSharedPages (
256 VgpuDev->VirtIo,
257 NumberOfPages,
258 &NewHostAddress
259 );
260 if (EFI_ERROR (Status)) {
261 return Status;
262 }
263
264 //
265 // Avoid exposing stale data to the device even temporarily: zero the area
266 // before mapping it.
267 //
268 ZeroMem (NewHostAddress, EFI_PAGES_TO_SIZE (NumberOfPages));
269
270 Status = VirtioMapAllBytesInSharedBuffer (
271 VgpuDev->VirtIo, // VirtIo
272 VirtioOperationBusMasterCommonBuffer, // Operation
273 NewHostAddress, // HostAddress
274 EFI_PAGES_TO_SIZE (NumberOfPages), // NumberOfBytes
275 DeviceAddress, // DeviceAddress
276 Mapping // Mapping
277 );
278 if (EFI_ERROR (Status)) {
279 goto FreeSharedPages;
280 }
281
282 *HostAddress = NewHostAddress;
283 return EFI_SUCCESS;
284
285 FreeSharedPages:
286 VgpuDev->VirtIo->FreeSharedPages (
287 VgpuDev->VirtIo,
288 NumberOfPages,
289 NewHostAddress
290 );
291 return Status;
292 }
293
294 /**
295 Unmap and free memory originally allocated and mapped with
296 VirtioGpuAllocateZeroAndMapBackingStore().
297
298 If the memory allocated and mapped with
299 VirtioGpuAllocateZeroAndMapBackingStore() was attached to a host-side VirtIo
300 GPU resource with VirtioGpuResourceAttachBacking(), then the caller is
301 responsible for detaching the backing store from the same resource, with
302 VirtioGpuResourceDetachBacking(), before calling this function.
303
304 @param[in] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
305 device.
306
307 @param[in] NumberOfPages The NumberOfPages parameter originally passed to
308 VirtioGpuAllocateZeroAndMapBackingStore().
309
310 @param[in] HostAddress The HostAddress value originally output by
311 VirtioGpuAllocateZeroAndMapBackingStore().
312
313 @param[in] Mapping The token that was originally output by
314 VirtioGpuAllocateZeroAndMapBackingStore().
315 **/
316 VOID
317 VirtioGpuUnmapAndFreeBackingStore (
318 IN VGPU_DEV *VgpuDev,
319 IN UINTN NumberOfPages,
320 IN VOID *HostAddress,
321 IN VOID *Mapping
322 )
323 {
324 VgpuDev->VirtIo->UnmapSharedBuffer (
325 VgpuDev->VirtIo,
326 Mapping
327 );
328 VgpuDev->VirtIo->FreeSharedPages (
329 VgpuDev->VirtIo,
330 NumberOfPages,
331 HostAddress
332 );
333 }
334
335 /**
336 EFI_EVENT_NOTIFY function for the VGPU_DEV.ExitBoot event. It resets the
337 VirtIo device, causing it to release its resources and to forget its
338 configuration.
339
340 This function may only be called (that is, VGPU_DEV.ExitBoot may only be
341 signaled) after VirtioGpuInit() returns and before VirtioGpuUninit() is
342 called.
343
344 @param[in] Event Event whose notification function is being invoked.
345
346 @param[in] Context Pointer to the associated VGPU_DEV object.
347 **/
348 VOID
349 EFIAPI
350 VirtioGpuExitBoot (
351 IN EFI_EVENT Event,
352 IN VOID *Context
353 )
354 {
355 VGPU_DEV *VgpuDev;
356
357 DEBUG ((DEBUG_VERBOSE, "%a: Context=0x%p\n", __FUNCTION__, Context));
358 VgpuDev = Context;
359 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
360 }
361
362 /**
363 Internal utility function that sends a request to the VirtIo GPU device
364 model, awaits the answer from the host, and returns a status.
365
366 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
367 device. The caller is responsible to have
368 successfully invoked VirtioGpuInit() on VgpuDev
369 previously, while VirtioGpuUninit() must not have
370 been called on VgpuDev.
371
372 @param[in] RequestType The type of the request. The caller is responsible
373 for providing a VirtioGpuCmd* RequestType which, on
374 success, elicits a VirtioGpuRespOkNodata response
375 from the host.
376
377 @param[in] Fence Whether to enable fencing for this request. Fencing
378 forces the host to complete the command before
379 producing a response. If Fence is TRUE, then
380 VgpuDev->FenceId is consumed, and incremented.
381
382 @param[in,out] Header Pointer to the caller-allocated request object. The
383 request must start with VIRTIO_GPU_CONTROL_HEADER.
384 This function overwrites all fields of Header before
385 submitting the request to the host:
386
387 - it sets Type from RequestType,
388
389 - it sets Flags and FenceId based on Fence,
390
391 - it zeroes CtxId and Padding.
392
393 @param[in] RequestSize Size of the entire caller-allocated request object,
394 including the leading VIRTIO_GPU_CONTROL_HEADER.
395
396 @retval EFI_SUCCESS Operation successful.
397
398 @retval EFI_DEVICE_ERROR The host rejected the request. The host error
399 code has been logged on the DEBUG_ERROR level.
400
401 @return Codes for unexpected errors in VirtIo
402 messaging, or request/response
403 mapping/unmapping.
404 **/
405 STATIC
406 EFI_STATUS
407 VirtioGpuSendCommand (
408 IN OUT VGPU_DEV *VgpuDev,
409 IN VIRTIO_GPU_CONTROL_TYPE RequestType,
410 IN BOOLEAN Fence,
411 IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,
412 IN UINTN RequestSize
413 )
414 {
415 DESC_INDICES Indices;
416 volatile VIRTIO_GPU_CONTROL_HEADER Response;
417 EFI_STATUS Status;
418 UINT32 ResponseSize;
419 EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
420 VOID *RequestMap;
421 EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;
422 VOID *ResponseMap;
423
424 //
425 // Initialize Header.
426 //
427 Header->Type = RequestType;
428 if (Fence) {
429 Header->Flags = VIRTIO_GPU_FLAG_FENCE;
430 Header->FenceId = VgpuDev->FenceId++;
431 } else {
432 Header->Flags = 0;
433 Header->FenceId = 0;
434 }
435
436 Header->CtxId = 0;
437 Header->Padding = 0;
438
439 ASSERT (RequestSize >= sizeof *Header);
440 ASSERT (RequestSize <= MAX_UINT32);
441
442 //
443 // Map request and response to bus master device addresses.
444 //
445 Status = VirtioMapAllBytesInSharedBuffer (
446 VgpuDev->VirtIo,
447 VirtioOperationBusMasterRead,
448 (VOID *)Header,
449 RequestSize,
450 &RequestDeviceAddress,
451 &RequestMap
452 );
453 if (EFI_ERROR (Status)) {
454 return Status;
455 }
456
457 Status = VirtioMapAllBytesInSharedBuffer (
458 VgpuDev->VirtIo,
459 VirtioOperationBusMasterWrite,
460 (VOID *)&Response,
461 sizeof Response,
462 &ResponseDeviceAddress,
463 &ResponseMap
464 );
465 if (EFI_ERROR (Status)) {
466 goto UnmapRequest;
467 }
468
469 //
470 // Compose the descriptor chain.
471 //
472 VirtioPrepare (&VgpuDev->Ring, &Indices);
473 VirtioAppendDesc (
474 &VgpuDev->Ring,
475 RequestDeviceAddress,
476 (UINT32)RequestSize,
477 VRING_DESC_F_NEXT,
478 &Indices
479 );
480 VirtioAppendDesc (
481 &VgpuDev->Ring,
482 ResponseDeviceAddress,
483 (UINT32)sizeof Response,
484 VRING_DESC_F_WRITE,
485 &Indices
486 );
487
488 //
489 // Send the command.
490 //
491 Status = VirtioFlush (
492 VgpuDev->VirtIo,
493 VIRTIO_GPU_CONTROL_QUEUE,
494 &VgpuDev->Ring,
495 &Indices,
496 &ResponseSize
497 );
498 if (EFI_ERROR (Status)) {
499 goto UnmapResponse;
500 }
501
502 //
503 // Verify response size.
504 //
505 if (ResponseSize != sizeof Response) {
506 DEBUG ((
507 DEBUG_ERROR,
508 "%a: malformed response to Request=0x%x\n",
509 __FUNCTION__,
510 (UINT32)RequestType
511 ));
512 Status = EFI_PROTOCOL_ERROR;
513 goto UnmapResponse;
514 }
515
516 //
517 // Unmap response and request, in reverse order of mapping. On error, the
518 // respective mapping is invalidated anyway, only the data may not have been
519 // committed to system memory (in case of VirtioOperationBusMasterWrite).
520 //
521 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
522 if (EFI_ERROR (Status)) {
523 goto UnmapRequest;
524 }
525
526 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
527 if (EFI_ERROR (Status)) {
528 return Status;
529 }
530
531 //
532 // Parse the response.
533 //
534 if (Response.Type == VirtioGpuRespOkNodata) {
535 return EFI_SUCCESS;
536 }
537
538 DEBUG ((
539 DEBUG_ERROR,
540 "%a: Request=0x%x Response=0x%x\n",
541 __FUNCTION__,
542 (UINT32)RequestType,
543 Response.Type
544 ));
545 return EFI_DEVICE_ERROR;
546
547 UnmapResponse:
548 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
549
550 UnmapRequest:
551 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
552
553 return Status;
554 }
555
556 /**
557 The following functions send requests to the VirtIo GPU device model, await
558 the answer from the host, and return a status. They share the following
559 interface details:
560
561 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
562 device. The caller is responsible to have
563 successfully invoked VirtioGpuInit() on VgpuDev
564 previously, while VirtioGpuUninit() must not have
565 been called on VgpuDev.
566
567 @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were
568 detected by this driver.
569
570 @retval EFI_SUCCESS Operation successful.
571
572 @retval EFI_DEVICE_ERROR The host rejected the request. The host error
573 code has been logged on the DEBUG_ERROR level.
574
575 @return Codes for unexpected errors in VirtIo
576 messaging.
577
578 For the command-specific parameters, please consult the GPU Device section of
579 the VirtIo 1.0 specification (see references in
580 "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
581 **/
582 EFI_STATUS
583 VirtioGpuResourceCreate2d (
584 IN OUT VGPU_DEV *VgpuDev,
585 IN UINT32 ResourceId,
586 IN VIRTIO_GPU_FORMATS Format,
587 IN UINT32 Width,
588 IN UINT32 Height
589 )
590 {
591 volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;
592
593 if (ResourceId == 0) {
594 return EFI_INVALID_PARAMETER;
595 }
596
597 Request.ResourceId = ResourceId;
598 Request.Format = (UINT32)Format;
599 Request.Width = Width;
600 Request.Height = Height;
601
602 return VirtioGpuSendCommand (
603 VgpuDev,
604 VirtioGpuCmdResourceCreate2d,
605 FALSE, // Fence
606 &Request.Header,
607 sizeof Request
608 );
609 }
610
611 EFI_STATUS
612 VirtioGpuResourceUnref (
613 IN OUT VGPU_DEV *VgpuDev,
614 IN UINT32 ResourceId
615 )
616 {
617 volatile VIRTIO_GPU_RESOURCE_UNREF Request;
618
619 if (ResourceId == 0) {
620 return EFI_INVALID_PARAMETER;
621 }
622
623 Request.ResourceId = ResourceId;
624 Request.Padding = 0;
625
626 return VirtioGpuSendCommand (
627 VgpuDev,
628 VirtioGpuCmdResourceUnref,
629 FALSE, // Fence
630 &Request.Header,
631 sizeof Request
632 );
633 }
634
635 EFI_STATUS
636 VirtioGpuResourceAttachBacking (
637 IN OUT VGPU_DEV *VgpuDev,
638 IN UINT32 ResourceId,
639 IN EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress,
640 IN UINTN NumberOfPages
641 )
642 {
643 volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;
644
645 if (ResourceId == 0) {
646 return EFI_INVALID_PARAMETER;
647 }
648
649 Request.ResourceId = ResourceId;
650 Request.NrEntries = 1;
651 Request.Entry.Addr = BackingStoreDeviceAddress;
652 Request.Entry.Length = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);
653 Request.Entry.Padding = 0;
654
655 return VirtioGpuSendCommand (
656 VgpuDev,
657 VirtioGpuCmdResourceAttachBacking,
658 FALSE, // Fence
659 &Request.Header,
660 sizeof Request
661 );
662 }
663
664 EFI_STATUS
665 VirtioGpuResourceDetachBacking (
666 IN OUT VGPU_DEV *VgpuDev,
667 IN UINT32 ResourceId
668 )
669 {
670 volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;
671
672 if (ResourceId == 0) {
673 return EFI_INVALID_PARAMETER;
674 }
675
676 Request.ResourceId = ResourceId;
677 Request.Padding = 0;
678
679 //
680 // In this case, we set Fence to TRUE, because after this function returns,
681 // the caller might reasonably want to repurpose the backing pages
682 // immediately. Thus we should ensure that the host releases all references
683 // to the backing pages before we return.
684 //
685 return VirtioGpuSendCommand (
686 VgpuDev,
687 VirtioGpuCmdResourceDetachBacking,
688 TRUE, // Fence
689 &Request.Header,
690 sizeof Request
691 );
692 }
693
694 EFI_STATUS
695 VirtioGpuSetScanout (
696 IN OUT VGPU_DEV *VgpuDev,
697 IN UINT32 X,
698 IN UINT32 Y,
699 IN UINT32 Width,
700 IN UINT32 Height,
701 IN UINT32 ScanoutId,
702 IN UINT32 ResourceId
703 )
704 {
705 volatile VIRTIO_GPU_SET_SCANOUT Request;
706
707 //
708 // Unlike for most other commands, ResourceId=0 is valid; it
709 // is used to disable a scanout.
710 //
711 Request.Rectangle.X = X;
712 Request.Rectangle.Y = Y;
713 Request.Rectangle.Width = Width;
714 Request.Rectangle.Height = Height;
715 Request.ScanoutId = ScanoutId;
716 Request.ResourceId = ResourceId;
717
718 return VirtioGpuSendCommand (
719 VgpuDev,
720 VirtioGpuCmdSetScanout,
721 FALSE, // Fence
722 &Request.Header,
723 sizeof Request
724 );
725 }
726
727 EFI_STATUS
728 VirtioGpuTransferToHost2d (
729 IN OUT VGPU_DEV *VgpuDev,
730 IN UINT32 X,
731 IN UINT32 Y,
732 IN UINT32 Width,
733 IN UINT32 Height,
734 IN UINT64 Offset,
735 IN UINT32 ResourceId
736 )
737 {
738 volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;
739
740 if (ResourceId == 0) {
741 return EFI_INVALID_PARAMETER;
742 }
743
744 Request.Rectangle.X = X;
745 Request.Rectangle.Y = Y;
746 Request.Rectangle.Width = Width;
747 Request.Rectangle.Height = Height;
748 Request.Offset = Offset;
749 Request.ResourceId = ResourceId;
750 Request.Padding = 0;
751
752 return VirtioGpuSendCommand (
753 VgpuDev,
754 VirtioGpuCmdTransferToHost2d,
755 FALSE, // Fence
756 &Request.Header,
757 sizeof Request
758 );
759 }
760
761 EFI_STATUS
762 VirtioGpuResourceFlush (
763 IN OUT VGPU_DEV *VgpuDev,
764 IN UINT32 X,
765 IN UINT32 Y,
766 IN UINT32 Width,
767 IN UINT32 Height,
768 IN UINT32 ResourceId
769 )
770 {
771 volatile VIRTIO_GPU_RESOURCE_FLUSH Request;
772
773 if (ResourceId == 0) {
774 return EFI_INVALID_PARAMETER;
775 }
776
777 Request.Rectangle.X = X;
778 Request.Rectangle.Y = Y;
779 Request.Rectangle.Width = Width;
780 Request.Rectangle.Height = Height;
781 Request.ResourceId = ResourceId;
782 Request.Padding = 0;
783
784 return VirtioGpuSendCommand (
785 VgpuDev,
786 VirtioGpuCmdResourceFlush,
787 FALSE, // Fence
788 &Request.Header,
789 sizeof Request
790 );
791 }