1 /** @file
2 
3   Internal type and macro definitions for the Virtio GPU hybrid driver.
4 
5   Copyright (C) 2016, Red Hat, Inc.
6 
7   SPDX-License-Identifier: BSD-2-Clause-Patent
8 
9 **/
10 
11 #ifndef _VIRTIO_GPU_DXE_H_
12 #define _VIRTIO_GPU_DXE_H_
13 
14 #include <IndustryStandard/VirtioGpu.h>
15 #include <Library/BaseMemoryLib.h>
16 #include <Library/DebugLib.h>
17 #include <Library/UefiLib.h>
18 #include <Protocol/GraphicsOutput.h>
19 #include <Protocol/VirtioDevice.h>
20 
21 //
22 // Forward declaration of VGPU_GOP.
23 //
24 typedef struct VGPU_GOP_STRUCT VGPU_GOP;
25 
26 //
27 // The abstraction that directly corresponds to a Virtio GPU device.
28 //
29 // This structure will be installed on the handle that has the VirtIo Device
30 // Protocol interface, with GUID gEfiCallerIdGuid. A similar trick is employed
31 // in TerminalDxe, and it is necessary so that we can look up VGPU_DEV just
32 // from the VirtIo Device Protocol handle in the Component Name 2 Protocol
33 // implementation.
34 //
35 typedef struct {
36   //
37   // VirtIo represents access to the Virtio GPU device. Never NULL.
38   //
39   VIRTIO_DEVICE_PROTOCOL   *VirtIo;
40 
41   //
42   // BusName carries a customized name for
43   // EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName(). It is expressed in table
44   // form because it can theoretically support several languages. Never NULL.
45   //
46   EFI_UNICODE_STRING_TABLE *BusName;
47 
48   //
49   // VirtIo ring used for VirtIo communication.
50   //
51   VRING                    Ring;
52 
53   //
54   // Token associated with Ring's mapping for bus master common buffer
55   // operation, from VirtioRingMap().
56   //
57   VOID                     *RingMap;
58 
59   //
60   // Event to be signaled at ExitBootServices().
61   //
62   EFI_EVENT                ExitBoot;
63 
64   //
65   // Common running counter for all VirtIo GPU requests that ask for fencing.
66   //
67   UINT64                   FenceId;
68 
69   //
70   // The Child field references the GOP wrapper structure. If this pointer is
71   // NULL, then the hybrid driver has bound (i.e., started) the
72   // VIRTIO_DEVICE_PROTOCOL controller without producing the child GOP
73   // controller (that is, after Start() was called with RemainingDevicePath
74   // pointing to and End of Device Path node). Child can be created and
75   // destroyed, even repeatedly, independently of VGPU_DEV.
76   //
77   // In practice, this field represents the single head (scanout) that we
78   // support.
79   //
80   VGPU_GOP                 *Child;
81 } VGPU_DEV;
82 
83 //
84 // The Graphics Output Protocol wrapper structure.
85 //
86 #define VGPU_GOP_SIG SIGNATURE_64 ('V', 'G', 'P', 'U', '_', 'G', 'O', 'P')
87 
88 struct VGPU_GOP_STRUCT {
89   UINT64                               Signature;
90 
91   //
92   // ParentBus points to the parent VGPU_DEV object. Never NULL.
93   //
94   VGPU_DEV                             *ParentBus;
95 
96   //
97   // GopName carries a customized name for
98   // EFI_COMPONENT_NAME2_PROTOCOL.GetControllerName(). It is expressed in table
99   // form because it can theoretically support several languages. Never NULL.
100   //
101   EFI_UNICODE_STRING_TABLE             *GopName;
102 
103   //
104   // GopHandle is the UEFI child handle that carries the device path ending
105   // with the ACPI ADR node, and the Graphics Output Protocol. Never NULL.
106   //
107   EFI_HANDLE                           GopHandle;
108 
109   //
110   // The GopDevicePath field is the device path installed on GopHandle,
111   // ending with an ACPI ADR node. Never NULL.
112   //
113   EFI_DEVICE_PATH_PROTOCOL             *GopDevicePath;
114 
115   //
116   // The Gop field is installed on the child handle as Graphics Output Protocol
117   // interface.
118   //
119   EFI_GRAPHICS_OUTPUT_PROTOCOL         Gop;
120 
121   //
122   // Referenced by Gop.Mode, GopMode provides a summary about the supported
123   // graphics modes, and the current mode.
124   //
125   EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE    GopMode;
126 
127   //
128   // Referenced by GopMode.Info, GopModeInfo provides detailed information
129   // about the current mode.
130   //
131   EFI_GRAPHICS_OUTPUT_MODE_INFORMATION GopModeInfo;
132 
133   //
134   // Identifier of the 2D host resource that is in use by this head (scanout)
135   // of the VirtIo GPU device. Zero until the first successful -- internal --
136   // Gop.SetMode() call, never zero afterwards.
137   //
138   UINT32                               ResourceId;
139 
140   //
141   // A number of whole pages providing the backing store for the 2D host
142   // resource identified by ResourceId above. NULL until the first successful
143   // -- internal -- Gop.SetMode() call, never NULL afterwards.
144   //
145   UINT32                               *BackingStore;
146   UINTN                                NumberOfPages;
147 
148   //
149   // Token associated with BackingStore's mapping for bus master common
150   // buffer operation. BackingStoreMap is valid if, and only if,
151   // BackingStore is non-NULL.
152   //
153   VOID                                 *BackingStoreMap;
154 };
155 
156 //
157 // VirtIo GPU initialization, and commands (primitives) for the GPU device.
158 //
159 /**
160   Configure the VirtIo GPU device that underlies VgpuDev.
161 
162   @param[in,out] VgpuDev  The VGPU_DEV object to set up VirtIo messaging for.
163                           On input, the caller is responsible for having
164                           initialized VgpuDev->VirtIo. On output, VgpuDev->Ring
165                           has been initialized, and synchronous VirtIo GPU
166                           commands (primitives) can be submitted to the device.
167 
168   @retval EFI_SUCCESS      VirtIo GPU configuration successful.
169 
170   @retval EFI_UNSUPPORTED  The host-side configuration of the VirtIo GPU is not
171                            supported by this driver.
172 
173   @retval                  Error codes from underlying functions.
174 **/
175 EFI_STATUS
176 VirtioGpuInit (
177   IN OUT VGPU_DEV *VgpuDev
178   );
179 
180 /**
181   De-configure the VirtIo GPU device that underlies VgpuDev.
182 
183   @param[in,out] VgpuDev  The VGPU_DEV object to tear down VirtIo messaging
184                           for. On input, the caller is responsible for having
185                           called VirtioGpuInit(). On output, VgpuDev->Ring has
186                           been uninitialized; VirtIo GPU commands (primitives)
187                           can no longer be submitted to the device.
188 **/
189 VOID
190 VirtioGpuUninit (
191   IN OUT VGPU_DEV *VgpuDev
192   );
193 
194 /**
195   Allocate, zero and map memory, for bus master common buffer operation, to be
196   attached as backing store to a host-side VirtIo GPU resource.
197 
198   @param[in]  VgpuDev        The VGPU_DEV object that represents the VirtIo GPU
199                              device.
200 
201   @param[in]  NumberOfPages  The number of whole pages to allocate and map.
202 
203   @param[out] HostAddress    The system memory address of the allocated area.
204 
205   @param[out] DeviceAddress  The bus master device address of the allocated
206                              area. The VirtIo GPU device may be programmed to
207                              access the allocated area through DeviceAddress;
208                              DeviceAddress is to be passed to the
209                              VirtioGpuResourceAttachBacking() function, as the
210                              BackingStoreDeviceAddress parameter.
211 
212   @param[out] Mapping        A resulting token to pass to
213                              VirtioGpuUnmapAndFreeBackingStore().
214 
215   @retval EFI_SUCCESS  The requested number of pages has been allocated, zeroed
216                        and mapped.
217 
218   @return              Status codes propagated from
219                        VgpuDev->VirtIo->AllocateSharedPages() and
220                        VirtioMapAllBytesInSharedBuffer().
221 **/
222 EFI_STATUS
223 VirtioGpuAllocateZeroAndMapBackingStore (
224   IN  VGPU_DEV             *VgpuDev,
225   IN  UINTN                NumberOfPages,
226   OUT VOID                 **HostAddress,
227   OUT EFI_PHYSICAL_ADDRESS *DeviceAddress,
228   OUT VOID                 **Mapping
229   );
230 
231 /**
232   Unmap and free memory originally allocated and mapped with
233   VirtioGpuAllocateZeroAndMapBackingStore().
234 
235   If the memory allocated and mapped with
236   VirtioGpuAllocateZeroAndMapBackingStore() was attached to a host-side VirtIo
237   GPU resource with VirtioGpuResourceAttachBacking(), then the caller is
238   responsible for detaching the backing store from the same resource, with
239   VirtioGpuResourceDetachBacking(), before calling this function.
240 
241   @param[in] VgpuDev        The VGPU_DEV object that represents the VirtIo GPU
242                             device.
243 
244   @param[in] NumberOfPages  The NumberOfPages parameter originally passed to
245                             VirtioGpuAllocateZeroAndMapBackingStore().
246 
247   @param[in] HostAddress    The HostAddress value originally output by
248                             VirtioGpuAllocateZeroAndMapBackingStore().
249 
250   @param[in] Mapping        The token that was originally output by
251                             VirtioGpuAllocateZeroAndMapBackingStore().
252 **/
253 VOID
254 VirtioGpuUnmapAndFreeBackingStore (
255   IN VGPU_DEV *VgpuDev,
256   IN UINTN    NumberOfPages,
257   IN VOID     *HostAddress,
258   IN VOID     *Mapping
259   );
260 
261 /**
262   EFI_EVENT_NOTIFY function for the VGPU_DEV.ExitBoot event. It resets the
263   VirtIo device, causing it to release its resources and to forget its
264   configuration.
265 
266   This function may only be called (that is, VGPU_DEV.ExitBoot may only be
267   signaled) after VirtioGpuInit() returns and before VirtioGpuUninit() is
268   called.
269 
270   @param[in] Event    Event whose notification function is being invoked.
271 
272   @param[in] Context  Pointer to the associated VGPU_DEV object.
273 **/
274 VOID
275 EFIAPI
276 VirtioGpuExitBoot (
277   IN EFI_EVENT Event,
278   IN VOID      *Context
279   );
280 
281 /**
282   The following functions send requests to the VirtIo GPU device model, await
283   the answer from the host, and return a status. They share the following
284   interface details:
285 
286   @param[in,out] VgpuDev  The VGPU_DEV object that represents the VirtIo GPU
287                           device. The caller is responsible to have
288                           successfully invoked VirtioGpuInit() on VgpuDev
289                           previously, while VirtioGpuUninit() must not have
290                           been called on VgpuDev.
291 
292   @retval EFI_INVALID_PARAMETER  Invalid command-specific parameters were
293                                  detected by this driver.
294 
295   @retval EFI_SUCCESS            Operation successful.
296 
297   @retval EFI_DEVICE_ERROR       The host rejected the request. The host error
298                                  code has been logged on the DEBUG_ERROR level.
299 
300   @return                        Codes for unexpected errors in VirtIo
301                                  messaging.
302 
303   For the command-specific parameters, please consult the GPU Device section of
304   the VirtIo 1.0 specification (see references in
305   "OvmfPkg/Include/IndustryStandard/VirtioGpu.h").
306 **/
307 EFI_STATUS
308 VirtioGpuResourceCreate2d (
309   IN OUT VGPU_DEV           *VgpuDev,
310   IN     UINT32             ResourceId,
311   IN     VIRTIO_GPU_FORMATS Format,
312   IN     UINT32             Width,
313   IN     UINT32             Height
314   );
315 
316 EFI_STATUS
317 VirtioGpuResourceUnref (
318   IN OUT VGPU_DEV *VgpuDev,
319   IN     UINT32   ResourceId
320   );
321 
322 EFI_STATUS
323 VirtioGpuResourceAttachBacking (
324   IN OUT VGPU_DEV             *VgpuDev,
325   IN     UINT32               ResourceId,
326   IN     EFI_PHYSICAL_ADDRESS BackingStoreDeviceAddress,
327   IN     UINTN                NumberOfPages
328   );
329 
330 EFI_STATUS
331 VirtioGpuResourceDetachBacking (
332   IN OUT VGPU_DEV *VgpuDev,
333   IN     UINT32   ResourceId
334   );
335 
336 EFI_STATUS
337 VirtioGpuSetScanout (
338   IN OUT VGPU_DEV *VgpuDev,
339   IN     UINT32   X,
340   IN     UINT32   Y,
341   IN     UINT32   Width,
342   IN     UINT32   Height,
343   IN     UINT32   ScanoutId,
344   IN     UINT32   ResourceId
345   );
346 
347 EFI_STATUS
348 VirtioGpuTransferToHost2d (
349   IN OUT VGPU_DEV *VgpuDev,
350   IN     UINT32   X,
351   IN     UINT32   Y,
352   IN     UINT32   Width,
353   IN     UINT32   Height,
354   IN     UINT64   Offset,
355   IN     UINT32   ResourceId
356   );
357 
358 EFI_STATUS
359 VirtioGpuResourceFlush (
360   IN OUT VGPU_DEV *VgpuDev,
361   IN     UINT32   X,
362   IN     UINT32   Y,
363   IN     UINT32   Width,
364   IN     UINT32   Height,
365   IN     UINT32   ResourceId
366   );
367 
368 /**
369   Release guest-side and host-side resources that are related to an initialized
370   VGPU_GOP.Gop.
371 
372   param[in,out] VgpuGop  The VGPU_GOP object to release resources for.
373 
374                          On input, the caller is responsible for having called
375                          VgpuGop->Gop.SetMode() at least once successfully.
376                          (This is equivalent to the requirement that
377                          VgpuGop->BackingStore be non-NULL. It is also
378                          equivalent to the requirement that VgpuGop->ResourceId
379                          be nonzero.)
380 
381                          On output, resources will be released, and
382                          VgpuGop->BackingStore and VgpuGop->ResourceId will be
383                          nulled.
384 
385   param[in] DisableHead  Whether this head (scanout) currently references the
386                          resource identified by VgpuGop->ResourceId. Only pass
387                          FALSE when VgpuGop->Gop.SetMode() calls this function
388                          while switching between modes, and set it to TRUE
389                          every other time.
390 **/
391 VOID
392 ReleaseGopResources (
393   IN OUT VGPU_GOP *VgpuGop,
394   IN     BOOLEAN  DisableHead
395   );
396 
397 //
398 // Template for initializing VGPU_GOP.Gop.
399 //
400 extern CONST EFI_GRAPHICS_OUTPUT_PROTOCOL mGopTemplate;
401 
402 #endif // _VIRTIO_GPU_DXE_H_
403