2 ConsoleOut Routines that speak VGA.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
6 SPDX-License-Identifier: BSD-2-Clause-Patent
12 EFI_PIXEL_BITMASK mPixelBitMask
= {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};
15 // Save controller attributes during first start
17 UINT64 mOriginalPciAttributes
;
18 BOOLEAN mPciAttributesSaved
= FALSE
;
19 FRAME_BUFFER_INFO
*mFrameBufferInfo
;
22 // EFI Driver Binding Protocol Instance
24 EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding
= {
25 FbGopDriverBindingSupported
,
26 FbGopDriverBindingStart
,
27 FbGopDriverBindingStop
,
34 // Native resolution in EDID DetailedTiming[0]
36 UINT32 mNativeModeHorizontal
;
37 UINT32 mNativeModeVertical
;
42 @param This Pointer to driver binding protocol
43 @param Controller Controller handle to connect
44 @param RemainingDevicePath A pointer to the remaining portion of a device
47 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
48 driver, Otherwise, this controller cannot be
49 managed by this driver
54 FbGopDriverBindingSupported (
55 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
56 IN EFI_HANDLE Controller
,
57 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
61 EFI_PCI_IO_PROTOCOL
*PciIo
;
65 EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
*Resources
;
68 // Open the IO Abstraction(s) needed to perform the supported test
70 Status
= gBS
->OpenProtocol (
72 &gEfiPciIoProtocolGuid
,
74 This
->DriverBindingHandle
,
76 EFI_OPEN_PROTOCOL_BY_DRIVER
78 if (EFI_ERROR (Status
)) {
83 // See if this is a PCI Graphics Controller by looking at the Command register and
84 // Class Code Register
86 Status
= PciIo
->Pci
.Read (
90 sizeof (Pci
) / sizeof (UINT32
),
93 if (EFI_ERROR (Status
)) {
94 Status
= EFI_UNSUPPORTED
;
98 Status
= EFI_UNSUPPORTED
;
99 if (IS_PCI_DISPLAY (&Pci
) || IS_PCI_OLD_VGA (&Pci
)) {
101 // Check if PCI BAR matches the framebuffer base
103 Status
= EFI_UNSUPPORTED
;
104 for (Index
= 0; Index
< PCI_MAX_BAR
; Index
++) {
105 Status
= PciIo
->GetBarAttributes (PciIo
, Index
, NULL
, (VOID
**) &Resources
);
106 if (!EFI_ERROR (Status
)) {
107 if ((Resources
->Desc
== ACPI_ADDRESS_SPACE_DESCRIPTOR
) &&
108 (Resources
->Len
== (UINT16
) (sizeof (EFI_ACPI_ADDRESS_SPACE_DESCRIPTOR
) - 3)) &&
109 (Resources
->ResType
== ACPI_ADDRESS_SPACE_TYPE_MEM
) &&
110 (Resources
->AddrRangeMin
== mFrameBufferInfo
->LinearFrameBuffer
)) {
111 DEBUG ((DEBUG_INFO
, "Found matched framebuffer PCI BAR !\n"));
112 Status
= EFI_SUCCESS
;
118 if (!EFI_ERROR (Status
)) {
120 // If this is a graphics controller,
121 // go further check RemainingDevicePath
123 if (RemainingDevicePath
!= NULL
) {
124 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
126 // Check if RemainingDevicePath is the End of Device Path Node,
127 // if yes, return EFI_SUCCESS
129 if (!IsDevicePathEnd (Node
)) {
131 // Verify RemainingDevicePath
133 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
134 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
135 DevicePathNodeLength(&Node
->DevPath
) < sizeof(ACPI_ADR_DEVICE_PATH
)) {
136 Status
= EFI_UNSUPPORTED
;
146 &gEfiPciIoProtocolGuid
,
147 This
->DriverBindingHandle
,
156 Install Graphics Output Protocol onto VGA device handles.
158 @param This Pointer to driver binding protocol
159 @param Controller Controller handle to connect
160 @param RemainingDevicePath A pointer to the remaining portion of a device
168 FbGopDriverBindingStart (
169 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
170 IN EFI_HANDLE Controller
,
171 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
175 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
176 EFI_PCI_IO_PROTOCOL
*PciIo
;
179 DEBUG ((DEBUG_INFO
, "GOP START\n"));
182 // Initialize local variables
185 ParentDevicePath
= NULL
;
188 // Prepare for status code
190 Status
= gBS
->HandleProtocol (
192 &gEfiDevicePathProtocolGuid
,
193 (VOID
**) &ParentDevicePath
195 if (EFI_ERROR (Status
)) {
200 // Open the IO Abstraction(s) needed
202 Status
= gBS
->OpenProtocol (
204 &gEfiPciIoProtocolGuid
,
206 This
->DriverBindingHandle
,
208 EFI_OPEN_PROTOCOL_BY_DRIVER
210 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
215 // Save original PCI attributes
217 if (!mPciAttributesSaved
) {
218 Status
= PciIo
->Attributes (
220 EfiPciIoAttributeOperationGet
,
222 &mOriginalPciAttributes
225 if (EFI_ERROR (Status
)) {
228 mPciAttributesSaved
= TRUE
;
232 // Get supported PCI attributes
234 Status
= PciIo
->Attributes (
236 EfiPciIoAttributeOperationSupported
,
240 if (EFI_ERROR (Status
)) {
244 Supports
&= (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
245 if (Supports
== 0 || Supports
== (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
246 Status
= EFI_UNSUPPORTED
;
250 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
252 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_ENABLE
,
256 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
258 Status
= PciIo
->Attributes (
260 EfiPciIoAttributeOperationEnable
,
261 EFI_PCI_DEVICE_ENABLE
,
264 if (EFI_ERROR (Status
)) {
265 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
266 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
267 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_RESOURCE_CONFLICT
,
273 if (RemainingDevicePath
!= NULL
) {
274 if (IsDevicePathEnd (RemainingDevicePath
)) {
276 // If RemainingDevicePath is the End of Device Path Node,
277 // don't create any child device and return EFI_SUCCESS
278 Status
= EFI_SUCCESS
;
284 // Create child handle and install GraphicsOutputProtocol on it
286 Status
= FbGopChildHandleInstall (
296 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
298 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
300 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_DISABLE
,
304 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
306 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_NOT_DETECTED
,
309 if (!HasChildHandle (Controller
)) {
310 if (mPciAttributesSaved
) {
312 // Restore original PCI attributes
316 EfiPciIoAttributeOperationSet
,
317 mOriginalPciAttributes
,
323 // Release PCI I/O Protocols on the controller handle.
327 &gEfiPciIoProtocolGuid
,
328 This
->DriverBindingHandle
,
340 @param This Pointer to driver binding protocol
341 @param Controller Controller handle to connect
342 @param NumberOfChildren Number of children handle created by this driver
343 @param ChildHandleBuffer Buffer containing child handle created
345 @retval EFI_SUCCESS Driver disconnected successfully from controller
346 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure
351 FbGopDriverBindingStop (
352 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
353 IN EFI_HANDLE Controller
,
354 IN UINTN NumberOfChildren
,
355 IN EFI_HANDLE
*ChildHandleBuffer
359 BOOLEAN AllChildrenStopped
;
361 EFI_PCI_IO_PROTOCOL
*PciIo
;
363 AllChildrenStopped
= TRUE
;
365 if (NumberOfChildren
== 0) {
367 // Close PCI I/O protocol on the controller handle
371 &gEfiPciIoProtocolGuid
,
372 This
->DriverBindingHandle
,
379 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
381 Status
= EFI_SUCCESS
;
383 FbGopChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
385 if (EFI_ERROR (Status
)) {
386 AllChildrenStopped
= FALSE
;
390 if (!AllChildrenStopped
) {
391 return EFI_DEVICE_ERROR
;
394 if (!HasChildHandle (Controller
)) {
395 if (mPciAttributesSaved
) {
396 Status
= gBS
->HandleProtocol (
398 &gEfiPciIoProtocolGuid
,
401 ASSERT_EFI_ERROR (Status
);
404 // Restore original PCI attributes
406 Status
= PciIo
->Attributes (
408 EfiPciIoAttributeOperationSet
,
409 mOriginalPciAttributes
,
412 ASSERT_EFI_ERROR (Status
);
422 Install child handles if the Handle supports MBR format.
424 @param This Calling context.
425 @param ParentHandle Parent Handle
426 @param ParentPciIo Parent PciIo interface
427 @param ParentLegacyBios Parent LegacyBios interface
428 @param ParentDevicePath Parent Device Path
429 @param RemainingDevicePath Remaining Device Path
431 @retval EFI_SUCCESS If a child handle was added
432 @retval other A child handle was not added
436 FbGopChildHandleInstall (
437 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
438 IN EFI_HANDLE ParentHandle
,
439 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
440 IN VOID
*ParentLegacyBios
,
441 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
442 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
446 FB_VIDEO_DEV
*FbGopPrivate
;
448 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
451 // Allocate the private device structure for video device
453 FbGopPrivate
= (FB_VIDEO_DEV
*) AllocateZeroPool (
454 sizeof (FB_VIDEO_DEV
)
456 if (NULL
== FbGopPrivate
) {
457 Status
= EFI_OUT_OF_RESOURCES
;
462 // See if this is a VGA compatible controller or not
464 Status
= ParentPciIo
->Pci
.Read (
468 sizeof (Pci
) / sizeof (UINT32
),
471 if (EFI_ERROR (Status
)) {
472 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
473 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
474 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
481 // Initialize the child private structure
483 FbGopPrivate
->Signature
= FB_VIDEO_DEV_SIGNATURE
;
486 // Fill in Graphics Output specific mode structures
488 FbGopPrivate
->ModeData
= NULL
;
490 FbGopPrivate
->VbeFrameBuffer
= NULL
;
492 FbGopPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
493 FbGopPrivate
->EdidDiscovered
.Edid
= NULL
;
494 FbGopPrivate
->EdidActive
.SizeOfEdid
= 0;
495 FbGopPrivate
->EdidActive
.Edid
= NULL
;
498 // Fill in the Graphics Output Protocol
500 FbGopPrivate
->GraphicsOutput
.QueryMode
= FbGopGraphicsOutputQueryMode
;
501 FbGopPrivate
->GraphicsOutput
.SetMode
= FbGopGraphicsOutputSetMode
;
505 // Allocate buffer for Graphics Output Protocol mode information
507 FbGopPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
508 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
510 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
) {
511 Status
= EFI_OUT_OF_RESOURCES
;
515 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
516 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
518 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
->Info
) {
519 Status
= EFI_OUT_OF_RESOURCES
;
524 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
526 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
527 if (RemainingDevicePath
== NULL
) {
528 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
529 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
530 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
531 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
532 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
534 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (
536 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
539 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
543 // Creat child handle and device path protocol firstly
545 FbGopPrivate
->Handle
= NULL
;
546 Status
= gBS
->InstallMultipleProtocolInterfaces (
547 &FbGopPrivate
->Handle
,
548 &gEfiDevicePathProtocolGuid
,
549 FbGopPrivate
->GopDevicePath
,
552 if (EFI_ERROR (Status
)) {
558 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
560 FbGopPrivate
->PciIo
= ParentPciIo
;
563 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
565 Status
= FbGopCheckForVbe (FbGopPrivate
);
566 DEBUG ((DEBUG_INFO
, "FbGopCheckForVbe - %r\n", Status
));
568 if (EFI_ERROR (Status
)) {
569 Status
= EFI_UNSUPPORTED
;
574 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
576 Status
= gBS
->InstallMultipleProtocolInterfaces (
577 &FbGopPrivate
->Handle
,
578 &gEfiGraphicsOutputProtocolGuid
,
579 &FbGopPrivate
->GraphicsOutput
,
580 &gEfiEdidDiscoveredProtocolGuid
,
581 &FbGopPrivate
->EdidDiscovered
,
582 &gEfiEdidActiveProtocolGuid
,
583 &FbGopPrivate
->EdidActive
,
587 if (!EFI_ERROR (Status
)) {
589 // Open the Parent Handle for the child
591 Status
= gBS
->OpenProtocol (
593 &gEfiPciIoProtocolGuid
,
594 (VOID
**) &FbGopPrivate
->PciIo
,
595 This
->DriverBindingHandle
,
596 FbGopPrivate
->Handle
,
597 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
599 if (EFI_ERROR (Status
)) {
605 if (EFI_ERROR (Status
)) {
607 // Free private data structure
609 FbGopDeviceReleaseResource (FbGopPrivate
);
617 Deregister an video child handle and free resources.
619 @param This Protocol instance pointer.
620 @param Controller Video controller handle
621 @param Handle Video child handle
627 FbGopChildHandleUninstall (
628 EFI_DRIVER_BINDING_PROTOCOL
*This
,
629 EFI_HANDLE Controller
,
634 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
635 FB_VIDEO_DEV
*FbGopPrivate
;
636 EFI_PCI_IO_PROTOCOL
*PciIo
;
639 GraphicsOutput
= NULL
;
641 Status
= EFI_UNSUPPORTED
;
643 Status
= gBS
->OpenProtocol (
645 &gEfiGraphicsOutputProtocolGuid
,
646 (VOID
**) &GraphicsOutput
,
647 This
->DriverBindingHandle
,
649 EFI_OPEN_PROTOCOL_GET_PROTOCOL
651 if (!EFI_ERROR (Status
)) {
652 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
655 if (FbGopPrivate
== NULL
) {
656 return EFI_UNSUPPORTED
;
660 // Close PCI I/O protocol that opened by child handle
662 Status
= gBS
->CloseProtocol (
664 &gEfiPciIoProtocolGuid
,
665 This
->DriverBindingHandle
,
670 // Uninstall protocols on child handle
672 Status
= gBS
->UninstallMultipleProtocolInterfaces (
673 FbGopPrivate
->Handle
,
674 &gEfiDevicePathProtocolGuid
,
675 FbGopPrivate
->GopDevicePath
,
676 &gEfiGraphicsOutputProtocolGuid
,
677 &FbGopPrivate
->GraphicsOutput
,
681 if (EFI_ERROR (Status
)) {
684 &gEfiPciIoProtocolGuid
,
686 This
->DriverBindingHandle
,
688 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
694 // Release all allocated resources
696 FbGopDeviceReleaseResource (FbGopPrivate
);
703 Release resource for bios video instance.
705 @param FbGopPrivate Video child device private data structure
709 FbGopDeviceReleaseResource (
710 FB_VIDEO_DEV
*FbGopPrivate
713 if (FbGopPrivate
== NULL
) {
718 // Release all the resources occupied by the FB_VIDEO_DEV
722 // Free VBE Frame Buffer
724 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
725 FreePool (FbGopPrivate
->VbeFrameBuffer
);
731 if (FbGopPrivate
->ModeData
!= NULL
) {
732 FreePool (FbGopPrivate
->ModeData
);
736 // Free graphics output protocol occupied resource
738 if (FbGopPrivate
->GraphicsOutput
.Mode
!= NULL
) {
739 if (FbGopPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
740 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
->Info
);
741 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
743 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
);
744 FbGopPrivate
->GraphicsOutput
.Mode
= NULL
;
747 if (FbGopPrivate
->GopDevicePath
!= NULL
) {
748 FreePool (FbGopPrivate
->GopDevicePath
);
751 FreePool (FbGopPrivate
);
759 Check if all video child handles have been uninstalled.
761 @param Controller Video controller handle
763 @return TRUE Child handles exist.
764 @return FALSE All video child handles have been uninstalled.
769 IN EFI_HANDLE Controller
773 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
779 gBS
->OpenProtocolInformation (
781 &gEfiPciIoProtocolGuid
,
785 for (Index
= 0; Index
< EntryCount
; Index
++) {
786 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
795 Check for VBE device.
797 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
799 @retval EFI_SUCCESS VBE device found
804 IN OUT FB_VIDEO_DEV
*FbGopPrivate
808 FB_VIDEO_MODE_DATA
*ModeBuffer
;
809 FB_VIDEO_MODE_DATA
*CurrentModeData
;
812 UINTN BytesPerScanLine
;
813 UINT32 HorizontalResolution
;
814 UINT32 VerticalResolution
;
815 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
816 FRAME_BUFFER_INFO
*FbInfo
;
818 Status
= EFI_SUCCESS
;
820 FbInfo
= mFrameBufferInfo
;
823 // Add mode to the list of available modes
825 VbeFrameBuffer
= NULL
;
829 BitsPerPixel
= FbInfo
->BitsPerPixel
;
830 HorizontalResolution
= FbInfo
->HorizontalResolution
;
831 VerticalResolution
= FbInfo
->VerticalResolution
;
832 BytesPerScanLine
= FbInfo
->BytesPerScanLine
;
834 ModeBuffer
= (FB_VIDEO_MODE_DATA
*) AllocatePool (
835 ModeNumber
* sizeof (FB_VIDEO_MODE_DATA
)
837 if (NULL
== ModeBuffer
) {
838 Status
= EFI_OUT_OF_RESOURCES
;
843 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
844 BytesPerScanLine
* VerticalResolution
846 if (NULL
== VbeFrameBuffer
) {
847 Status
= EFI_OUT_OF_RESOURCES
;
851 if (FbGopPrivate
->ModeData
!= NULL
) {
852 FreePool (FbGopPrivate
->ModeData
);
855 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
856 FreePool (FbGopPrivate
->VbeFrameBuffer
);
859 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
860 CurrentModeData
->BytesPerScanLine
= (UINT16
)BytesPerScanLine
;
862 CurrentModeData
->Red
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(FbInfo
->Red
);
863 CurrentModeData
->Blue
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(FbInfo
->Blue
);
864 CurrentModeData
->Green
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(FbInfo
->Green
);
865 CurrentModeData
->Reserved
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(FbInfo
->Reserved
);
867 CurrentModeData
->BitsPerPixel
= (UINT32
)BitsPerPixel
;
868 CurrentModeData
->HorizontalResolution
= HorizontalResolution
;
869 CurrentModeData
->VerticalResolution
= VerticalResolution
;
870 CurrentModeData
->FrameBufferSize
= CurrentModeData
->BytesPerScanLine
* CurrentModeData
->VerticalResolution
;
871 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
) FbInfo
->LinearFrameBuffer
;
872 CurrentModeData
->VbeModeNumber
= 0;
873 CurrentModeData
->ColorDepth
= 32;
874 CurrentModeData
->RefreshRate
= 60;
876 CurrentModeData
->PixelFormat
= PixelBitMask
;
877 if ((CurrentModeData
->BitsPerPixel
== 32) &&
878 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
879 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
880 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
881 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
882 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
886 CopyMem (&(CurrentModeData
->PixelBitMask
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
888 FbGopPrivate
->ModeData
= ModeBuffer
;
889 FbGopPrivate
->VbeFrameBuffer
= VbeFrameBuffer
;
892 // Assign Gop's Blt function
894 FbGopPrivate
->GraphicsOutput
.Blt
= FbGopGraphicsOutputVbeBlt
;
896 FbGopPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
897 FbGopPrivate
->GraphicsOutput
.Mode
->Mode
= 0;
898 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
899 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= HorizontalResolution
;
900 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= VerticalResolution
;
901 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= CurrentModeData
->PixelFormat
;
902 CopyMem (&(FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelInformation
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
903 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= (UINT32
)(BytesPerScanLine
* 8 / BitsPerPixel
);
904 FbGopPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
905 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CurrentModeData
->LinearFrameBuffer
;
906 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= CurrentModeData
->FrameBufferSize
;
909 // Find the best mode to initialize
914 // If there was an error, then free the mode structure
916 if (EFI_ERROR (Status
)) {
918 if (VbeFrameBuffer
!= NULL
) {
919 FreePool (VbeFrameBuffer
);
922 if (ModeBuffer
!= NULL
) {
923 FreePool (ModeBuffer
);
932 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
936 Graphics Output protocol interface to get video mode.
938 @param This Protocol instance pointer.
939 @param ModeNumber The mode number to return information on.
940 @param SizeOfInfo A pointer to the size, in bytes, of the Info
942 @param Info Caller allocated buffer that returns information
945 @retval EFI_SUCCESS Mode information returned.
946 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
948 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
949 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
954 FbGopGraphicsOutputQueryMode (
955 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
956 IN UINT32 ModeNumber
,
957 OUT UINTN
*SizeOfInfo
,
958 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
961 FB_VIDEO_DEV
*FbGopPrivate
;
962 FB_VIDEO_MODE_DATA
*ModeData
;
964 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
966 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
967 return EFI_INVALID_PARAMETER
;
970 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
971 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
974 return EFI_OUT_OF_RESOURCES
;
977 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
979 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
980 (*Info
)->Version
= 0;
981 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
982 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
983 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
984 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
986 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
992 Graphics Output protocol interface to set video mode.
994 @param This Protocol instance pointer.
995 @param ModeNumber The mode number to be set.
997 @retval EFI_SUCCESS Graphics mode was changed.
998 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1000 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1005 FbGopGraphicsOutputSetMode (
1006 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1007 IN UINT32 ModeNumber
1010 FB_VIDEO_DEV
*FbGopPrivate
;
1011 FB_VIDEO_MODE_DATA
*ModeData
;
1012 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1015 return EFI_INVALID_PARAMETER
;
1018 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1020 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
1022 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1023 return EFI_UNSUPPORTED
;
1026 if (ModeNumber
== This
->Mode
->Mode
) {
1028 // Clear screen to black
1030 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1031 FbGopGraphicsOutputVbeBlt (
1039 ModeData
->HorizontalResolution
,
1040 ModeData
->VerticalResolution
,
1045 return EFI_UNSUPPORTED
;
1051 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1053 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1054 @param VbeBuffer The data to transfer to screen
1055 @param MemAddress Physical frame buffer base address
1056 @param DestinationX The X coordinate of the destination for BltOperation
1057 @param DestinationY The Y coordinate of the destination for BltOperation
1058 @param TotalBytes The total bytes of copy
1059 @param VbePixelWidth Bytes per pixel
1060 @param BytesPerScanLine Bytes per scan line
1065 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1066 IN UINT8
*VbeBuffer
,
1067 IN VOID
*MemAddress
,
1068 IN UINTN DestinationX
,
1069 IN UINTN DestinationY
,
1070 IN UINTN TotalBytes
,
1071 IN UINT32 VbePixelWidth
,
1072 IN UINTN BytesPerScanLine
1075 UINTN FrameBufferAddr
;
1077 UINTN RemainingBytes
;
1078 UINTN UnalignedBytes
;
1081 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1084 // If TotalBytes is less than 4 bytes, only start byte copy.
1086 if (TotalBytes
< 4) {
1087 Status
= PciIo
->Mem
.Write (
1090 EFI_PCI_IO_PASS_THROUGH_BAR
,
1091 (UINT64
) FrameBufferAddr
,
1095 ASSERT_EFI_ERROR (Status
);
1100 // If VbeBuffer is not 4-byte aligned, start byte copy.
1102 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1104 if (UnalignedBytes
!= 0) {
1105 Status
= PciIo
->Mem
.Write (
1108 EFI_PCI_IO_PASS_THROUGH_BAR
,
1109 (UINT64
) FrameBufferAddr
,
1113 ASSERT_EFI_ERROR (Status
);
1114 FrameBufferAddr
+= UnalignedBytes
;
1115 VbeBuffer
+= UnalignedBytes
;
1119 // Calculate 4-byte block count and remaining bytes.
1121 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1122 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1125 // Copy 4-byte block and remaining bytes to physical frame buffer.
1127 if (CopyBlockNum
!= 0) {
1128 Status
= PciIo
->Mem
.Write (
1130 EfiPciIoWidthUint32
,
1131 EFI_PCI_IO_PASS_THROUGH_BAR
,
1132 (UINT64
) FrameBufferAddr
,
1136 ASSERT_EFI_ERROR (Status
);
1139 if (RemainingBytes
!= 0) {
1140 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1141 VbeBuffer
+= (CopyBlockNum
<< 2);
1142 Status
= PciIo
->Mem
.Write (
1145 EFI_PCI_IO_PASS_THROUGH_BAR
,
1146 (UINT64
) FrameBufferAddr
,
1150 ASSERT_EFI_ERROR (Status
);
1155 Worker function to block transfer for VBE device.
1157 @param FbGopPrivate Instance of FB_VIDEO_DEV
1158 @param BltBuffer The data to transfer to screen
1159 @param BltOperation The operation to perform
1160 @param SourceX The X coordinate of the source for BltOperation
1161 @param SourceY The Y coordinate of the source for BltOperation
1162 @param DestinationX The X coordinate of the destination for
1164 @param DestinationY The Y coordinate of the destination for
1166 @param Width The width of a rectangle in the blt rectangle in
1168 @param Height The height of a rectangle in the blt rectangle in
1170 @param Delta Not used for EfiBltVideoFill and
1171 EfiBltVideoToVideo operation. If a Delta of 0 is
1172 used, the entire BltBuffer will be operated on. If
1173 a subrectangle of the BltBuffer is used, then
1174 Delta represents the number of bytes in a row of
1176 @param Mode Mode data.
1178 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1179 @retval EFI_SUCCESS Blt operation success
1184 IN FB_VIDEO_DEV
*FbGopPrivate
,
1185 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1186 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1189 IN UINTN DestinationX
,
1190 IN UINTN DestinationY
,
1194 IN FB_VIDEO_MODE_DATA
*Mode
1197 EFI_PCI_IO_PROTOCOL
*PciIo
;
1198 EFI_TPL OriginalTPL
;
1202 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1204 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1205 UINTN BytesPerScanLine
;
1210 UINT32 VbePixelWidth
;
1214 PciIo
= FbGopPrivate
->PciIo
;
1216 VbeFrameBuffer
= FbGopPrivate
->VbeFrameBuffer
;
1217 MemAddress
= Mode
->LinearFrameBuffer
;
1218 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1219 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1220 BltUint8
= (UINT8
*) BltBuffer
;
1221 TotalBytes
= Width
* VbePixelWidth
;
1223 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1224 return EFI_INVALID_PARAMETER
;
1227 if (Width
== 0 || Height
== 0) {
1228 return EFI_INVALID_PARAMETER
;
1231 // We need to fill the Virtual Screen buffer with the blt data.
1232 // The virtual screen is upside down, as the first row is the bottom row of
1235 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1237 // Video to BltBuffer: Source is Video, destination is BltBuffer
1239 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1240 return EFI_INVALID_PARAMETER
;
1243 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1244 return EFI_INVALID_PARAMETER
;
1248 // BltBuffer to Video: Source is BltBuffer, destination is Video
1250 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1251 return EFI_INVALID_PARAMETER
;
1254 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1255 return EFI_INVALID_PARAMETER
;
1259 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1260 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1261 // the number of bytes in each row can be computed.
1264 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1267 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1268 // We would not want a timer based event (Cursor, ...) to come in while we are
1269 // doing this operation.
1271 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1273 switch (BltOperation
) {
1274 case EfiBltVideoToBltBuffer
:
1275 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1276 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1278 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1280 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1281 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1282 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
1283 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1284 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1285 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1288 VbeBuffer
+= VbePixelWidth
;
1294 case EfiBltVideoToVideo
:
1295 for (Index
= 0; Index
< Height
; Index
++) {
1296 if (DestinationY
<= SourceY
) {
1297 SrcY
= SourceY
+ Index
;
1298 DstY
= DestinationY
+ Index
;
1300 SrcY
= SourceY
+ Height
- Index
- 1;
1301 DstY
= DestinationY
+ Height
- Index
- 1;
1304 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
1305 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
1314 // Update physical frame buffer.
1329 case EfiBltVideoFill
:
1330 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1331 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
1333 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1335 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1337 (Blt
->Green
& Mode
->Green
.Mask
) <<
1338 Mode
->Green
.Position
1340 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1342 for (Index
= 0; Index
< Width
; Index
++) {
1348 VbeBuffer
+= VbePixelWidth
;
1351 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1352 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
1354 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
1360 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
1362 // Update physical frame buffer.
1377 case EfiBltBufferToVideo
:
1378 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
1379 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1380 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1381 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1383 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1385 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1386 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
1387 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1394 VbeBuffer
+= VbePixelWidth
;
1397 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1400 // Update physical frame buffer.
1418 gBS
->RestoreTPL (OriginalTPL
);
1424 Graphics Output protocol instance to block transfer for VBE device.
1426 @param This Pointer to Graphics Output protocol instance
1427 @param BltBuffer The data to transfer to screen
1428 @param BltOperation The operation to perform
1429 @param SourceX The X coordinate of the source for BltOperation
1430 @param SourceY The Y coordinate of the source for BltOperation
1431 @param DestinationX The X coordinate of the destination for
1433 @param DestinationY The Y coordinate of the destination for
1435 @param Width The width of a rectangle in the blt rectangle in
1437 @param Height The height of a rectangle in the blt rectangle in
1439 @param Delta Not used for EfiBltVideoFill and
1440 EfiBltVideoToVideo operation. If a Delta of 0 is
1441 used, the entire BltBuffer will be operated on. If
1442 a subrectangle of the BltBuffer is used, then
1443 Delta represents the number of bytes in a row of
1446 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1447 @retval EFI_SUCCESS Blt operation success
1452 FbGopGraphicsOutputVbeBlt (
1453 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1454 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1455 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1458 IN UINTN DestinationX
,
1459 IN UINTN DestinationY
,
1465 FB_VIDEO_DEV
*FbGopPrivate
;
1466 FB_VIDEO_MODE_DATA
*Mode
;
1469 return EFI_INVALID_PARAMETER
;
1472 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1473 Mode
= &FbGopPrivate
->ModeData
[This
->Mode
->Mode
];
1475 return FbGopVbeBltWorker (
1492 The user Entry Point for module UefiFbGop. The user code starts with this function.
1494 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1495 @param[in] SystemTable A pointer to the EFI System Table.
1497 @retval EFI_SUCCESS The entry point is executed successfully.
1498 @retval other Some error occurs when executing this entry point.
1504 IN EFI_HANDLE ImageHandle
,
1505 IN EFI_SYSTEM_TABLE
*SystemTable
1509 EFI_HOB_GUID_TYPE
*GuidHob
;
1512 // Find the frame buffer information guid hob
1514 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
1515 if (GuidHob
!= NULL
) {
1516 mFrameBufferInfo
= (FRAME_BUFFER_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
1519 // Install driver model protocol(s).
1521 Status
= EfiLibInstallDriverBindingComponentName2 (
1524 &gFbGopDriverBinding
,
1526 &gFbGopComponentName
,
1527 &gFbGopComponentName2
1529 ASSERT_EFI_ERROR (Status
);
1531 DEBUG ((DEBUG_ERROR
, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1532 Status
= EFI_ABORTED
;