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
,
24 Tests to see if this driver supports a given controller. If a child device is provided,
25 it further tests to see if this driver supports creating a handle for the specified child device.
27 This function checks to see if the driver specified by This supports the device specified by
28 ControllerHandle. Drivers will typically use the device path attached to
29 ControllerHandle and/or the services from the bus I/O abstraction attached to
30 ControllerHandle to determine if the driver supports ControllerHandle. This function
31 may be called many times during platform initialization. In order to reduce boot times, the tests
32 performed by this function must be very small, and take as little time as possible to execute. This
33 function must not change the state of any hardware devices, and this function must be aware that the
34 device specified by ControllerHandle may already be managed by the same driver or a
35 different driver. This function must match its calls to AllocatePages() with FreePages(),
36 AllocatePool() with FreePool(), and OpenProtocol() with CloseProtocol().
37 Because ControllerHandle may have been previously started by the same driver, if a protocol is
38 already in the opened state, then it must not be closed with CloseProtocol(). This is required
39 to guarantee the state of ControllerHandle is not modified by this function.
41 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
42 @param[in] ControllerHandle The handle of the controller to test. This handle
43 must support a protocol interface that supplies
44 an I/O abstraction to the driver.
45 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
46 parameter is ignored by device drivers, and is optional for bus
47 drivers. For bus drivers, if this parameter is not NULL, then
48 the bus driver must determine if the bus controller specified
49 by ControllerHandle and the child controller specified
50 by RemainingDevicePath are both supported by this
53 @retval EFI_SUCCESS The device specified by ControllerHandle and
54 RemainingDevicePath is supported by the driver specified by This.
55 @retval EFI_ALREADY_STARTED The device specified by ControllerHandle and
56 RemainingDevicePath is already being managed by the driver
58 @retval EFI_ACCESS_DENIED The device specified by ControllerHandle and
59 RemainingDevicePath is already being managed by a different
60 driver or an application that requires exclusive access.
61 Currently not implemented.
62 @retval EFI_UNSUPPORTED The device specified by ControllerHandle and
63 RemainingDevicePath is not supported by the driver specified by This.
67 EmuGopDriverBindingSupported (
68 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
70 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
74 EFI_PCI_IO_PROTOCOL
*PciIo
;
76 UINT16 Width
, Height
, Depth
;
79 // Open the IO Abstraction(s) needed to perform the supported test
81 Status
= gBS
->OpenProtocol (
83 &gEfiPciIoProtocolGuid
,
85 This
->DriverBindingHandle
,
87 EFI_OPEN_PROTOCOL_BY_DRIVER
89 if (EFI_ERROR (Status
)) {
94 // See if this is a PCI Framebuffer Controller by looking at the Command register and
95 // Class Code Register
97 Status
= PciIo
->Pci
.Read (
101 sizeof (Pci
) / sizeof (UINT32
),
104 if (EFI_ERROR (Status
)) {
105 Status
= EFI_UNSUPPORTED
;
109 Status
= EFI_UNSUPPORTED
;
110 if (Pci
.Hdr
.VendorId
== 0xFB5D && Pci
.Hdr
.DeviceId
== 0x40FB) {
111 DEBUG((DEBUG_INFO
, "BHYVE framebuffer device detected\n"));
112 Status
= EFI_SUCCESS
;
114 BhyveGetGraphicsMode(PciIo
, &Width
, &Height
, &Depth
);
115 PcdSet32S (PcdVideoHorizontalResolution
, Width
);
116 PcdSet32S (PcdVideoVerticalResolution
, Height
);
121 // Close the PCI I/O Protocol
125 &gEfiPciIoProtocolGuid
,
126 This
->DriverBindingHandle
,
135 Starts a device controller or a bus controller.
137 The Start() function is designed to be invoked from the EFI boot service ConnectController().
138 As a result, much of the error checking on the parameters to Start() has been moved into this
139 common boot service. It is legal to call Start() from other locations,
140 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
141 1. ControllerHandle must be a valid EFI_HANDLE.
142 2. If RemainingDevicePath is not NULL, then it must be a pointer to a naturally aligned
143 EFI_DEVICE_PATH_PROTOCOL.
144 3. Prior to calling Start(), the Supported() function for the driver specified by This must
145 have been called with the same calling parameters, and Supported() must have returned EFI_SUCCESS.
147 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
148 @param[in] ControllerHandle The handle of the controller to start. This handle
149 must support a protocol interface that supplies
150 an I/O abstraction to the driver.
151 @param[in] RemainingDevicePath A pointer to the remaining portion of a device path. This
152 parameter is ignored by device drivers, and is optional for bus
153 drivers. For a bus driver, if this parameter is NULL, then handles
154 for all the children of Controller are created by this driver.
155 If this parameter is not NULL and the first Device Path Node is
156 not the End of Device Path Node, then only the handle for the
157 child device specified by the first Device Path Node of
158 RemainingDevicePath is created by this driver.
159 If the first Device Path Node of RemainingDevicePath is
160 the End of Device Path Node, no child handle is created by this
163 @retval EFI_SUCCESS The device was started.
164 @retval EFI_DEVICE_ERROR The device could not be started due to a device error.Currently not implemented.
165 @retval EFI_OUT_OF_RESOURCES The request could not be completed due to a lack of resources.
166 @retval Others The driver failded to start the device.
171 EmuGopDriverBindingStart (
172 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
173 IN EFI_HANDLE Handle
,
174 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
177 BHYVE_FBUF_MEMREGS Memregs
;
178 GOP_PRIVATE_DATA
*Private
;
180 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*MmioDesc
;
183 // Allocate Private context data for SGO inteface.
186 Status
= gBS
->AllocatePool (
188 sizeof (GOP_PRIVATE_DATA
),
191 if (EFI_ERROR (Status
)) {
195 // Set up context record
197 Private
->Signature
= GOP_PRIVATE_DATA_SIGNATURE
;
198 Private
->Handle
= Handle
;
199 Private
->ControllerNameTable
= NULL
;
202 // Open PCI I/O Protocol
204 Status
= gBS
->OpenProtocol (
206 &gEfiPciIoProtocolGuid
,
207 (VOID
**) &Private
->PciIo
,
208 This
->DriverBindingHandle
,
210 EFI_OPEN_PROTOCOL_BY_DRIVER
212 if (EFI_ERROR (Status
)) {
217 // Check if fbuf mmio BAR is present
220 Status
= Private
->PciIo
->GetBarAttributes (
226 if (EFI_ERROR (Status
) ||
227 MmioDesc
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_MEM
) {
228 DEBUG ((DEBUG_INFO
, "BHYVE GOP: No mmio bar\n"));
230 DEBUG ((DEBUG_INFO
, "BHYVE GOP: Using mmio bar @ 0x%lx\n",
231 MmioDesc
->AddrRangeMin
));
232 BhyveGetMemregs(Private
, &Memregs
);
233 Private
->FbSize
= Memregs
.FbSize
;
235 if (MmioDesc
!= NULL
) {
238 if (EFI_ERROR (Status
)) {
243 // Check if fbuf frame-buffer BAR is present
246 Status
= Private
->PciIo
->GetBarAttributes (
252 if (EFI_ERROR (Status
) ||
253 MmioDesc
->ResType
!= ACPI_ADDRESS_SPACE_TYPE_MEM
) {
254 DEBUG ((DEBUG_INFO
, "BHYVE GOP: No frame-buffer bar\n"));
256 DEBUG ((DEBUG_INFO
, "BHYVE GOP: Using frame-buffer bar @ 0x%lx\n",
257 MmioDesc
->AddrRangeMin
));
258 Private
->FbAddr
= MmioDesc
->AddrRangeMin
;
259 // XXX assert BAR is >= size
262 if (MmioDesc
!= NULL
) {
265 if (EFI_ERROR (Status
)) {
269 DEBUG ((DEBUG_INFO
, "BHYVE GOP: Framebuf addr 0x%lx, size %x\n",
270 Private
->FbAddr
, Private
->FbSize
));
272 Status
= EmuGopConstructor (Private
);
273 if (EFI_ERROR (Status
)) {
278 // Publish the Gop interface to the world
280 Status
= gBS
->InstallMultipleProtocolInterfaces (
282 &gEfiGraphicsOutputProtocolGuid
, &Private
->GraphicsOutput
,
286 DEBUG((DEBUG_INFO
, "BHYVE framebuffer device started\n"));
289 // Install int10 handler
292 InstallVbeShim (L
"Framebuffer", Private
->FbAddr
);
296 if (EFI_ERROR (Status
)) {
297 if (Private
!= NULL
) {
299 // On Error Free back private data
301 if (Private
->ControllerNameTable
!= NULL
) {
302 FreeUnicodeStringTable (Private
->ControllerNameTable
);
305 gBS
->FreePool (Private
);
315 Stops a device controller or a bus controller.
317 The Stop() function is designed to be invoked from the EFI boot service DisconnectController().
318 As a result, much of the error checking on the parameters to Stop() has been moved
319 into this common boot service. It is legal to call Stop() from other locations,
320 but the following calling restrictions must be followed, or the system behavior will not be deterministic.
321 1. ControllerHandle must be a valid EFI_HANDLE that was used on a previous call to this
322 same driver's Start() function.
323 2. The first NumberOfChildren handles of ChildHandleBuffer must all be a valid
324 EFI_HANDLE. In addition, all of these handles must have been created in this driver's
325 Start() function, and the Start() function must have called OpenProtocol() on
326 ControllerHandle with an Attribute of EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER.
328 @param[in] This A pointer to the EFI_DRIVER_BINDING_PROTOCOL instance.
329 @param[in] ControllerHandle A handle to the device being stopped. The handle must
330 support a bus specific I/O protocol for the driver
331 to use to stop the device.
332 @param[in] NumberOfChildren The number of child device handles in ChildHandleBuffer.
333 @param[in] ChildHandleBuffer An array of child handles to be freed. May be NULL
334 if NumberOfChildren is 0.
336 @retval EFI_SUCCESS The device was stopped.
337 @retval EFI_DEVICE_ERROR The device could not be stopped due to a device error.
342 EmuGopDriverBindingStop (
343 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
344 IN EFI_HANDLE Handle
,
345 IN UINTN NumberOfChildren
,
346 IN EFI_HANDLE
*ChildHandleBuffer
349 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
351 GOP_PRIVATE_DATA
*Private
;
353 DEBUG((DEBUG_INFO
, "BHYVE framebuffer device stopping\n"));
355 Status
= gBS
->OpenProtocol (
357 &gEfiGraphicsOutputProtocolGuid
,
358 (VOID
**)&GraphicsOutput
,
359 This
->DriverBindingHandle
,
361 EFI_OPEN_PROTOCOL_GET_PROTOCOL
363 if (EFI_ERROR (Status
)) {
365 // If the GOP interface does not exist the driver is not started
367 return EFI_NOT_STARTED
;
371 // Get our private context information
373 Private
= GOP_PRIVATE_DATA_FROM_THIS (GraphicsOutput
);
376 // Remove the SGO interface from the system
378 Status
= gBS
->UninstallMultipleProtocolInterfaces (
380 &gEfiGraphicsOutputProtocolGuid
, &Private
->GraphicsOutput
,
383 if (!EFI_ERROR (Status
)) {
385 // Shutdown the hardware
387 Status
= EmuGopDestructor (Private
);
388 if (EFI_ERROR (Status
)) {
389 return EFI_DEVICE_ERROR
;
394 &gEfiPciIoProtocolGuid
,
395 This
->DriverBindingHandle
,
400 // Free our instance data
402 FreeUnicodeStringTable (Private
->ControllerNameTable
);
404 gBS
->FreePool (Private
);
413 /// This protocol provides the services required to determine if a driver supports a given controller.
414 /// If a controller is supported, then it also provides routines to start and stop the controller.
416 EFI_DRIVER_BINDING_PROTOCOL gEmuGopDriverBinding
= {
417 EmuGopDriverBindingSupported
,
418 EmuGopDriverBindingStart
,
419 EmuGopDriverBindingStop
,
428 The user Entry Point for module EmuGop. The user code starts with this function.
430 @param[in] ImageHandle The firmware allocated handle for the EFI image.
431 @param[in] SystemTable A pointer to the EFI System Table.
433 @retval EFI_SUCCESS The entry point is executed successfully.
434 @retval other Some error occurs when executing this entry point.
440 IN EFI_HANDLE ImageHandle
,
441 IN EFI_SYSTEM_TABLE
*SystemTable
446 Status
= EfiLibInstallDriverBindingComponentName2 (
449 &gEmuGopDriverBinding
,
451 &gEmuGopComponentName
,
452 &gEmuGopComponentName2
454 ASSERT_EFI_ERROR (Status
);
461 BhyveGetGraphicsMode (
462 EFI_PCI_IO_PROTOCOL
*PciIo
,
468 BHYVE_FBUF_MEMREGS BhyveRegs
;
473 Offset
= (UINT64
)&BhyveRegs
.Width
- (UINT64
)&BhyveRegs
;
475 Status
= PciIo
->Mem
.Read (
484 *Width
= BhyveRegs
.Width
;
485 *Height
= BhyveRegs
.Height
;
486 *Depth
= BhyveRegs
.Depth
;
488 DEBUG ((DEBUG_INFO
, "BHYVE Get Graphics Mode: w %d, h %d\n", *Width
, *Height
));
490 ASSERT_EFI_ERROR (Status
);
494 BhyveSetGraphicsMode (
495 GOP_PRIVATE_DATA
*Private
,
501 BHYVE_FBUF_MEMREGS BhyveRegs
;
505 DEBUG ((DEBUG_INFO
, "BHYVE Set Graphics Mode: w %d, h %d\n", Width
, Height
));
507 BhyveRegs
.Width
= Width
;
508 BhyveRegs
.Height
= Height
;
509 BhyveRegs
.Depth
= Depth
;
510 Offset
= (UINT64
)&BhyveRegs
.Width
- (UINT64
)&BhyveRegs
;
512 Status
= Private
->PciIo
->Mem
.Write (
520 ASSERT_EFI_ERROR (Status
);
525 GOP_PRIVATE_DATA
*Private
,
526 BHYVE_FBUF_MEMREGS
*Memregs
531 Status
= Private
->PciIo
->Mem
.Read (
539 ASSERT_EFI_ERROR (Status
);
541 DEBUG ((DEBUG_INFO
, "BHYVE Get Memregs, size %d width %d height %d\n",
542 Memregs
->FbSize
, Memregs
->Width
, Memregs
->Height
));