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
;
439 // Allocate the private device structure for video device
441 FbGopPrivate
= (FB_VIDEO_DEV
*) AllocateZeroPool (
442 sizeof (FB_VIDEO_DEV
)
444 if (NULL
== FbGopPrivate
) {
445 Status
= EFI_OUT_OF_RESOURCES
;
450 // See if this is a VGA compatible controller or not
452 Status
= ParentPciIo
->Pci
.Read (
456 sizeof (Pci
) / sizeof (UINT32
),
459 if (EFI_ERROR (Status
)) {
460 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
461 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
462 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
469 // Initialize the child private structure
471 FbGopPrivate
->Signature
= FB_VIDEO_DEV_SIGNATURE
;
474 // Fill in Graphics Output specific mode structures
476 FbGopPrivate
->ModeData
= NULL
;
478 FbGopPrivate
->VbeFrameBuffer
= NULL
;
480 FbGopPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
481 FbGopPrivate
->EdidDiscovered
.Edid
= NULL
;
482 FbGopPrivate
->EdidActive
.SizeOfEdid
= 0;
483 FbGopPrivate
->EdidActive
.Edid
= NULL
;
486 // Fill in the Graphics Output Protocol
488 FbGopPrivate
->GraphicsOutput
.QueryMode
= FbGopGraphicsOutputQueryMode
;
489 FbGopPrivate
->GraphicsOutput
.SetMode
= FbGopGraphicsOutputSetMode
;
493 // Allocate buffer for Graphics Output Protocol mode information
495 FbGopPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
496 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
498 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
) {
499 Status
= EFI_OUT_OF_RESOURCES
;
503 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
504 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
506 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
->Info
) {
507 Status
= EFI_OUT_OF_RESOURCES
;
512 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
514 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
515 if (RemainingDevicePath
== NULL
) {
516 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
517 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
518 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
519 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
520 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
522 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (
524 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
527 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
531 // Creat child handle and device path protocol firstly
533 FbGopPrivate
->Handle
= NULL
;
534 Status
= gBS
->InstallMultipleProtocolInterfaces (
535 &FbGopPrivate
->Handle
,
536 &gEfiDevicePathProtocolGuid
,
537 FbGopPrivate
->GopDevicePath
,
540 if (EFI_ERROR (Status
)) {
546 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
548 FbGopPrivate
->PciIo
= ParentPciIo
;
551 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
553 Status
= FbGopCheckForVbe (FbGopPrivate
);
554 DEBUG ((EFI_D_INFO
, "FbGopCheckForVbe - %r\n", Status
));
556 if (EFI_ERROR (Status
)) {
557 Status
= EFI_UNSUPPORTED
;
562 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
564 Status
= gBS
->InstallMultipleProtocolInterfaces (
565 &FbGopPrivate
->Handle
,
566 &gEfiGraphicsOutputProtocolGuid
,
567 &FbGopPrivate
->GraphicsOutput
,
568 &gEfiEdidDiscoveredProtocolGuid
,
569 &FbGopPrivate
->EdidDiscovered
,
570 &gEfiEdidActiveProtocolGuid
,
571 &FbGopPrivate
->EdidActive
,
575 if (!EFI_ERROR (Status
)) {
577 // Open the Parent Handle for the child
579 Status
= gBS
->OpenProtocol (
581 &gEfiPciIoProtocolGuid
,
582 (VOID
**) &FbGopPrivate
->PciIo
,
583 This
->DriverBindingHandle
,
584 FbGopPrivate
->Handle
,
585 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
587 if (EFI_ERROR (Status
)) {
593 if (EFI_ERROR (Status
)) {
595 // Free private data structure
597 FbGopDeviceReleaseResource (FbGopPrivate
);
605 Deregister an video child handle and free resources.
607 @param This Protocol instance pointer.
608 @param Controller Video controller handle
609 @param Handle Video child handle
615 FbGopChildHandleUninstall (
616 EFI_DRIVER_BINDING_PROTOCOL
*This
,
617 EFI_HANDLE Controller
,
622 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
623 FB_VIDEO_DEV
*FbGopPrivate
;
624 EFI_PCI_IO_PROTOCOL
*PciIo
;
627 GraphicsOutput
= NULL
;
629 Status
= EFI_UNSUPPORTED
;
631 Status
= gBS
->OpenProtocol (
633 &gEfiGraphicsOutputProtocolGuid
,
634 (VOID
**) &GraphicsOutput
,
635 This
->DriverBindingHandle
,
637 EFI_OPEN_PROTOCOL_GET_PROTOCOL
639 if (!EFI_ERROR (Status
)) {
640 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
643 if (FbGopPrivate
== NULL
) {
644 return EFI_UNSUPPORTED
;
648 // Close PCI I/O protocol that opened by child handle
650 Status
= gBS
->CloseProtocol (
652 &gEfiPciIoProtocolGuid
,
653 This
->DriverBindingHandle
,
658 // Uninstall protocols on child handle
660 Status
= gBS
->UninstallMultipleProtocolInterfaces (
661 FbGopPrivate
->Handle
,
662 &gEfiDevicePathProtocolGuid
,
663 FbGopPrivate
->GopDevicePath
,
664 &gEfiGraphicsOutputProtocolGuid
,
665 &FbGopPrivate
->GraphicsOutput
,
669 if (EFI_ERROR (Status
)) {
672 &gEfiPciIoProtocolGuid
,
674 This
->DriverBindingHandle
,
676 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
682 // Release all allocated resources
684 FbGopDeviceReleaseResource (FbGopPrivate
);
691 Release resource for biso video instance.
693 @param FbGopPrivate Video child device private data structure
697 FbGopDeviceReleaseResource (
698 FB_VIDEO_DEV
*FbGopPrivate
701 if (FbGopPrivate
== NULL
) {
706 // Release all the resourses occupied by the FB_VIDEO_DEV
710 // Free VBE Frame Buffer
712 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
713 FreePool (FbGopPrivate
->VbeFrameBuffer
);
719 if (FbGopPrivate
->ModeData
!= NULL
) {
720 FreePool (FbGopPrivate
->ModeData
);
724 // Free graphics output protocol occupied resource
726 if (FbGopPrivate
->GraphicsOutput
.Mode
!= NULL
) {
727 if (FbGopPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
728 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
->Info
);
729 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
731 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
);
732 FbGopPrivate
->GraphicsOutput
.Mode
= NULL
;
735 if (FbGopPrivate
->GopDevicePath
!= NULL
) {
736 FreePool (FbGopPrivate
->GopDevicePath
);
739 FreePool (FbGopPrivate
);
747 Check if all video child handles have been uninstalled.
749 @param Controller Video controller handle
751 @return TRUE Child handles exist.
752 @return FALSE All video child handles have been uninstalled.
757 IN EFI_HANDLE Controller
761 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
767 gBS
->OpenProtocolInformation (
769 &gEfiPciIoProtocolGuid
,
773 for (Index
= 0; Index
< EntryCount
; Index
++) {
774 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
783 Check for VBE device.
785 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
787 @retval EFI_SUCCESS VBE device found
792 IN OUT FB_VIDEO_DEV
*FbGopPrivate
796 FB_VIDEO_MODE_DATA
*ModeBuffer
;
797 FB_VIDEO_MODE_DATA
*CurrentModeData
;
800 UINTN BytesPerScanLine
;
801 UINT32 HorizontalResolution
;
802 UINT32 VerticalResolution
;
803 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
804 EFI_HOB_GUID_TYPE
*GuidHob
;
805 FRAME_BUFFER_INFO
*pFbInfo
;
807 Status
= EFI_SUCCESS
;
809 // Find the frame buffer information guid hob
811 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
812 ASSERT (GuidHob
!= NULL
);
813 pFbInfo
= (FRAME_BUFFER_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
816 // Add mode to the list of available modes
818 VbeFrameBuffer
= NULL
;
822 BitsPerPixel
= pFbInfo
->BitsPerPixel
;
823 HorizontalResolution
= pFbInfo
->HorizontalResolution
;
824 VerticalResolution
= pFbInfo
->VerticalResolution
;
825 BytesPerScanLine
= HorizontalResolution
* (BitsPerPixel
/ 8);
827 ModeBuffer
= (FB_VIDEO_MODE_DATA
*) AllocatePool (
828 ModeNumber
* sizeof (FB_VIDEO_MODE_DATA
)
830 if (NULL
== ModeBuffer
) {
831 Status
= EFI_OUT_OF_RESOURCES
;
836 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
837 BytesPerScanLine
* VerticalResolution
839 if (NULL
== VbeFrameBuffer
) {
840 Status
= EFI_OUT_OF_RESOURCES
;
844 if (FbGopPrivate
->ModeData
!= NULL
) {
845 FreePool (FbGopPrivate
->ModeData
);
848 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
849 FreePool (FbGopPrivate
->VbeFrameBuffer
);
852 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
853 CurrentModeData
->BytesPerScanLine
= (UINT16
)BytesPerScanLine
;
855 CurrentModeData
->Red
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Red
);
856 CurrentModeData
->Blue
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Blue
);
857 CurrentModeData
->Green
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Green
);
858 CurrentModeData
->Reserved
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Reserved
);
860 CurrentModeData
->BitsPerPixel
= (UINT32
)BitsPerPixel
;
861 CurrentModeData
->HorizontalResolution
= HorizontalResolution
;
862 CurrentModeData
->VerticalResolution
= VerticalResolution
;
863 CurrentModeData
->FrameBufferSize
= CurrentModeData
->BytesPerScanLine
* CurrentModeData
->VerticalResolution
;
864 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
) pFbInfo
->LinearFrameBuffer
;
865 CurrentModeData
->VbeModeNumber
= 0;
866 CurrentModeData
->ColorDepth
= 32;
867 CurrentModeData
->RefreshRate
= 60;
869 CurrentModeData
->PixelFormat
= PixelBitMask
;
870 if ((CurrentModeData
->BitsPerPixel
== 32) &&
871 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
872 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
873 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
874 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
875 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
879 CopyMem (&(CurrentModeData
->PixelBitMask
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
881 FbGopPrivate
->ModeData
= ModeBuffer
;
882 FbGopPrivate
->VbeFrameBuffer
= VbeFrameBuffer
;
885 // Assign Gop's Blt function
887 FbGopPrivate
->GraphicsOutput
.Blt
= FbGopGraphicsOutputVbeBlt
;
889 FbGopPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
890 FbGopPrivate
->GraphicsOutput
.Mode
->Mode
= 0;
891 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
892 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= HorizontalResolution
;
893 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= VerticalResolution
;
894 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= CurrentModeData
->PixelFormat
;
895 CopyMem (&(FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelInformation
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
896 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= HorizontalResolution
;
897 FbGopPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
898 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CurrentModeData
->LinearFrameBuffer
;
899 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= CurrentModeData
->FrameBufferSize
;
902 // Find the best mode to initialize
907 // If there was an error, then free the mode structure
909 if (EFI_ERROR (Status
)) {
911 if (VbeFrameBuffer
!= NULL
) {
912 FreePool (VbeFrameBuffer
);
915 if (ModeBuffer
!= NULL
) {
916 FreePool (ModeBuffer
);
925 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
929 Graphics Output protocol interface to get video mode.
931 @param This Protocol instance pointer.
932 @param ModeNumber The mode number to return information on.
933 @param SizeOfInfo A pointer to the size, in bytes, of the Info
935 @param Info Caller allocated buffer that returns information
938 @retval EFI_SUCCESS Mode information returned.
939 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
941 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
942 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
947 FbGopGraphicsOutputQueryMode (
948 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
949 IN UINT32 ModeNumber
,
950 OUT UINTN
*SizeOfInfo
,
951 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
954 FB_VIDEO_DEV
*FbGopPrivate
;
955 FB_VIDEO_MODE_DATA
*ModeData
;
957 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
959 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
960 return EFI_INVALID_PARAMETER
;
963 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
964 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
967 return EFI_OUT_OF_RESOURCES
;
970 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
972 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
973 (*Info
)->Version
= 0;
974 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
975 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
976 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
977 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
979 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
985 Graphics Output protocol interface to set video mode.
987 @param This Protocol instance pointer.
988 @param ModeNumber The mode number to be set.
990 @retval EFI_SUCCESS Graphics mode was changed.
991 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
993 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
998 FbGopGraphicsOutputSetMode (
999 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1000 IN UINT32 ModeNumber
1003 FB_VIDEO_DEV
*FbGopPrivate
;
1004 FB_VIDEO_MODE_DATA
*ModeData
;
1005 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1008 return EFI_INVALID_PARAMETER
;
1011 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1013 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
1015 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1016 return EFI_UNSUPPORTED
;
1019 if (ModeNumber
== This
->Mode
->Mode
) {
1021 // Clear screen to black
1023 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1024 FbGopGraphicsOutputVbeBlt (
1032 ModeData
->HorizontalResolution
,
1033 ModeData
->VerticalResolution
,
1038 return EFI_UNSUPPORTED
;
1044 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1046 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1047 @param VbeBuffer The data to transfer to screen
1048 @param MemAddress Physical frame buffer base address
1049 @param DestinationX The X coordinate of the destination for BltOperation
1050 @param DestinationY The Y coordinate of the destination for BltOperation
1051 @param TotalBytes The total bytes of copy
1052 @param VbePixelWidth Bytes per pixel
1053 @param BytesPerScanLine Bytes per scan line
1058 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1059 IN UINT8
*VbeBuffer
,
1060 IN VOID
*MemAddress
,
1061 IN UINTN DestinationX
,
1062 IN UINTN DestinationY
,
1063 IN UINTN TotalBytes
,
1064 IN UINT32 VbePixelWidth
,
1065 IN UINTN BytesPerScanLine
1068 UINTN FrameBufferAddr
;
1070 UINTN RemainingBytes
;
1071 UINTN UnalignedBytes
;
1074 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1077 // If TotalBytes is less than 4 bytes, only start byte copy.
1079 if (TotalBytes
< 4) {
1080 Status
= PciIo
->Mem
.Write (
1083 EFI_PCI_IO_PASS_THROUGH_BAR
,
1084 (UINT64
) FrameBufferAddr
,
1088 ASSERT_EFI_ERROR (Status
);
1093 // If VbeBuffer is not 4-byte aligned, start byte copy.
1095 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1097 if (UnalignedBytes
!= 0) {
1098 Status
= PciIo
->Mem
.Write (
1101 EFI_PCI_IO_PASS_THROUGH_BAR
,
1102 (UINT64
) FrameBufferAddr
,
1106 ASSERT_EFI_ERROR (Status
);
1107 FrameBufferAddr
+= UnalignedBytes
;
1108 VbeBuffer
+= UnalignedBytes
;
1112 // Calculate 4-byte block count and remaining bytes.
1114 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1115 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1118 // Copy 4-byte block and remaining bytes to physical frame buffer.
1120 if (CopyBlockNum
!= 0) {
1121 Status
= PciIo
->Mem
.Write (
1123 EfiPciIoWidthUint32
,
1124 EFI_PCI_IO_PASS_THROUGH_BAR
,
1125 (UINT64
) FrameBufferAddr
,
1129 ASSERT_EFI_ERROR (Status
);
1132 if (RemainingBytes
!= 0) {
1133 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1134 VbeBuffer
+= (CopyBlockNum
<< 2);
1135 Status
= PciIo
->Mem
.Write (
1138 EFI_PCI_IO_PASS_THROUGH_BAR
,
1139 (UINT64
) FrameBufferAddr
,
1143 ASSERT_EFI_ERROR (Status
);
1148 Worker function to block transfer for VBE device.
1150 @param FbGopPrivate Instance of FB_VIDEO_DEV
1151 @param BltBuffer The data to transfer to screen
1152 @param BltOperation The operation to perform
1153 @param SourceX The X coordinate of the source for BltOperation
1154 @param SourceY The Y coordinate of the source for BltOperation
1155 @param DestinationX The X coordinate of the destination for
1157 @param DestinationY The Y coordinate of the destination for
1159 @param Width The width of a rectangle in the blt rectangle in
1161 @param Height The height of a rectangle in the blt rectangle in
1163 @param Delta Not used for EfiBltVideoFill and
1164 EfiBltVideoToVideo operation. If a Delta of 0 is
1165 used, the entire BltBuffer will be operated on. If
1166 a subrectangle of the BltBuffer is used, then
1167 Delta represents the number of bytes in a row of
1169 @param Mode Mode data.
1171 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1172 @retval EFI_SUCCESS Blt operation success
1177 IN FB_VIDEO_DEV
*FbGopPrivate
,
1178 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1179 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1182 IN UINTN DestinationX
,
1183 IN UINTN DestinationY
,
1187 IN FB_VIDEO_MODE_DATA
*Mode
1190 EFI_PCI_IO_PROTOCOL
*PciIo
;
1191 EFI_TPL OriginalTPL
;
1195 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1197 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1198 UINTN BytesPerScanLine
;
1203 UINT32 VbePixelWidth
;
1207 PciIo
= FbGopPrivate
->PciIo
;
1209 VbeFrameBuffer
= FbGopPrivate
->VbeFrameBuffer
;
1210 MemAddress
= Mode
->LinearFrameBuffer
;
1211 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1212 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1213 BltUint8
= (UINT8
*) BltBuffer
;
1214 TotalBytes
= Width
* VbePixelWidth
;
1216 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1217 return EFI_INVALID_PARAMETER
;
1220 if (Width
== 0 || Height
== 0) {
1221 return EFI_INVALID_PARAMETER
;
1224 // We need to fill the Virtual Screen buffer with the blt data.
1225 // The virtual screen is upside down, as the first row is the bootom row of
1228 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1230 // Video to BltBuffer: Source is Video, destination is BltBuffer
1232 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1233 return EFI_INVALID_PARAMETER
;
1236 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1237 return EFI_INVALID_PARAMETER
;
1241 // BltBuffer to Video: Source is BltBuffer, destination is Video
1243 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1244 return EFI_INVALID_PARAMETER
;
1247 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1248 return EFI_INVALID_PARAMETER
;
1252 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1253 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1254 // the number of bytes in each row can be computed.
1257 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1260 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1261 // We would not want a timer based event (Cursor, ...) to come in while we are
1262 // doing this operation.
1264 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1266 switch (BltOperation
) {
1267 case EfiBltVideoToBltBuffer
:
1268 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1269 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1271 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1273 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1274 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1275 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
1276 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1277 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1278 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1281 VbeBuffer
+= VbePixelWidth
;
1287 case EfiBltVideoToVideo
:
1288 for (Index
= 0; Index
< Height
; Index
++) {
1289 if (DestinationY
<= SourceY
) {
1290 SrcY
= SourceY
+ Index
;
1291 DstY
= DestinationY
+ Index
;
1293 SrcY
= SourceY
+ Height
- Index
- 1;
1294 DstY
= DestinationY
+ Height
- Index
- 1;
1297 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
1298 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
1307 // Update physical frame buffer.
1322 case EfiBltVideoFill
:
1323 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1324 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
1326 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1328 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1330 (Blt
->Green
& Mode
->Green
.Mask
) <<
1331 Mode
->Green
.Position
1333 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1335 for (Index
= 0; Index
< Width
; Index
++) {
1341 VbeBuffer
+= VbePixelWidth
;
1344 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1345 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
1347 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
1353 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
1355 // Update physical frame buffer.
1370 case EfiBltBufferToVideo
:
1371 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
1372 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1373 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1374 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1376 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1378 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1379 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
1380 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1387 VbeBuffer
+= VbePixelWidth
;
1390 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1393 // Update physical frame buffer.
1411 gBS
->RestoreTPL (OriginalTPL
);
1417 Graphics Output protocol instance to block transfer for VBE device.
1419 @param This Pointer to Graphics Output protocol instance
1420 @param BltBuffer The data to transfer to screen
1421 @param BltOperation The operation to perform
1422 @param SourceX The X coordinate of the source for BltOperation
1423 @param SourceY The Y coordinate of the source for BltOperation
1424 @param DestinationX The X coordinate of the destination for
1426 @param DestinationY The Y coordinate of the destination for
1428 @param Width The width of a rectangle in the blt rectangle in
1430 @param Height The height of a rectangle in the blt rectangle in
1432 @param Delta Not used for EfiBltVideoFill and
1433 EfiBltVideoToVideo operation. If a Delta of 0 is
1434 used, the entire BltBuffer will be operated on. If
1435 a subrectangle of the BltBuffer is used, then
1436 Delta represents the number of bytes in a row of
1439 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1440 @retval EFI_SUCCESS Blt operation success
1445 FbGopGraphicsOutputVbeBlt (
1446 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1447 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1448 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1451 IN UINTN DestinationX
,
1452 IN UINTN DestinationY
,
1458 FB_VIDEO_DEV
*FbGopPrivate
;
1459 FB_VIDEO_MODE_DATA
*Mode
;
1462 return EFI_INVALID_PARAMETER
;
1465 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1466 Mode
= &FbGopPrivate
->ModeData
[This
->Mode
->Mode
];
1468 return FbGopVbeBltWorker (
1485 The user Entry Point for module UefiFbGop. The user code starts with this function.
1487 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1488 @param[in] SystemTable A pointer to the EFI System Table.
1490 @retval EFI_SUCCESS The entry point is executed successfully.
1491 @retval other Some error occurs when executing this entry point.
1497 IN EFI_HANDLE ImageHandle
,
1498 IN EFI_SYSTEM_TABLE
*SystemTable
1502 EFI_HOB_GUID_TYPE
*GuidHob
;
1505 // Find the frame buffer information guid hob
1507 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
1508 if (GuidHob
!= NULL
) {
1510 // Install driver model protocol(s).
1512 Status
= EfiLibInstallDriverBindingComponentName2 (
1515 &gFbGopDriverBinding
,
1517 &gFbGopComponentName
,
1518 &gFbGopComponentName2
1520 ASSERT_EFI_ERROR (Status
);
1522 DEBUG ((EFI_D_ERROR
, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1523 Status
= EFI_ABORTED
;