3 Copyright (c) 2020, Rebecca Cran <rebecca@bsdio.com>
4 Copyright (c) 2006, Intel Corporation. All rights reserved.<BR>
5 Portions copyright (c) 2010,Apple Inc. All rights reserved.<BR>
7 SPDX-License-Identifier: BSD-2-Clause-Patent
12 #include <IndustryStandard/Acpi.h>
15 BhyveGetGraphicsMode (
16 EFI_PCI_IO_PROTOCOL
*PciIo
,
23 Tests to see if this driver supports a given controller. If a child device is provided,
24 it further tests to see if this driver supports creating a handle for the specified child device.
26 This function checks to see if the driver specified by This supports the device specified by
27 ControllerHandle. Drivers will typically use the device path attached to
28 ControllerHandle and/or the services from the bus I/O abstraction attached to
29 ControllerHandle to determine if the driver supports ControllerHandle. This function
30 may be called many times during platform initialization. In order to reduce boot times, the tests
31 performed by this function must be very small, and take as little time as possible to execute. This
32 function must not change the state of any hardware devices, and this function must be aware that the
33 device specified by ControllerHandle may already be managed by the same driver or a
34 different driver. This function must match its calls to AllocatePages() with FreePages(),
35 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
36 Because ControllerHandle may have been previously started by the same driver, if a protocol is
37 already in the opened state, then it must not be closed with CloseProtocol(). This is required
38 to guarantee the state of ControllerHandle is not modified by this function.
40 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
41 @param[in] ControllerHandle The handle of the controller to test. This handle
42 must support a protocol interface that supplies
43 an I/O abstraction to the driver.
44 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
45 parameter is ignored by device drivers, and is optional for bus
46 drivers. For bus drivers, if this parameter is not NULL, then
47 the bus driver must determine if the bus controller specified
48 by ControllerHandle and the child controller specified
49 by RemainingDevicePath are both supported by this
52 @retval EFI_SUCCESS The device specified by ControllerHandle and
53 RemainingDevicePath is supported by the driver specified by This.
54 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
55 RemainingDevicePath is already being managed by the driver
57 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
58 RemainingDevicePath is already being managed by a different
59 driver or an application that requires exclusive access.
60 Currently not implemented.
61 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
62 RemainingDevicePath is not supported by the driver specified by This.
66 EmuGopDriverBindingSupported (
67 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
69 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
73 EFI_PCI_IO_PROTOCOL
*PciIo
;
75 UINT16 Width
, Height
, Depth
;
78 // Open the IO Abstraction(s) needed to perform the supported test
80 Status
= gBS
->OpenProtocol (
82 &gEfiPciIoProtocolGuid
,
84 This
->DriverBindingHandle
,
86 EFI_OPEN_PROTOCOL_BY_DRIVER
88 if (EFI_ERROR (Status
)) {
93 // See if this is a PCI Framebuffer Controller by looking at the Command register and
94 // Class Code Register
96 Status
= PciIo
->Pci
.Read (
100 sizeof (Pci
) / sizeof (UINT32
),
103 if (EFI_ERROR (Status
)) {
104 Status
= EFI_UNSUPPORTED
;
108 Status
= EFI_UNSUPPORTED
;
109 if ((Pci
.Hdr
.VendorId
== 0xFB5D) && (Pci
.Hdr
.DeviceId
== 0x40FB)) {
110 DEBUG ((DEBUG_INFO
, "BHYVE framebuffer device detected\n"));
111 Status
= EFI_SUCCESS
;
113 BhyveGetGraphicsMode (PciIo
, &Width
, &Height
, &Depth
);
114 PcdSet32S (PcdVideoHorizontalResolution
, Width
);
115 PcdSet32S (PcdVideoVerticalResolution
, Height
);
120 // Close the PCI I/O Protocol
124 &gEfiPciIoProtocolGuid
,
125 This
->DriverBindingHandle
,
133 Starts a device controller or a bus controller.
135 The Start() function is designed to be invoked from the EFI boot service ConnectController().
136 As a result, much of the error checking on the parameters to Start() has been moved into this
137 common boot service. It is legal to call Start() from other locations,
138 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
139 1. ControllerHandle must be a valid EFI_HANDLE.
140 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
141 EFI_DEVICE_PATH_PROTOCOL.
142 3. Prior to calling Start(), the Supported() function for the driver specified by This must
143 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
145 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
146 @param[in] ControllerHandle The handle of the controller to start. This handle
147 must support a protocol interface that supplies
148 an I/O abstraction to the driver.
149 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
150 parameter is ignored by device drivers, and is optional for bus
151 drivers. For a bus driver, if this parameter is NULL, then handles
152 for all the children of Controller are created by this driver.
153 If this parameter is not NULL and the first Device Path Node is
154 not the End of Device Path Node, then only the handle for the
155 child device specified by the first Device Path Node of
156 RemainingDevicePath is created by this driver.
157 If the first Device Path Node of RemainingDevicePath is
158 the End of Device Path Node, no child handle is created by this
161 @retval EFI_SUCCESS The device was started.
162 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
163 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
164 @retval Others The driver failded to start the device.
169 EmuGopDriverBindingStart (
170 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
171 IN EFI_HANDLE Handle
,
172 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
175 BHYVE_FBUF_MEMREGS Memregs
;
176 GOP_PRIVATE_DATA
*Private
;
178 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*MmioDesc
;
181 // Allocate Private context data for SGO inteface.
184 Status
= gBS
->AllocatePool (
186 sizeof (GOP_PRIVATE_DATA
),
189 if (EFI_ERROR (Status
)) {
193 // Set up context record
195 Private
->Signature
= GOP_PRIVATE_DATA_SIGNATURE
;
196 Private
->Handle
= Handle
;
197 Private
->ControllerNameTable
= NULL
;
200 // Open PCI I/O Protocol
202 Status
= gBS
->OpenProtocol (
204 &gEfiPciIoProtocolGuid
,
205 (VOID
**)&Private
->PciIo
,
206 This
->DriverBindingHandle
,
208 EFI_OPEN_PROTOCOL_BY_DRIVER
210 if (EFI_ERROR (Status
)) {
215 // Check if fbuf mmio BAR is present
218 Status
= Private
->PciIo
->GetBarAttributes (
224 if (EFI_ERROR (Status
) ||
225 (MmioDesc
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_MEM
))
227 DEBUG ((DEBUG_INFO
, "BHYVE GOP: No mmio bar\n"));
231 "BHYVE GOP: Using mmio bar @ 0x%lx\n",
232 MmioDesc
->AddrRangeMin
234 BhyveGetMemregs (Private
, &Memregs
);
235 Private
->FbSize
= Memregs
.FbSize
;
238 if (MmioDesc
!= NULL
) {
242 if (EFI_ERROR (Status
)) {
247 // Check if fbuf frame-buffer BAR is present
250 Status
= Private
->PciIo
->GetBarAttributes (
256 if (EFI_ERROR (Status
) ||
257 (MmioDesc
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_MEM
))
259 DEBUG ((DEBUG_INFO
, "BHYVE GOP: No frame-buffer bar\n"));
263 "BHYVE GOP: Using frame-buffer bar @ 0x%lx\n",
264 MmioDesc
->AddrRangeMin
266 Private
->FbAddr
= MmioDesc
->AddrRangeMin
;
267 // XXX assert BAR is >= size
270 if (MmioDesc
!= NULL
) {
274 if (EFI_ERROR (Status
)) {
280 "BHYVE GOP: Framebuf addr 0x%lx, size %x\n",
285 Status
= EmuGopConstructor (Private
);
286 if (EFI_ERROR (Status
)) {
291 // Publish the Gop interface to the world
293 Status
= gBS
->InstallMultipleProtocolInterfaces (
295 &gEfiGraphicsOutputProtocolGuid
,
296 &Private
->GraphicsOutput
,
300 DEBUG ((DEBUG_INFO
, "BHYVE framebuffer device started\n"));
303 // Install int10 handler
306 InstallVbeShim (L
"Framebuffer", Private
->FbAddr
);
310 if (EFI_ERROR (Status
)) {
311 if (Private
!= NULL
) {
313 // On Error Free back private data
315 if (Private
->ControllerNameTable
!= NULL
) {
316 FreeUnicodeStringTable (Private
->ControllerNameTable
);
319 gBS
->FreePool (Private
);
327 Stops a device controller or a bus controller.
329 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
330 As a result, much of the error checking on the parameters to Stop() has been moved
331 into this common boot service. It is legal to call Stop() from other locations,
332 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
333 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
334 same driver's Start() function.
335 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
336 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
337 Start() function, and the Start() function must have called OpenProtocol() on
338 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
340 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
341 @param[in] ControllerHandle A handle to the device being stopped. The handle must
342 support a bus specific I/O protocol for the driver
343 to use to stop the device.
344 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
345 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
346 if NumberOfChildren is 0.
348 @retval EFI_SUCCESS The device was stopped.
349 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
354 EmuGopDriverBindingStop (
355 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
356 IN EFI_HANDLE Handle
,
357 IN UINTN NumberOfChildren
,
358 IN EFI_HANDLE
*ChildHandleBuffer
361 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
363 GOP_PRIVATE_DATA
*Private
;
365 DEBUG ((DEBUG_INFO
, "BHYVE framebuffer device stopping\n"));
367 Status
= gBS
->OpenProtocol (
369 &gEfiGraphicsOutputProtocolGuid
,
370 (VOID
**)&GraphicsOutput
,
371 This
->DriverBindingHandle
,
373 EFI_OPEN_PROTOCOL_GET_PROTOCOL
375 if (EFI_ERROR (Status
)) {
377 // If the GOP interface does not exist the driver is not started
379 return EFI_NOT_STARTED
;
383 // Get our private context information
385 Private
= GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput
);
388 // Remove the SGO interface from the system
390 Status
= gBS
->UninstallMultipleProtocolInterfaces (
392 &gEfiGraphicsOutputProtocolGuid
,
393 &Private
->GraphicsOutput
,
396 if (!EFI_ERROR (Status
)) {
398 // Shutdown the hardware
400 Status
= EmuGopDestructor (Private
);
401 if (EFI_ERROR (Status
)) {
402 return EFI_DEVICE_ERROR
;
407 &gEfiPciIoProtocolGuid
,
408 This
->DriverBindingHandle
,
413 // Free our instance data
415 FreeUnicodeStringTable (Private
->ControllerNameTable
);
417 gBS
->FreePool (Private
);
424 /// This protocol provides the services required to determine if a driver supports a given controller.
425 /// If a controller is supported, then it also provides routines to start and stop the controller.
427 EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding
= {
428 EmuGopDriverBindingSupported
,
429 EmuGopDriverBindingStart
,
430 EmuGopDriverBindingStop
,
437 The user Entry Point for module EmuGop. The user code starts with this function.
439 @param[in] ImageHandle The firmware allocated handle for the EFI image.
440 @param[in] SystemTable A pointer to the EFI System Table.
442 @retval EFI_SUCCESS The entry point is executed successfully.
443 @retval other Some error occurs when executing this entry point.
449 IN EFI_HANDLE ImageHandle
,
450 IN EFI_SYSTEM_TABLE
*SystemTable
455 Status
= EfiLibInstallDriverBindingComponentName2 (
458 &gEmuGopDriverBinding
,
460 &gEmuGopComponentName
,
461 &gEmuGopComponentName2
463 ASSERT_EFI_ERROR (Status
);
469 BhyveGetGraphicsMode (
470 EFI_PCI_IO_PROTOCOL
*PciIo
,
476 BHYVE_FBUF_MEMREGS BhyveRegs
;
480 Offset
= (UINT64
)&BhyveRegs
.Width
- (UINT64
)&BhyveRegs
;
482 Status
= PciIo
->Mem
.Read (
491 *Width
= BhyveRegs
.Width
;
492 *Height
= BhyveRegs
.Height
;
493 *Depth
= BhyveRegs
.Depth
;
495 DEBUG ((DEBUG_INFO
, "BHYVE Get Graphics Mode: w %d, h %d\n", *Width
, *Height
));
497 ASSERT_EFI_ERROR (Status
);
501 BhyveSetGraphicsMode (
502 GOP_PRIVATE_DATA
*Private
,
508 BHYVE_FBUF_MEMREGS BhyveRegs
;
512 DEBUG ((DEBUG_INFO
, "BHYVE Set Graphics Mode: w %d, h %d\n", Width
, Height
));
514 BhyveRegs
.Width
= Width
;
515 BhyveRegs
.Height
= Height
;
516 BhyveRegs
.Depth
= Depth
;
517 Offset
= (UINT64
)&BhyveRegs
.Width
- (UINT64
)&BhyveRegs
;
519 Status
= Private
->PciIo
->Mem
.Write (
527 ASSERT_EFI_ERROR (Status
);
532 GOP_PRIVATE_DATA
*Private
,
533 BHYVE_FBUF_MEMREGS
*Memregs
538 Status
= Private
->PciIo
->Mem
.Read (
546 ASSERT_EFI_ERROR (Status
);
550 "BHYVE Get Memregs, size %d width %d height %d\n",