2 ConsoleOut Routines that speak VGA.
4 Copyright (c) 2007 - 2013, Intel Corporation. All rights reserved.<BR>
6 This program and the accompanying materials
7 are licensed and made available under the terms and conditions
8 of the BSD License which accompanies this distribution. The
9 full text of the license may be found at
10 http://opensource.org/licenses/bsd-license.php
12 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
13 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
19 EFI_PIXEL_BITMASK mPixelBitMask
= {0x0000FF, 0x00FF00, 0xFF0000, 0x000000};
22 // Save controller attributes during first start
24 UINT64 mOriginalPciAttributes
;
25 BOOLEAN mPciAttributesSaved
= FALSE
;
29 // EFI Driver Binding Protocol Instance
31 EFI_DRIVER_BINDING_PROTOCOL gFbGopDriverBinding
= {
32 FbGopDriverBindingSupported
,
33 FbGopDriverBindingStart
,
34 FbGopDriverBindingStop
,
41 // Native resolution in EDID DetailedTiming[0]
43 UINT32 mNativeModeHorizontal
;
44 UINT32 mNativeModeVertical
;
49 @param This Pointer to driver binding protocol
50 @param Controller Controller handle to connect
51 @param RemainingDevicePath A pointer to the remaining portion of a device
54 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
55 driver, Otherwise, this controller cannot be
56 managed by this driver
61 FbGopDriverBindingSupported (
62 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
63 IN EFI_HANDLE Controller
,
64 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
68 EFI_PCI_IO_PROTOCOL
*PciIo
;
73 // Open the IO Abstraction(s) needed to perform the supported test
75 Status
= gBS
->OpenProtocol (
77 &gEfiPciIoProtocolGuid
,
79 This
->DriverBindingHandle
,
81 EFI_OPEN_PROTOCOL_BY_DRIVER
83 if (EFI_ERROR (Status
)) {
88 // See if this is a PCI Graphics Controller by looking at the Command register and
89 // Class Code Register
91 Status
= PciIo
->Pci
.Read (
95 sizeof (Pci
) / sizeof (UINT32
),
98 if (EFI_ERROR (Status
)) {
99 Status
= EFI_UNSUPPORTED
;
103 Status
= EFI_UNSUPPORTED
;
104 if (Pci
.Hdr
.ClassCode
[2] == 0x03 || (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01)) {
106 Status
= EFI_SUCCESS
;
108 // If this is a graphics controller,
109 // go further check RemainingDevicePath validation
111 if (RemainingDevicePath
!= NULL
) {
112 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
114 // Check if RemainingDevicePath is the End of Device Path Node,
115 // if yes, return EFI_SUCCESS
117 if (!IsDevicePathEnd (Node
)) {
119 // If RemainingDevicePath isn't the End of Device Path Node,
120 // check its validation
122 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
123 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
124 DevicePathNodeLength(&Node
->DevPath
) < sizeof(ACPI_ADR_DEVICE_PATH
)) {
125 Status
= EFI_UNSUPPORTED
;
134 &gEfiPciIoProtocolGuid
,
135 This
->DriverBindingHandle
,
144 Install Graphics Output Protocol onto VGA device handles.
146 @param This Pointer to driver binding protocol
147 @param Controller Controller handle to connect
148 @param RemainingDevicePath A pointer to the remaining portion of a device
156 FbGopDriverBindingStart (
157 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
158 IN EFI_HANDLE Controller
,
159 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
163 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
164 EFI_PCI_IO_PROTOCOL
*PciIo
;
167 DEBUG ((EFI_D_INFO
, "GOP START\n"));
170 // Initialize local variables
173 ParentDevicePath
= NULL
;
176 // Prepare for status code
178 Status
= gBS
->HandleProtocol (
180 &gEfiDevicePathProtocolGuid
,
181 (VOID
**) &ParentDevicePath
183 if (EFI_ERROR (Status
)) {
188 // Open the IO Abstraction(s) needed
190 Status
= gBS
->OpenProtocol (
192 &gEfiPciIoProtocolGuid
,
194 This
->DriverBindingHandle
,
196 EFI_OPEN_PROTOCOL_BY_DRIVER
198 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
203 // Save original PCI attributes
205 if (!mPciAttributesSaved
) {
206 Status
= PciIo
->Attributes (
208 EfiPciIoAttributeOperationGet
,
210 &mOriginalPciAttributes
213 if (EFI_ERROR (Status
)) {
216 mPciAttributesSaved
= TRUE
;
220 // Get supported PCI attributes
222 Status
= PciIo
->Attributes (
224 EfiPciIoAttributeOperationSupported
,
228 if (EFI_ERROR (Status
)) {
232 Supports
&= (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
233 if (Supports
== 0 || Supports
== (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
234 Status
= EFI_UNSUPPORTED
;
238 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
240 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_ENABLE
,
244 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
246 Status
= PciIo
->Attributes (
248 EfiPciIoAttributeOperationEnable
,
249 EFI_PCI_DEVICE_ENABLE
,
252 if (EFI_ERROR (Status
)) {
253 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
254 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
255 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_RESOURCE_CONFLICT
,
261 if (RemainingDevicePath
!= NULL
) {
262 if (IsDevicePathEnd (RemainingDevicePath
)) {
264 // If RemainingDevicePath is the End of Device Path Node,
265 // don't create any child device and return EFI_SUCESS
266 Status
= EFI_SUCCESS
;
272 // Create child handle and install GraphicsOutputProtocol on it
274 Status
= FbGopChildHandleInstall (
284 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
286 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
288 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_DISABLE
,
292 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
294 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_NOT_DETECTED
,
297 if (!HasChildHandle (Controller
)) {
298 if (mPciAttributesSaved
) {
300 // Restore original PCI attributes
304 EfiPciIoAttributeOperationSet
,
305 mOriginalPciAttributes
,
311 // Release PCI I/O Protocols on the controller handle.
315 &gEfiPciIoProtocolGuid
,
316 This
->DriverBindingHandle
,
328 @param This Pointer to driver binding protocol
329 @param Controller Controller handle to connect
330 @param NumberOfChildren Number of children handle created by this driver
331 @param ChildHandleBuffer Buffer containing child handle created
333 @retval EFI_SUCCESS Driver disconnected successfully from controller
334 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure
339 FbGopDriverBindingStop (
340 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
341 IN EFI_HANDLE Controller
,
342 IN UINTN NumberOfChildren
,
343 IN EFI_HANDLE
*ChildHandleBuffer
347 BOOLEAN AllChildrenStopped
;
349 EFI_PCI_IO_PROTOCOL
*PciIo
;
351 AllChildrenStopped
= TRUE
;
353 if (NumberOfChildren
== 0) {
355 // Close PCI I/O protocol on the controller handle
359 &gEfiPciIoProtocolGuid
,
360 This
->DriverBindingHandle
,
367 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
369 Status
= EFI_SUCCESS
;
371 FbGopChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
373 if (EFI_ERROR (Status
)) {
374 AllChildrenStopped
= FALSE
;
378 if (!AllChildrenStopped
) {
379 return EFI_DEVICE_ERROR
;
382 if (!HasChildHandle (Controller
)) {
383 if (mPciAttributesSaved
) {
384 Status
= gBS
->HandleProtocol (
386 &gEfiPciIoProtocolGuid
,
389 ASSERT_EFI_ERROR (Status
);
392 // Restore original PCI attributes
394 Status
= PciIo
->Attributes (
396 EfiPciIoAttributeOperationSet
,
397 mOriginalPciAttributes
,
400 ASSERT_EFI_ERROR (Status
);
410 Install child handles if the Handle supports MBR format.
412 @param This Calling context.
413 @param ParentHandle Parent Handle
414 @param ParentPciIo Parent PciIo interface
415 @param ParentLegacyBios Parent LegacyBios interface
416 @param ParentDevicePath Parent Device Path
417 @param RemainingDevicePath Remaining Device Path
419 @retval EFI_SUCCESS If a child handle was added
420 @retval other A child handle was not added
424 FbGopChildHandleInstall (
425 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
426 IN EFI_HANDLE ParentHandle
,
427 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
428 IN VOID
*ParentLegacyBios
,
429 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
430 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
434 FB_VIDEO_DEV
*FbGopPrivate
;
436 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
437 BOOLEAN ProtocolInstalled
;
440 // Allocate the private device structure for video device
442 FbGopPrivate
= (FB_VIDEO_DEV
*) AllocateZeroPool (
443 sizeof (FB_VIDEO_DEV
)
445 if (NULL
== FbGopPrivate
) {
446 Status
= EFI_OUT_OF_RESOURCES
;
451 // See if this is a VGA compatible controller or not
453 Status
= ParentPciIo
->Pci
.Read (
457 sizeof (Pci
) / sizeof (UINT32
),
460 if (EFI_ERROR (Status
)) {
461 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
462 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
463 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
470 // Initialize the child private structure
472 FbGopPrivate
->Signature
= FB_VIDEO_DEV_SIGNATURE
;
475 // Fill in Graphics Output specific mode structures
477 FbGopPrivate
->ModeData
= NULL
;
479 FbGopPrivate
->VbeFrameBuffer
= NULL
;
481 FbGopPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
482 FbGopPrivate
->EdidDiscovered
.Edid
= NULL
;
483 FbGopPrivate
->EdidActive
.SizeOfEdid
= 0;
484 FbGopPrivate
->EdidActive
.Edid
= NULL
;
487 // Fill in the Graphics Output Protocol
489 FbGopPrivate
->GraphicsOutput
.QueryMode
= FbGopGraphicsOutputQueryMode
;
490 FbGopPrivate
->GraphicsOutput
.SetMode
= FbGopGraphicsOutputSetMode
;
494 // Allocate buffer for Graphics Output Protocol mode information
496 FbGopPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
497 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
499 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
) {
500 Status
= EFI_OUT_OF_RESOURCES
;
504 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
505 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
507 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
->Info
) {
508 Status
= EFI_OUT_OF_RESOURCES
;
513 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
515 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
516 if (RemainingDevicePath
== NULL
) {
517 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
518 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
519 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
520 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
521 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
523 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (
525 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
528 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
532 // Creat child handle and device path protocol firstly
534 FbGopPrivate
->Handle
= NULL
;
535 Status
= gBS
->InstallMultipleProtocolInterfaces (
536 &FbGopPrivate
->Handle
,
537 &gEfiDevicePathProtocolGuid
,
538 FbGopPrivate
->GopDevicePath
,
541 if (EFI_ERROR (Status
)) {
547 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
549 FbGopPrivate
->PciIo
= ParentPciIo
;
552 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
554 Status
= FbGopCheckForVbe (FbGopPrivate
);
555 DEBUG ((EFI_D_INFO
, "FbGopCheckForVbe - %r\n", Status
));
557 if (EFI_ERROR (Status
)) {
558 Status
= EFI_UNSUPPORTED
;
562 ProtocolInstalled
= FALSE
;
565 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
567 Status
= gBS
->InstallMultipleProtocolInterfaces (
568 &FbGopPrivate
->Handle
,
569 &gEfiGraphicsOutputProtocolGuid
,
570 &FbGopPrivate
->GraphicsOutput
,
571 &gEfiEdidDiscoveredProtocolGuid
,
572 &FbGopPrivate
->EdidDiscovered
,
573 &gEfiEdidActiveProtocolGuid
,
574 &FbGopPrivate
->EdidActive
,
578 if (!EFI_ERROR (Status
)) {
580 // Open the Parent Handle for the child
582 Status
= gBS
->OpenProtocol (
584 &gEfiPciIoProtocolGuid
,
585 (VOID
**) &FbGopPrivate
->PciIo
,
586 This
->DriverBindingHandle
,
587 FbGopPrivate
->Handle
,
588 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
590 if (EFI_ERROR (Status
)) {
593 ProtocolInstalled
= TRUE
;
597 if (EFI_ERROR (Status
)) {
599 // Free private data structure
601 FbGopDeviceReleaseResource (FbGopPrivate
);
609 Deregister an video child handle and free resources.
611 @param This Protocol instance pointer.
612 @param Controller Video controller handle
613 @param Handle Video child handle
619 FbGopChildHandleUninstall (
620 EFI_DRIVER_BINDING_PROTOCOL
*This
,
621 EFI_HANDLE Controller
,
626 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
627 FB_VIDEO_DEV
*FbGopPrivate
;
628 EFI_PCI_IO_PROTOCOL
*PciIo
;
631 GraphicsOutput
= NULL
;
633 Status
= EFI_UNSUPPORTED
;
635 Status
= gBS
->OpenProtocol (
637 &gEfiGraphicsOutputProtocolGuid
,
638 (VOID
**) &GraphicsOutput
,
639 This
->DriverBindingHandle
,
641 EFI_OPEN_PROTOCOL_GET_PROTOCOL
643 if (!EFI_ERROR (Status
)) {
644 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
647 if (FbGopPrivate
== NULL
) {
648 return EFI_UNSUPPORTED
;
652 // Close PCI I/O protocol that opened by child handle
654 Status
= gBS
->CloseProtocol (
656 &gEfiPciIoProtocolGuid
,
657 This
->DriverBindingHandle
,
662 // Uninstall protocols on child handle
664 Status
= gBS
->UninstallMultipleProtocolInterfaces (
665 FbGopPrivate
->Handle
,
666 &gEfiDevicePathProtocolGuid
,
667 FbGopPrivate
->GopDevicePath
,
668 &gEfiGraphicsOutputProtocolGuid
,
669 &FbGopPrivate
->GraphicsOutput
,
673 if (EFI_ERROR (Status
)) {
676 &gEfiPciIoProtocolGuid
,
678 This
->DriverBindingHandle
,
680 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
686 // Release all allocated resources
688 FbGopDeviceReleaseResource (FbGopPrivate
);
695 Release resource for biso video instance.
697 @param FbGopPrivate Video child device private data structure
701 FbGopDeviceReleaseResource (
702 FB_VIDEO_DEV
*FbGopPrivate
705 if (FbGopPrivate
== NULL
) {
710 // Release all the resourses occupied by the FB_VIDEO_DEV
714 // Free VBE Frame Buffer
716 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
717 FreePool (FbGopPrivate
->VbeFrameBuffer
);
723 if (FbGopPrivate
->ModeData
!= NULL
) {
724 FreePool (FbGopPrivate
->ModeData
);
728 // Free graphics output protocol occupied resource
730 if (FbGopPrivate
->GraphicsOutput
.Mode
!= NULL
) {
731 if (FbGopPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
732 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
->Info
);
733 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
735 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
);
736 FbGopPrivate
->GraphicsOutput
.Mode
= NULL
;
739 if (FbGopPrivate
->GopDevicePath
!= NULL
) {
740 FreePool (FbGopPrivate
->GopDevicePath
);
743 FreePool (FbGopPrivate
);
751 Check if all video child handles have been uninstalled.
753 @param Controller Video controller handle
755 @return TRUE Child handles exist.
756 @return FALSE All video child handles have been uninstalled.
761 IN EFI_HANDLE Controller
765 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
772 Status
= gBS
->OpenProtocolInformation (
774 &gEfiPciIoProtocolGuid
,
778 for (Index
= 0; Index
< EntryCount
; Index
++) {
779 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
788 Check for VBE device.
790 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
792 @retval EFI_SUCCESS VBE device found
797 IN OUT FB_VIDEO_DEV
*FbGopPrivate
801 FB_VIDEO_MODE_DATA
*ModeBuffer
;
802 FB_VIDEO_MODE_DATA
*CurrentModeData
;
805 UINTN BytesPerScanLine
;
806 UINT32 HorizontalResolution
;
807 UINT32 VerticalResolution
;
808 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
809 EFI_HOB_GUID_TYPE
*GuidHob
;
810 FRAME_BUFFER_INFO
*pFbInfo
;
812 Status
= EFI_SUCCESS
;
814 // Find the frame buffer information guid hob
816 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
817 ASSERT (GuidHob
!= NULL
);
818 pFbInfo
= (FRAME_BUFFER_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
821 // Add mode to the list of available modes
823 VbeFrameBuffer
= NULL
;
827 BitsPerPixel
= pFbInfo
->BitsPerPixel
;
828 HorizontalResolution
= pFbInfo
->HorizontalResolution
;
829 VerticalResolution
= pFbInfo
->VerticalResolution
;
830 BytesPerScanLine
= HorizontalResolution
* (BitsPerPixel
/ 8);
832 ModeBuffer
= (FB_VIDEO_MODE_DATA
*) AllocatePool (
833 ModeNumber
* sizeof (FB_VIDEO_MODE_DATA
)
835 if (NULL
== ModeBuffer
) {
836 Status
= EFI_OUT_OF_RESOURCES
;
841 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
842 BytesPerScanLine
* VerticalResolution
844 if (NULL
== VbeFrameBuffer
) {
845 Status
= EFI_OUT_OF_RESOURCES
;
849 if (FbGopPrivate
->ModeData
!= NULL
) {
850 FreePool (FbGopPrivate
->ModeData
);
853 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
854 FreePool (FbGopPrivate
->VbeFrameBuffer
);
857 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
858 CurrentModeData
->BytesPerScanLine
= (UINT16
)BytesPerScanLine
;
860 CurrentModeData
->Red
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Red
);
861 CurrentModeData
->Blue
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Blue
);
862 CurrentModeData
->Green
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Green
);
863 CurrentModeData
->Reserved
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Reserved
);
865 CurrentModeData
->BitsPerPixel
= (UINT32
)BitsPerPixel
;
866 CurrentModeData
->HorizontalResolution
= HorizontalResolution
;
867 CurrentModeData
->VerticalResolution
= VerticalResolution
;
868 CurrentModeData
->FrameBufferSize
= CurrentModeData
->BytesPerScanLine
* CurrentModeData
->VerticalResolution
;
869 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
) pFbInfo
->LinearFrameBuffer
;
870 CurrentModeData
->VbeModeNumber
= 0;
871 CurrentModeData
->ColorDepth
= 32;
872 CurrentModeData
->RefreshRate
= 60;
874 CurrentModeData
->PixelFormat
= PixelBitMask
;
875 if ((CurrentModeData
->BitsPerPixel
== 32) &&
876 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
877 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
878 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
879 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
880 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
884 CopyMem (&(CurrentModeData
->PixelBitMask
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
886 FbGopPrivate
->ModeData
= ModeBuffer
;
887 FbGopPrivate
->VbeFrameBuffer
= VbeFrameBuffer
;
890 // Assign Gop's Blt function
892 FbGopPrivate
->GraphicsOutput
.Blt
= FbGopGraphicsOutputVbeBlt
;
894 FbGopPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
895 FbGopPrivate
->GraphicsOutput
.Mode
->Mode
= 0;
896 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
897 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= HorizontalResolution
;
898 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= VerticalResolution
;
899 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= CurrentModeData
->PixelFormat
;
900 CopyMem (&(FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelInformation
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
901 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= HorizontalResolution
;
902 FbGopPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
903 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CurrentModeData
->LinearFrameBuffer
;
904 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= CurrentModeData
->FrameBufferSize
;
907 // Find the best mode to initialize
912 // If there was an error, then free the mode structure
914 if (EFI_ERROR (Status
)) {
916 if (VbeFrameBuffer
!= NULL
) {
917 FreePool (VbeFrameBuffer
);
920 if (ModeBuffer
!= NULL
) {
921 FreePool (ModeBuffer
);
930 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
934 Graphics Output protocol interface to get video mode.
936 @param This Protocol instance pointer.
937 @param ModeNumber The mode number to return information on.
938 @param SizeOfInfo A pointer to the size, in bytes, of the Info
940 @param Info Caller allocated buffer that returns information
943 @retval EFI_SUCCESS Mode information returned.
944 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
946 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
947 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
952 FbGopGraphicsOutputQueryMode (
953 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
954 IN UINT32 ModeNumber
,
955 OUT UINTN
*SizeOfInfo
,
956 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
959 FB_VIDEO_DEV
*FbGopPrivate
;
960 FB_VIDEO_MODE_DATA
*ModeData
;
962 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
964 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
965 return EFI_INVALID_PARAMETER
;
968 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
969 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
972 return EFI_OUT_OF_RESOURCES
;
975 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
977 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
978 (*Info
)->Version
= 0;
979 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
980 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
981 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
982 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
984 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
990 Graphics Output protocol interface to set video mode.
992 @param This Protocol instance pointer.
993 @param ModeNumber The mode number to be set.
995 @retval EFI_SUCCESS Graphics mode was changed.
996 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
998 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1003 FbGopGraphicsOutputSetMode (
1004 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1005 IN UINT32 ModeNumber
1008 FB_VIDEO_DEV
*FbGopPrivate
;
1009 FB_VIDEO_MODE_DATA
*ModeData
;
1010 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1013 return EFI_INVALID_PARAMETER
;
1016 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1018 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
1020 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1021 return EFI_UNSUPPORTED
;
1024 if (ModeNumber
== This
->Mode
->Mode
) {
1026 // Clear screen to black
1028 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1029 FbGopGraphicsOutputVbeBlt (
1037 ModeData
->HorizontalResolution
,
1038 ModeData
->VerticalResolution
,
1043 return EFI_UNSUPPORTED
;
1049 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1051 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1052 @param VbeBuffer The data to transfer to screen
1053 @param MemAddress Physical frame buffer base address
1054 @param DestinationX The X coordinate of the destination for BltOperation
1055 @param DestinationY The Y coordinate of the destination for BltOperation
1056 @param TotalBytes The total bytes of copy
1057 @param VbePixelWidth Bytes per pixel
1058 @param BytesPerScanLine Bytes per scan line
1063 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1064 IN UINT8
*VbeBuffer
,
1065 IN VOID
*MemAddress
,
1066 IN UINTN DestinationX
,
1067 IN UINTN DestinationY
,
1068 IN UINTN TotalBytes
,
1069 IN UINT32 VbePixelWidth
,
1070 IN UINTN BytesPerScanLine
1073 UINTN FrameBufferAddr
;
1075 UINTN RemainingBytes
;
1076 UINTN UnalignedBytes
;
1079 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1082 // If TotalBytes is less than 4 bytes, only start byte copy.
1084 if (TotalBytes
< 4) {
1085 Status
= PciIo
->Mem
.Write (
1088 EFI_PCI_IO_PASS_THROUGH_BAR
,
1089 (UINT64
) FrameBufferAddr
,
1093 ASSERT_EFI_ERROR (Status
);
1098 // If VbeBuffer is not 4-byte aligned, start byte copy.
1100 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1102 if (UnalignedBytes
!= 0) {
1103 Status
= PciIo
->Mem
.Write (
1106 EFI_PCI_IO_PASS_THROUGH_BAR
,
1107 (UINT64
) FrameBufferAddr
,
1111 ASSERT_EFI_ERROR (Status
);
1112 FrameBufferAddr
+= UnalignedBytes
;
1113 VbeBuffer
+= UnalignedBytes
;
1117 // Calculate 4-byte block count and remaining bytes.
1119 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1120 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1123 // Copy 4-byte block and remaining bytes to physical frame buffer.
1125 if (CopyBlockNum
!= 0) {
1126 Status
= PciIo
->Mem
.Write (
1128 EfiPciIoWidthUint32
,
1129 EFI_PCI_IO_PASS_THROUGH_BAR
,
1130 (UINT64
) FrameBufferAddr
,
1134 ASSERT_EFI_ERROR (Status
);
1137 if (RemainingBytes
!= 0) {
1138 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1139 VbeBuffer
+= (CopyBlockNum
<< 2);
1140 Status
= PciIo
->Mem
.Write (
1143 EFI_PCI_IO_PASS_THROUGH_BAR
,
1144 (UINT64
) FrameBufferAddr
,
1148 ASSERT_EFI_ERROR (Status
);
1153 Worker function to block transfer for VBE device.
1155 @param FbGopPrivate Instance of FB_VIDEO_DEV
1156 @param BltBuffer The data to transfer to screen
1157 @param BltOperation The operation to perform
1158 @param SourceX The X coordinate of the source for BltOperation
1159 @param SourceY The Y coordinate of the source for BltOperation
1160 @param DestinationX The X coordinate of the destination for
1162 @param DestinationY The Y coordinate of the destination for
1164 @param Width The width of a rectangle in the blt rectangle in
1166 @param Height The height of a rectangle in the blt rectangle in
1168 @param Delta Not used for EfiBltVideoFill and
1169 EfiBltVideoToVideo operation. If a Delta of 0 is
1170 used, the entire BltBuffer will be operated on. If
1171 a subrectangle of the BltBuffer is used, then
1172 Delta represents the number of bytes in a row of
1174 @param Mode Mode data.
1176 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1177 @retval EFI_SUCCESS Blt operation success
1182 IN FB_VIDEO_DEV
*FbGopPrivate
,
1183 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1184 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1187 IN UINTN DestinationX
,
1188 IN UINTN DestinationY
,
1192 IN FB_VIDEO_MODE_DATA
*Mode
1195 EFI_PCI_IO_PROTOCOL
*PciIo
;
1196 EFI_TPL OriginalTPL
;
1200 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1202 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1203 UINTN BytesPerScanLine
;
1208 UINT32 VbePixelWidth
;
1212 PciIo
= FbGopPrivate
->PciIo
;
1214 VbeFrameBuffer
= FbGopPrivate
->VbeFrameBuffer
;
1215 MemAddress
= Mode
->LinearFrameBuffer
;
1216 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1217 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1218 BltUint8
= (UINT8
*) BltBuffer
;
1219 TotalBytes
= Width
* VbePixelWidth
;
1221 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1222 return EFI_INVALID_PARAMETER
;
1225 if (Width
== 0 || Height
== 0) {
1226 return EFI_INVALID_PARAMETER
;
1229 // We need to fill the Virtual Screen buffer with the blt data.
1230 // The virtual screen is upside down, as the first row is the bootom row of
1233 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1235 // Video to BltBuffer: Source is Video, destination is BltBuffer
1237 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1238 return EFI_INVALID_PARAMETER
;
1241 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1242 return EFI_INVALID_PARAMETER
;
1246 // BltBuffer to Video: Source is BltBuffer, destination is Video
1248 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1249 return EFI_INVALID_PARAMETER
;
1252 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1253 return EFI_INVALID_PARAMETER
;
1257 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1258 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1259 // the number of bytes in each row can be computed.
1262 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1265 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1266 // We would not want a timer based event (Cursor, ...) to come in while we are
1267 // doing this operation.
1269 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1271 switch (BltOperation
) {
1272 case EfiBltVideoToBltBuffer
:
1273 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1274 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1276 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1278 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1279 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1280 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
1281 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1282 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1283 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1286 VbeBuffer
+= VbePixelWidth
;
1292 case EfiBltVideoToVideo
:
1293 for (Index
= 0; Index
< Height
; Index
++) {
1294 if (DestinationY
<= SourceY
) {
1295 SrcY
= SourceY
+ Index
;
1296 DstY
= DestinationY
+ Index
;
1298 SrcY
= SourceY
+ Height
- Index
- 1;
1299 DstY
= DestinationY
+ Height
- Index
- 1;
1302 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
1303 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
1312 // Update physical frame buffer.
1327 case EfiBltVideoFill
:
1328 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1329 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
1331 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1333 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1335 (Blt
->Green
& Mode
->Green
.Mask
) <<
1336 Mode
->Green
.Position
1338 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1340 for (Index
= 0; Index
< Width
; Index
++) {
1346 VbeBuffer
+= VbePixelWidth
;
1349 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1350 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
1352 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
1358 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
1360 // Update physical frame buffer.
1375 case EfiBltBufferToVideo
:
1376 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
1377 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1378 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1379 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1381 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1383 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1384 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
1385 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1392 VbeBuffer
+= VbePixelWidth
;
1395 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1398 // Update physical frame buffer.
1416 gBS
->RestoreTPL (OriginalTPL
);
1422 Graphics Output protocol instance to block transfer for VBE device.
1424 @param This Pointer to Graphics Output protocol instance
1425 @param BltBuffer The data to transfer to screen
1426 @param BltOperation The operation to perform
1427 @param SourceX The X coordinate of the source for BltOperation
1428 @param SourceY The Y coordinate of the source for BltOperation
1429 @param DestinationX The X coordinate of the destination for
1431 @param DestinationY The Y coordinate of the destination for
1433 @param Width The width of a rectangle in the blt rectangle in
1435 @param Height The height of a rectangle in the blt rectangle in
1437 @param Delta Not used for EfiBltVideoFill and
1438 EfiBltVideoToVideo operation. If a Delta of 0 is
1439 used, the entire BltBuffer will be operated on. If
1440 a subrectangle of the BltBuffer is used, then
1441 Delta represents the number of bytes in a row of
1444 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1445 @retval EFI_SUCCESS Blt operation success
1450 FbGopGraphicsOutputVbeBlt (
1451 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1452 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1453 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1456 IN UINTN DestinationX
,
1457 IN UINTN DestinationY
,
1463 FB_VIDEO_DEV
*FbGopPrivate
;
1464 FB_VIDEO_MODE_DATA
*Mode
;
1467 return EFI_INVALID_PARAMETER
;
1470 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1471 Mode
= &FbGopPrivate
->ModeData
[This
->Mode
->Mode
];
1473 return FbGopVbeBltWorker (
1490 The user Entry Point for module UefiFbGop. The user code starts with this function.
1492 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1493 @param[in] SystemTable A pointer to the EFI System Table.
1495 @retval EFI_SUCCESS The entry point is executed successfully.
1496 @retval other Some error occurs when executing this entry point.
1502 IN EFI_HANDLE ImageHandle
,
1503 IN EFI_SYSTEM_TABLE
*SystemTable
1507 EFI_HOB_GUID_TYPE
*GuidHob
;
1510 // Find the frame buffer information guid hob
1512 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
1513 if (GuidHob
!= NULL
) {
1515 // Install driver model protocol(s).
1517 Status
= EfiLibInstallDriverBindingComponentName2 (
1520 &gFbGopDriverBinding
,
1522 &gFbGopComponentName
,
1523 &gFbGopComponentName2
1525 ASSERT_EFI_ERROR (Status
);
1527 DEBUG ((EFI_D_ERROR
, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1528 Status
= EFI_ABORTED
;