]> git.proxmox.com Git - mirror_edk2.git/blob - OvmfPkg/VirtioGpuDxe/Commands.c
6e70b1c33f6508a800107578dc33dcaf8cb3d53c
[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 VgpuDev = Context;
357 VgpuDev->VirtIo->SetDeviceStatus (VgpuDev->VirtIo, 0);
358
359 //
360 // If VirtioGpuDriverBindingStart() and VirtioGpuDriverBindingStop() have
361 // been called thus far in such a sequence that right now our (sole) child
362 // handle exists -- with the GOP on it standing for head (scanout) #0 --,
363 // then we have to unmap the current video mode's backing store.
364 //
365 if (VgpuDev->Child != NULL) {
366 //
367 // The current video mode is guaranteed to have a valid and mapped backing
368 // store, due to the first Gop.SetMode() call, made internally in
369 // InitVgpuGop().
370 //
371 ASSERT (VgpuDev->Child->BackingStore != NULL);
372
373 VgpuDev->VirtIo->UnmapSharedBuffer (
374 VgpuDev->VirtIo,
375 VgpuDev->Child->BackingStoreMap
376 );
377 }
378
379 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, VgpuDev->RingMap);
380 }
381
382 /**
383 Internal utility function that sends a request to the VirtIo GPU device
384 model, awaits the answer from the host, and returns a status.
385
386 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
387 device. The caller is responsible to have
388 successfully invoked VirtioGpuInit() on VgpuDev
389 previously, while VirtioGpuUninit() must not have
390 been called on VgpuDev.
391
392 @param[in] RequestType The type of the request. The caller is responsible
393 for providing a VirtioGpuCmd* RequestType which, on
394 success, elicits a VirtioGpuRespOkNodata response
395 from the host.
396
397 @param[in] Fence Whether to enable fencing for this request. Fencing
398 forces the host to complete the command before
399 producing a response. If Fence is TRUE, then
400 VgpuDev->FenceId is consumed, and incremented.
401
402 @param[in,out] Header Pointer to the caller-allocated request object. The
403 request must start with VIRTIO_GPU_CONTROL_HEADER.
404 This function overwrites all fields of Header before
405 submitting the request to the host:
406
407 - it sets Type from RequestType,
408
409 - it sets Flags and FenceId based on Fence,
410
411 - it zeroes CtxId and Padding.
412
413 @param[in] RequestSize Size of the entire caller-allocated request object,
414 including the leading VIRTIO_GPU_CONTROL_HEADER.
415
416 @retval EFI_SUCCESS Operation successful.
417
418 @retval EFI_DEVICE_ERROR The host rejected the request. The host error
419 code has been logged on the EFI_D_ERROR level.
420
421 @return Codes for unexpected errors in VirtIo
422 messaging, or request/response
423 mapping/unmapping.
424 **/
425 STATIC
426 EFI_STATUS
427 VirtioGpuSendCommand (
428 IN OUT VGPU_DEV *VgpuDev,
429 IN VIRTIO_GPU_CONTROL_TYPE RequestType,
430 IN BOOLEAN Fence,
431 IN OUT volatile VIRTIO_GPU_CONTROL_HEADER *Header,
432 IN UINTN RequestSize
433 )
434 {
435 DESC_INDICES Indices;
436 volatile VIRTIO_GPU_CONTROL_HEADER Response;
437 EFI_STATUS Status;
438 UINT32 ResponseSize;
439 EFI_PHYSICAL_ADDRESS RequestDeviceAddress;
440 VOID *RequestMap;
441 EFI_PHYSICAL_ADDRESS ResponseDeviceAddress;
442 VOID *ResponseMap;
443
444 //
445 // Initialize Header.
446 //
447 Header->Type = RequestType;
448 if (Fence) {
449 Header->Flags = VIRTIO_GPU_FLAG_FENCE;
450 Header->FenceId = VgpuDev->FenceId++;
451 } else {
452 Header->Flags = 0;
453 Header->FenceId = 0;
454 }
455 Header->CtxId = 0;
456 Header->Padding = 0;
457
458 ASSERT (RequestSize >= sizeof *Header);
459 ASSERT (RequestSize <= MAX_UINT32);
460
461 //
462 // Map request and response to bus master device addresses.
463 //
464 Status = VirtioMapAllBytesInSharedBuffer (
465 VgpuDev->VirtIo,
466 VirtioOperationBusMasterRead,
467 (VOID *)Header,
468 RequestSize,
469 &RequestDeviceAddress,
470 &RequestMap
471 );
472 if (EFI_ERROR (Status)) {
473 return Status;
474 }
475 Status = VirtioMapAllBytesInSharedBuffer (
476 VgpuDev->VirtIo,
477 VirtioOperationBusMasterWrite,
478 (VOID *)&Response,
479 sizeof Response,
480 &ResponseDeviceAddress,
481 &ResponseMap
482 );
483 if (EFI_ERROR (Status)) {
484 goto UnmapRequest;
485 }
486
487 //
488 // Compose the descriptor chain.
489 //
490 VirtioPrepare (&VgpuDev->Ring, &Indices);
491 VirtioAppendDesc (
492 &VgpuDev->Ring,
493 RequestDeviceAddress,
494 (UINT32)RequestSize,
495 VRING_DESC_F_NEXT,
496 &Indices
497 );
498 VirtioAppendDesc (
499 &VgpuDev->Ring,
500 ResponseDeviceAddress,
501 (UINT32)sizeof Response,
502 VRING_DESC_F_WRITE,
503 &Indices
504 );
505
506 //
507 // Send the command.
508 //
509 Status = VirtioFlush (VgpuDev->VirtIo, VIRTIO_GPU_CONTROL_QUEUE,
510 &VgpuDev->Ring, &Indices, &ResponseSize);
511 if (EFI_ERROR (Status)) {
512 goto UnmapResponse;
513 }
514
515 //
516 // Verify response size.
517 //
518 if (ResponseSize != sizeof Response) {
519 DEBUG ((EFI_D_ERROR, "%a: malformed response to Request=0x%x\n",
520 __FUNCTION__, (UINT32)RequestType));
521 Status = EFI_PROTOCOL_ERROR;
522 goto UnmapResponse;
523 }
524
525 //
526 // Unmap response and request, in reverse order of mapping. On error, the
527 // respective mapping is invalidated anyway, only the data may not have been
528 // committed to system memory (in case of VirtioOperationBusMasterWrite).
529 //
530 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
531 if (EFI_ERROR (Status)) {
532 goto UnmapRequest;
533 }
534 Status = VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
535 if (EFI_ERROR (Status)) {
536 return Status;
537 }
538
539 //
540 // Parse the response.
541 //
542 if (Response.Type == VirtioGpuRespOkNodata) {
543 return EFI_SUCCESS;
544 }
545
546 DEBUG ((EFI_D_ERROR, "%a: Request=0x%x Response=0x%x\n", __FUNCTION__,
547 (UINT32)RequestType, Response.Type));
548 return EFI_DEVICE_ERROR;
549
550 UnmapResponse:
551 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, ResponseMap);
552
553 UnmapRequest:
554 VgpuDev->VirtIo->UnmapSharedBuffer (VgpuDev->VirtIo, RequestMap);
555
556 return Status;
557 }
558
559 /**
560 The following functions send requests to the VirtIo GPU device model, await
561 the answer from the host, and return a status. They share the following
562 interface details:
563
564 @param[in,out] VgpuDev The VGPU_DEV object that represents the VirtIo GPU
565 device. The caller is responsible to have
566 successfully invoked VirtioGpuInit() on VgpuDev
567 previously, while VirtioGpuUninit() must not have
568 been called on VgpuDev.
569
570 @retval EFI_INVALID_PARAMETER Invalid command-specific parameters were
571 detected by this driver.
572
573 @retval EFI_SUCCESS Operation successful.
574
575 @retval EFI_DEVICE_ERROR The host rejected the request. The host error
576 code has been logged on the EFI_D_ERROR level.
577
578 @return Codes for unexpected errors in VirtIo
579 messaging.
580
581 For the command-specific parameters, please consult the GPU Device section of
582 the VirtIo 1.0 specification (see references in
583 "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
584 **/
585 EFI_STATUS
586 VirtioGpuResourceCreate2d (
587 IN OUT VGPU_DEV *VgpuDev,
588 IN UINT32 ResourceId,
589 IN VIRTIO_GPU_FORMATS Format,
590 IN UINT32 Width,
591 IN UINT32 Height
592 )
593 {
594 volatile VIRTIO_GPU_RESOURCE_CREATE_2D Request;
595
596 if (ResourceId == 0) {
597 return EFI_INVALID_PARAMETER;
598 }
599
600 Request.ResourceId = ResourceId;
601 Request.Format = (UINT32)Format;
602 Request.Width = Width;
603 Request.Height = Height;
604
605 return VirtioGpuSendCommand (
606 VgpuDev,
607 VirtioGpuCmdResourceCreate2d,
608 FALSE, // Fence
609 &Request.Header,
610 sizeof Request
611 );
612 }
613
614 EFI_STATUS
615 VirtioGpuResourceUnref (
616 IN OUT VGPU_DEV *VgpuDev,
617 IN UINT32 ResourceId
618 )
619 {
620 volatile VIRTIO_GPU_RESOURCE_UNREF Request;
621
622 if (ResourceId == 0) {
623 return EFI_INVALID_PARAMETER;
624 }
625
626 Request.ResourceId = ResourceId;
627 Request.Padding = 0;
628
629 return VirtioGpuSendCommand (
630 VgpuDev,
631 VirtioGpuCmdResourceUnref,
632 FALSE, // Fence
633 &Request.Header,
634 sizeof Request
635 );
636 }
637
638 EFI_STATUS
639 VirtioGpuResourceAttachBacking (
640 IN OUT VGPU_DEV *VgpuDev,
641 IN UINT32 ResourceId,
642 IN EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress,
643 IN UINTN NumberOfPages
644 )
645 {
646 volatile VIRTIO_GPU_RESOURCE_ATTACH_BACKING Request;
647
648 if (ResourceId == 0) {
649 return EFI_INVALID_PARAMETER;
650 }
651
652 Request.ResourceId = ResourceId;
653 Request.NrEntries = 1;
654 Request.Entry.Addr = BackingStoreDeviceAddress;
655 Request.Entry.Length = (UINT32)EFI_PAGES_TO_SIZE (NumberOfPages);
656 Request.Entry.Padding = 0;
657
658 return VirtioGpuSendCommand (
659 VgpuDev,
660 VirtioGpuCmdResourceAttachBacking,
661 FALSE, // Fence
662 &Request.Header,
663 sizeof Request
664 );
665 }
666
667 EFI_STATUS
668 VirtioGpuResourceDetachBacking (
669 IN OUT VGPU_DEV *VgpuDev,
670 IN UINT32 ResourceId
671 )
672 {
673 volatile VIRTIO_GPU_RESOURCE_DETACH_BACKING Request;
674
675 if (ResourceId == 0) {
676 return EFI_INVALID_PARAMETER;
677 }
678
679 Request.ResourceId = ResourceId;
680 Request.Padding = 0;
681
682 //
683 // In this case, we set Fence to TRUE, because after this function returns,
684 // the caller might reasonably want to repurpose the backing pages
685 // immediately. Thus we should ensure that the host releases all references
686 // to the backing pages before we return.
687 //
688 return VirtioGpuSendCommand (
689 VgpuDev,
690 VirtioGpuCmdResourceDetachBacking,
691 TRUE, // Fence
692 &Request.Header,
693 sizeof Request
694 );
695 }
696
697 EFI_STATUS
698 VirtioGpuSetScanout (
699 IN OUT VGPU_DEV *VgpuDev,
700 IN UINT32 X,
701 IN UINT32 Y,
702 IN UINT32 Width,
703 IN UINT32 Height,
704 IN UINT32 ScanoutId,
705 IN UINT32 ResourceId
706 )
707 {
708 volatile VIRTIO_GPU_SET_SCANOUT Request;
709
710 //
711 // Unlike for most other commands, ResourceId=0 is valid; it
712 // is used to disable a scanout.
713 //
714 Request.Rectangle.X = X;
715 Request.Rectangle.Y = Y;
716 Request.Rectangle.Width = Width;
717 Request.Rectangle.Height = Height;
718 Request.ScanoutId = ScanoutId;
719 Request.ResourceId = ResourceId;
720
721 return VirtioGpuSendCommand (
722 VgpuDev,
723 VirtioGpuCmdSetScanout,
724 FALSE, // Fence
725 &Request.Header,
726 sizeof Request
727 );
728 }
729
730 EFI_STATUS
731 VirtioGpuTransferToHost2d (
732 IN OUT VGPU_DEV *VgpuDev,
733 IN UINT32 X,
734 IN UINT32 Y,
735 IN UINT32 Width,
736 IN UINT32 Height,
737 IN UINT64 Offset,
738 IN UINT32 ResourceId
739 )
740 {
741 volatile VIRTIO_GPU_CMD_TRANSFER_TO_HOST_2D Request;
742
743 if (ResourceId == 0) {
744 return EFI_INVALID_PARAMETER;
745 }
746
747 Request.Rectangle.X = X;
748 Request.Rectangle.Y = Y;
749 Request.Rectangle.Width = Width;
750 Request.Rectangle.Height = Height;
751 Request.Offset = Offset;
752 Request.ResourceId = ResourceId;
753 Request.Padding = 0;
754
755 return VirtioGpuSendCommand (
756 VgpuDev,
757 VirtioGpuCmdTransferToHost2d,
758 FALSE, // Fence
759 &Request.Header,
760 sizeof Request
761 );
762 }
763
764 EFI_STATUS
765 VirtioGpuResourceFlush (
766 IN OUT VGPU_DEV *VgpuDev,
767 IN UINT32 X,
768 IN UINT32 Y,
769 IN UINT32 Width,
770 IN UINT32 Height,
771 IN UINT32 ResourceId
772 )
773 {
774 volatile VIRTIO_GPU_RESOURCE_FLUSH Request;
775
776 if (ResourceId == 0) {
777 return EFI_INVALID_PARAMETER;
778 }
779
780 Request.Rectangle.X = X;
781 Request.Rectangle.Y = Y;
782 Request.Rectangle.Width = Width;
783 Request.Rectangle.Height = Height;
784 Request.ResourceId = ResourceId;
785 Request.Padding = 0;
786
787 return VirtioGpuSendCommand (
788 VgpuDev,
789 VirtioGpuCmdResourceFlush,
790 FALSE, // Fence
791 &Request.Header,
792 sizeof Request
793 );
794 }