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