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