]> git.proxmox.com Git - mirror_edk2.git/blame - OvmfPkg/Bhyve/BhyveRfbDxe/GopDriver.c
OvmfPkg: Apply uncrustify changes
[mirror_edk2.git] / OvmfPkg / Bhyve / BhyveRfbDxe / GopDriver.c
CommitLineData
656419f9
RC
1/*++ @file\r
2\r
3Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>\r
4Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>\r
5Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>\r
6\r
7SPDX-License-Identifier: BSD-2-Clause-Patent\r
8\r
9**/\r
10\r
11#include "Gop.h"\r
12#include <IndustryStandard/Acpi.h>\r
13\r
14STATIC VOID\r
15BhyveGetGraphicsMode (\r
ac0a286f
MK
16 EFI_PCI_IO_PROTOCOL *PciIo,\r
17 UINT16 *Width,\r
18 UINT16 *Height,\r
19 UINT16 *Depth\r
656419f9
RC
20 );\r
21\r
656419f9
RC
22/**\r
23 Tests to see if this driver supports a given controller. If a child device is provided,\r
24 it further tests to see if this driver supports creating a handle for the specified child device.\r
25\r
26 This function checks to see if the driver specified by This supports the device specified by\r
27 ControllerHandle. Drivers will typically use the device path attached to\r
28 ControllerHandle and/or the services from the bus I/O abstraction attached to\r
29 ControllerHandle to determine if the driver supports ControllerHandle. This function\r
30 may be called many times during platform initialization. In order to reduce boot times, the tests\r
31 performed by this function must be very small, and take as little time as possible to execute. This\r
32 function must not change the state of any hardware devices, and this function must be aware that the\r
33 device specified by ControllerHandle may already be managed by the same driver or a\r
34 different driver. This function must match its calls to AllocatePages() with FreePages(),\r
35 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().\r
36 Because ControllerHandle may have been previously started by the same driver, if a protocol is\r
37 already in the opened state, then it must not be closed with CloseProtocol(). This is required\r
38 to guarantee the state of ControllerHandle is not modified by this function.\r
39\r
40 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
41 @param[in] ControllerHandle The handle of the controller to test. This handle\r
42 must support a protocol interface that supplies\r
43 an I/O abstraction to the driver.\r
44 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
45 parameter is ignored by device drivers, and is optional for bus\r
46 drivers. For bus drivers, if this parameter is not NULL, then\r
47 the bus driver must determine if the bus controller specified\r
48 by ControllerHandle and the child controller specified\r
49 by RemainingDevicePath are both supported by this\r
50 bus driver.\r
51\r
52 @retval EFI_SUCCESS The device specified by ControllerHandle and\r
53 RemainingDevicePath is supported by the driver specified by This.\r
54 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and\r
55 RemainingDevicePath is already being managed by the driver\r
56 specified by This.\r
57 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and\r
58 RemainingDevicePath is already being managed by a different\r
59 driver or an application that requires exclusive access.\r
60 Currently not implemented.\r
61 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and\r
62 RemainingDevicePath is not supported by the driver specified by This.\r
63**/\r
64EFI_STATUS\r
65EFIAPI\r
66EmuGopDriverBindingSupported (\r
ac0a286f
MK
67 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
68 IN EFI_HANDLE Handle,\r
69 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
656419f9
RC
70 )\r
71{\r
ac0a286f
MK
72 EFI_STATUS Status;\r
73 EFI_PCI_IO_PROTOCOL *PciIo;\r
74 PCI_TYPE00 Pci;\r
75 UINT16 Width, Height, Depth;\r
656419f9
RC
76\r
77 //\r
78 // Open the IO Abstraction(s) needed to perform the supported test\r
79 //\r
80 Status = gBS->OpenProtocol (\r
81 Handle,\r
82 &gEfiPciIoProtocolGuid,\r
ac0a286f 83 (VOID **)&PciIo,\r
656419f9
RC
84 This->DriverBindingHandle,\r
85 Handle,\r
86 EFI_OPEN_PROTOCOL_BY_DRIVER\r
87 );\r
88 if (EFI_ERROR (Status)) {\r
89 return Status;\r
90 }\r
91\r
92 //\r
93 // See if this is a PCI Framebuffer Controller by looking at the Command register and\r
94 // Class Code Register\r
95 //\r
96 Status = PciIo->Pci.Read (\r
97 PciIo,\r
98 EfiPciIoWidthUint32,\r
99 PCI_BAR_IDX0,\r
100 sizeof (Pci) / sizeof (UINT32),\r
101 &Pci\r
102 );\r
103 if (EFI_ERROR (Status)) {\r
104 Status = EFI_UNSUPPORTED;\r
105 goto Done;\r
106 }\r
107\r
108 Status = EFI_UNSUPPORTED;\r
ac0a286f
MK
109 if ((Pci.Hdr.VendorId == 0xFB5D) && (Pci.Hdr.DeviceId == 0x40FB)) {\r
110 DEBUG ((DEBUG_INFO, "BHYVE framebuffer device detected\n"));\r
656419f9
RC
111 Status = EFI_SUCCESS;\r
112\r
ac0a286f 113 BhyveGetGraphicsMode (PciIo, &Width, &Height, &Depth);\r
656419f9
RC
114 PcdSet32S (PcdVideoHorizontalResolution, Width);\r
115 PcdSet32S (PcdVideoVerticalResolution, Height);\r
116 }\r
117\r
118Done:\r
119 //\r
120 // Close the PCI I/O Protocol\r
121 //\r
122 gBS->CloseProtocol (\r
ac0a286f
MK
123 Handle,\r
124 &gEfiPciIoProtocolGuid,\r
125 This->DriverBindingHandle,\r
126 Handle\r
127 );\r
656419f9
RC
128\r
129 return Status;\r
130}\r
131\r
656419f9
RC
132/**\r
133 Starts a device controller or a bus controller.\r
134\r
135 The Start() function is designed to be invoked from the EFI boot service ConnectController().\r
136 As a result, much of the error checking on the parameters to Start() has been moved into this\r
137 common boot service. It is legal to call Start() from other locations,\r
138 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
139 1. ControllerHandle must be a valid EFI_HANDLE.\r
140 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned\r
141 EFI_DEVICE_PATH_PROTOCOL.\r
142 3. Prior to calling Start(), the Supported() function for the driver specified by This must\r
143 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.\r
144\r
145 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
146 @param[in] ControllerHandle The handle of the controller to start. This handle\r
147 must support a protocol interface that supplies\r
148 an I/O abstraction to the driver.\r
149 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This\r
150 parameter is ignored by device drivers, and is optional for bus\r
151 drivers. For a bus driver, if this parameter is NULL, then handles\r
152 for all the children of Controller are created by this driver.\r
153 If this parameter is not NULL and the first Device Path Node is\r
154 not the End of Device Path Node, then only the handle for the\r
155 child device specified by the first Device Path Node of\r
156 RemainingDevicePath is created by this driver.\r
157 If the first Device Path Node of RemainingDevicePath is\r
158 the End of Device Path Node, no child handle is created by this\r
159 driver.\r
160\r
161 @retval EFI_SUCCESS The device was started.\r
162 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.\r
163 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.\r
164 @retval Others The driver failded to start the device.\r
165\r
166**/\r
167EFI_STATUS\r
168EFIAPI\r
169EmuGopDriverBindingStart (\r
ac0a286f
MK
170 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
171 IN EFI_HANDLE Handle,\r
172 IN EFI_DEVICE_PATH_PROTOCOL *RemainingDevicePath\r
656419f9
RC
173 )\r
174{\r
ac0a286f
MK
175 BHYVE_FBUF_MEMREGS Memregs;\r
176 GOP_PRIVATE_DATA *Private;\r
177 EFI_STATUS Status;\r
178 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR *MmioDesc;\r
656419f9
RC
179\r
180 //\r
181 // Allocate Private context data for SGO inteface.\r
182 //\r
183 Private = NULL;\r
ac0a286f
MK
184 Status = gBS->AllocatePool (\r
185 EfiBootServicesData,\r
186 sizeof (GOP_PRIVATE_DATA),\r
187 (VOID **)&Private\r
188 );\r
656419f9
RC
189 if (EFI_ERROR (Status)) {\r
190 goto Done;\r
191 }\r
192\r
193 // Set up context record\r
194 //\r
195 Private->Signature = GOP_PRIVATE_DATA_SIGNATURE;\r
196 Private->Handle = Handle;\r
197 Private->ControllerNameTable = NULL;\r
198\r
199 //\r
200 // Open PCI I/O Protocol\r
201 //\r
202 Status = gBS->OpenProtocol (\r
203 Handle,\r
204 &gEfiPciIoProtocolGuid,\r
ac0a286f 205 (VOID **)&Private->PciIo,\r
656419f9
RC
206 This->DriverBindingHandle,\r
207 Handle,\r
208 EFI_OPEN_PROTOCOL_BY_DRIVER\r
209 );\r
210 if (EFI_ERROR (Status)) {\r
211 goto Done;\r
212 }\r
213\r
214 //\r
215 // Check if fbuf mmio BAR is present\r
216 //\r
217 MmioDesc = NULL;\r
ac0a286f
MK
218 Status = Private->PciIo->GetBarAttributes (\r
219 Private->PciIo,\r
220 PCI_BAR_IDX0,\r
221 NULL,\r
222 (VOID **)&MmioDesc\r
223 );\r
656419f9 224 if (EFI_ERROR (Status) ||\r
ac0a286f
MK
225 (MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM))\r
226 {\r
656419f9
RC
227 DEBUG ((DEBUG_INFO, "BHYVE GOP: No mmio bar\n"));\r
228 } else {\r
ac0a286f
MK
229 DEBUG ((\r
230 DEBUG_INFO,\r
231 "BHYVE GOP: Using mmio bar @ 0x%lx\n",\r
232 MmioDesc->AddrRangeMin\r
233 ));\r
234 BhyveGetMemregs (Private, &Memregs);\r
656419f9
RC
235 Private->FbSize = Memregs.FbSize;\r
236 }\r
ac0a286f 237\r
656419f9
RC
238 if (MmioDesc != NULL) {\r
239 FreePool (MmioDesc);\r
240 }\r
ac0a286f 241\r
656419f9
RC
242 if (EFI_ERROR (Status)) {\r
243 goto Done;\r
244 }\r
245\r
246 //\r
247 // Check if fbuf frame-buffer BAR is present\r
248 //\r
249 MmioDesc = NULL;\r
ac0a286f
MK
250 Status = Private->PciIo->GetBarAttributes (\r
251 Private->PciIo,\r
252 PCI_BAR_IDX1,\r
253 NULL,\r
254 (VOID **)&MmioDesc\r
255 );\r
656419f9 256 if (EFI_ERROR (Status) ||\r
ac0a286f
MK
257 (MmioDesc->ResType != ACPI_ADDRESS_SPACE_TYPE_MEM))\r
258 {\r
656419f9
RC
259 DEBUG ((DEBUG_INFO, "BHYVE GOP: No frame-buffer bar\n"));\r
260 } else {\r
ac0a286f
MK
261 DEBUG ((\r
262 DEBUG_INFO,\r
263 "BHYVE GOP: Using frame-buffer bar @ 0x%lx\n",\r
264 MmioDesc->AddrRangeMin\r
265 ));\r
656419f9
RC
266 Private->FbAddr = MmioDesc->AddrRangeMin;\r
267 // XXX assert BAR is >= size\r
268 }\r
269\r
270 if (MmioDesc != NULL) {\r
271 FreePool (MmioDesc);\r
272 }\r
ac0a286f 273\r
656419f9
RC
274 if (EFI_ERROR (Status)) {\r
275 goto Done;\r
276 }\r
277\r
ac0a286f
MK
278 DEBUG ((\r
279 DEBUG_INFO,\r
280 "BHYVE GOP: Framebuf addr 0x%lx, size %x\n",\r
281 Private->FbAddr,\r
282 Private->FbSize\r
283 ));\r
656419f9
RC
284\r
285 Status = EmuGopConstructor (Private);\r
286 if (EFI_ERROR (Status)) {\r
287 goto Done;\r
288 }\r
289\r
290 //\r
291 // Publish the Gop interface to the world\r
292 //\r
293 Status = gBS->InstallMultipleProtocolInterfaces (\r
294 &Private->Handle,\r
ac0a286f
MK
295 &gEfiGraphicsOutputProtocolGuid,\r
296 &Private->GraphicsOutput,\r
656419f9
RC
297 NULL\r
298 );\r
299\r
ac0a286f 300 DEBUG ((DEBUG_INFO, "BHYVE framebuffer device started\n"));\r
656419f9
RC
301\r
302 //\r
303 // Install int10 handler\r
304 //\r
ac0a286f 305 #ifndef CSM_ENABLE\r
656419f9 306 InstallVbeShim (L"Framebuffer", Private->FbAddr);\r
ac0a286f 307 #endif\r
656419f9
RC
308\r
309Done:\r
310 if (EFI_ERROR (Status)) {\r
311 if (Private != NULL) {\r
312 //\r
313 // On Error Free back private data\r
314 //\r
315 if (Private->ControllerNameTable != NULL) {\r
316 FreeUnicodeStringTable (Private->ControllerNameTable);\r
317 }\r
318\r
319 gBS->FreePool (Private);\r
320 }\r
321 }\r
322\r
323 return Status;\r
324}\r
325\r
656419f9
RC
326/**\r
327 Stops a device controller or a bus controller.\r
328\r
329 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().\r
330 As a result, much of the error checking on the parameters to Stop() has been moved\r
331 into this common boot service. It is legal to call Stop() from other locations,\r
332 but the following calling restrictions must be followed, or the system behavior will not be deterministic.\r
333 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this\r
334 same driver's Start() function.\r
335 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid\r
336 EFI_HANDLE. In addition, all of these handles must have been created in this driver's\r
337 Start() function, and the Start() function must have called OpenProtocol() on\r
338 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.\r
339\r
340 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.\r
341 @param[in] ControllerHandle A handle to the device being stopped. The handle must\r
342 support a bus specific I/O protocol for the driver\r
343 to use to stop the device.\r
344 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.\r
345 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL\r
346 if NumberOfChildren is 0.\r
347\r
348 @retval EFI_SUCCESS The device was stopped.\r
349 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.\r
350\r
351**/\r
352EFI_STATUS\r
353EFIAPI\r
354EmuGopDriverBindingStop (\r
355 IN EFI_DRIVER_BINDING_PROTOCOL *This,\r
356 IN EFI_HANDLE Handle,\r
357 IN UINTN NumberOfChildren,\r
358 IN EFI_HANDLE *ChildHandleBuffer\r
359 )\r
360{\r
ac0a286f
MK
361 EFI_GRAPHICS_OUTPUT_PROTOCOL *GraphicsOutput;\r
362 EFI_STATUS Status;\r
363 GOP_PRIVATE_DATA *Private;\r
656419f9 364\r
ac0a286f 365 DEBUG ((DEBUG_INFO, "BHYVE framebuffer device stopping\n"));\r
656419f9
RC
366\r
367 Status = gBS->OpenProtocol (\r
368 Handle,\r
369 &gEfiGraphicsOutputProtocolGuid,\r
370 (VOID **)&GraphicsOutput,\r
371 This->DriverBindingHandle,\r
372 Handle,\r
373 EFI_OPEN_PROTOCOL_GET_PROTOCOL\r
374 );\r
375 if (EFI_ERROR (Status)) {\r
376 //\r
377 // If the GOP interface does not exist the driver is not started\r
378 //\r
379 return EFI_NOT_STARTED;\r
380 }\r
381\r
382 //\r
383 // Get our private context information\r
384 //\r
385 Private = GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput);\r
386\r
387 //\r
388 // Remove the SGO interface from the system\r
389 //\r
390 Status = gBS->UninstallMultipleProtocolInterfaces (\r
391 Private->Handle,\r
ac0a286f
MK
392 &gEfiGraphicsOutputProtocolGuid,\r
393 &Private->GraphicsOutput,\r
656419f9
RC
394 NULL\r
395 );\r
396 if (!EFI_ERROR (Status)) {\r
397 //\r
398 // Shutdown the hardware\r
399 //\r
400 Status = EmuGopDestructor (Private);\r
401 if (EFI_ERROR (Status)) {\r
402 return EFI_DEVICE_ERROR;\r
403 }\r
404\r
405 gBS->CloseProtocol (\r
ac0a286f
MK
406 Handle,\r
407 &gEfiPciIoProtocolGuid,\r
408 This->DriverBindingHandle,\r
409 Private->Handle\r
410 );\r
656419f9
RC
411\r
412 //\r
413 // Free our instance data\r
414 //\r
415 FreeUnicodeStringTable (Private->ControllerNameTable);\r
416\r
417 gBS->FreePool (Private);\r
656419f9
RC
418 }\r
419\r
420 return Status;\r
421}\r
422\r
656419f9
RC
423///\r
424/// This protocol provides the services required to determine if a driver supports a given controller.\r
425/// If a controller is supported, then it also provides routines to start and stop the controller.\r
426///\r
ac0a286f 427EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding = {\r
656419f9
RC
428 EmuGopDriverBindingSupported,\r
429 EmuGopDriverBindingStart,\r
430 EmuGopDriverBindingStop,\r
431 0xa,\r
432 NULL,\r
433 NULL\r
434};\r
435\r
656419f9
RC
436/**\r
437 The user Entry Point for module EmuGop. The user code starts with this function.\r
438\r
439 @param[in] ImageHandle The firmware allocated handle for the EFI image.\r
440 @param[in] SystemTable A pointer to the EFI System Table.\r
441\r
442 @retval EFI_SUCCESS The entry point is executed successfully.\r
443 @retval other Some error occurs when executing this entry point.\r
444\r
445**/\r
446EFI_STATUS\r
447EFIAPI\r
448InitializeEmuGop (\r
ac0a286f
MK
449 IN EFI_HANDLE ImageHandle,\r
450 IN EFI_SYSTEM_TABLE *SystemTable\r
656419f9
RC
451 )\r
452{\r
ac0a286f 453 EFI_STATUS Status;\r
656419f9
RC
454\r
455 Status = EfiLibInstallDriverBindingComponentName2 (\r
456 ImageHandle,\r
457 SystemTable,\r
458 &gEmuGopDriverBinding,\r
459 ImageHandle,\r
460 &gEmuGopComponentName,\r
461 &gEmuGopComponentName2\r
462 );\r
463 ASSERT_EFI_ERROR (Status);\r
464\r
656419f9
RC
465 return Status;\r
466}\r
467\r
468STATIC VOID\r
469BhyveGetGraphicsMode (\r
ac0a286f
MK
470 EFI_PCI_IO_PROTOCOL *PciIo,\r
471 UINT16 *Width,\r
472 UINT16 *Height,\r
473 UINT16 *Depth\r
656419f9
RC
474 )\r
475{\r
ac0a286f
MK
476 BHYVE_FBUF_MEMREGS BhyveRegs;\r
477 UINT64 Offset;\r
478 EFI_STATUS Status;\r
656419f9
RC
479\r
480 Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;\r
481\r
482 Status = PciIo->Mem.Read (\r
ac0a286f
MK
483 PciIo,\r
484 EfiPciIoWidthUint16,\r
485 PCI_BAR_IDX0,\r
486 Offset,\r
487 3,\r
488 &BhyveRegs.Width\r
489 );\r
656419f9
RC
490\r
491 *Width = BhyveRegs.Width;\r
492 *Height = BhyveRegs.Height;\r
493 *Depth = BhyveRegs.Depth;\r
494\r
495 DEBUG ((DEBUG_INFO, "BHYVE Get Graphics Mode: w %d, h %d\n", *Width, *Height));\r
496\r
497 ASSERT_EFI_ERROR (Status);\r
498}\r
499\r
500VOID\r
501BhyveSetGraphicsMode (\r
502 GOP_PRIVATE_DATA *Private,\r
ac0a286f
MK
503 UINT16 Width,\r
504 UINT16 Height,\r
505 UINT16 Depth\r
656419f9
RC
506 )\r
507{\r
ac0a286f
MK
508 BHYVE_FBUF_MEMREGS BhyveRegs;\r
509 UINT64 Offset;\r
510 EFI_STATUS Status;\r
656419f9
RC
511\r
512 DEBUG ((DEBUG_INFO, "BHYVE Set Graphics Mode: w %d, h %d\n", Width, Height));\r
513\r
514 BhyveRegs.Width = Width;\r
515 BhyveRegs.Height = Height;\r
516 BhyveRegs.Depth = Depth;\r
ac0a286f 517 Offset = (UINT64)&BhyveRegs.Width - (UINT64)&BhyveRegs;\r
656419f9
RC
518\r
519 Status = Private->PciIo->Mem.Write (\r
ac0a286f
MK
520 Private->PciIo,\r
521 EfiPciIoWidthUint16,\r
522 PCI_BAR_IDX0,\r
523 Offset,\r
524 3,\r
525 &BhyveRegs.Width\r
526 );\r
656419f9
RC
527 ASSERT_EFI_ERROR (Status);\r
528}\r
529\r
530VOID\r
531BhyveGetMemregs (\r
ac0a286f
MK
532 GOP_PRIVATE_DATA *Private,\r
533 BHYVE_FBUF_MEMREGS *Memregs\r
656419f9
RC
534 )\r
535{\r
ac0a286f 536 EFI_STATUS Status;\r
656419f9
RC
537\r
538 Status = Private->PciIo->Mem.Read (\r
ac0a286f
MK
539 Private->PciIo,\r
540 EfiPciIoWidthUint32,\r
541 PCI_BAR_IDX0,\r
542 0,\r
543 3,\r
544 Memregs\r
545 );\r
656419f9
RC
546 ASSERT_EFI_ERROR (Status);\r
547\r
ac0a286f
MK
548 DEBUG ((\r
549 DEBUG_INFO,\r
550 "BHYVE Get Memregs, size %d width %d height %d\n",\r
551 Memregs->FbSize,\r
552 Memregs->Width,\r
553 Memregs->Height\r
554 ));\r
656419f9 555}\r