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
;
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
;
66 // Open the IO Abstraction(s) needed to perform the supported test
68 Status
= gBS
->OpenProtocol (
70 &gEfiPciIoProtocolGuid
,
72 This
->DriverBindingHandle
,
74 EFI_OPEN_PROTOCOL_BY_DRIVER
76 if (EFI_ERROR (Status
)) {
81 // See if this is a PCI Graphics Controller by looking at the Command register and
82 // Class Code Register
84 Status
= PciIo
->Pci
.Read (
88 sizeof (Pci
) / sizeof (UINT32
),
91 if (EFI_ERROR (Status
)) {
92 Status
= EFI_UNSUPPORTED
;
96 Status
= EFI_UNSUPPORTED
;
97 if (Pci
.Hdr
.ClassCode
[2] == 0x03 || (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01)) {
101 // If this is a graphics controller,
102 // go further check RemainingDevicePath validation
104 if (RemainingDevicePath
!= NULL
) {
105 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
107 // Check if RemainingDevicePath is the End of Device Path Node,
108 // if yes, return EFI_SUCCESS
110 if (!IsDevicePathEnd (Node
)) {
112 // If RemainingDevicePath isn't the End of Device Path Node,
113 // check its validation
115 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
116 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
117 DevicePathNodeLength(&Node
->DevPath
) < sizeof(ACPI_ADR_DEVICE_PATH
)) {
118 Status
= EFI_UNSUPPORTED
;
127 &gEfiPciIoProtocolGuid
,
128 This
->DriverBindingHandle
,
137 Install Graphics Output Protocol onto VGA device handles.
139 @param This Pointer to driver binding protocol
140 @param Controller Controller handle to connect
141 @param RemainingDevicePath A pointer to the remaining portion of a device
149 FbGopDriverBindingStart (
150 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
151 IN EFI_HANDLE Controller
,
152 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
156 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
157 EFI_PCI_IO_PROTOCOL
*PciIo
;
160 DEBUG ((EFI_D_INFO
, "GOP START\n"));
163 // Initialize local variables
166 ParentDevicePath
= NULL
;
169 // Prepare for status code
171 Status
= gBS
->HandleProtocol (
173 &gEfiDevicePathProtocolGuid
,
174 (VOID
**) &ParentDevicePath
176 if (EFI_ERROR (Status
)) {
181 // Open the IO Abstraction(s) needed
183 Status
= gBS
->OpenProtocol (
185 &gEfiPciIoProtocolGuid
,
187 This
->DriverBindingHandle
,
189 EFI_OPEN_PROTOCOL_BY_DRIVER
191 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
196 // Save original PCI attributes
198 if (!mPciAttributesSaved
) {
199 Status
= PciIo
->Attributes (
201 EfiPciIoAttributeOperationGet
,
203 &mOriginalPciAttributes
206 if (EFI_ERROR (Status
)) {
209 mPciAttributesSaved
= TRUE
;
213 // Get supported PCI attributes
215 Status
= PciIo
->Attributes (
217 EfiPciIoAttributeOperationSupported
,
221 if (EFI_ERROR (Status
)) {
225 Supports
&= (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
226 if (Supports
== 0 || Supports
== (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
227 Status
= EFI_UNSUPPORTED
;
231 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
233 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_ENABLE
,
237 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
239 Status
= PciIo
->Attributes (
241 EfiPciIoAttributeOperationEnable
,
242 EFI_PCI_DEVICE_ENABLE
,
245 if (EFI_ERROR (Status
)) {
246 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
247 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
248 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_RESOURCE_CONFLICT
,
254 if (RemainingDevicePath
!= NULL
) {
255 if (IsDevicePathEnd (RemainingDevicePath
)) {
257 // If RemainingDevicePath is the End of Device Path Node,
258 // don't create any child device and return EFI_SUCCESS
259 Status
= EFI_SUCCESS
;
265 // Create child handle and install GraphicsOutputProtocol on it
267 Status
= FbGopChildHandleInstall (
277 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
279 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
281 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_DISABLE
,
285 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
287 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_NOT_DETECTED
,
290 if (!HasChildHandle (Controller
)) {
291 if (mPciAttributesSaved
) {
293 // Restore original PCI attributes
297 EfiPciIoAttributeOperationSet
,
298 mOriginalPciAttributes
,
304 // Release PCI I/O Protocols on the controller handle.
308 &gEfiPciIoProtocolGuid
,
309 This
->DriverBindingHandle
,
321 @param This Pointer to driver binding protocol
322 @param Controller Controller handle to connect
323 @param NumberOfChildren Number of children handle created by this driver
324 @param ChildHandleBuffer Buffer containing child handle created
326 @retval EFI_SUCCESS Driver disconnected successfully from controller
327 @retval EFI_UNSUPPORTED Cannot find FB_VIDEO_DEV structure
332 FbGopDriverBindingStop (
333 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
334 IN EFI_HANDLE Controller
,
335 IN UINTN NumberOfChildren
,
336 IN EFI_HANDLE
*ChildHandleBuffer
340 BOOLEAN AllChildrenStopped
;
342 EFI_PCI_IO_PROTOCOL
*PciIo
;
344 AllChildrenStopped
= TRUE
;
346 if (NumberOfChildren
== 0) {
348 // Close PCI I/O protocol on the controller handle
352 &gEfiPciIoProtocolGuid
,
353 This
->DriverBindingHandle
,
360 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
362 Status
= EFI_SUCCESS
;
364 FbGopChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
366 if (EFI_ERROR (Status
)) {
367 AllChildrenStopped
= FALSE
;
371 if (!AllChildrenStopped
) {
372 return EFI_DEVICE_ERROR
;
375 if (!HasChildHandle (Controller
)) {
376 if (mPciAttributesSaved
) {
377 Status
= gBS
->HandleProtocol (
379 &gEfiPciIoProtocolGuid
,
382 ASSERT_EFI_ERROR (Status
);
385 // Restore original PCI attributes
387 Status
= PciIo
->Attributes (
389 EfiPciIoAttributeOperationSet
,
390 mOriginalPciAttributes
,
393 ASSERT_EFI_ERROR (Status
);
403 Install child handles if the Handle supports MBR format.
405 @param This Calling context.
406 @param ParentHandle Parent Handle
407 @param ParentPciIo Parent PciIo interface
408 @param ParentLegacyBios Parent LegacyBios interface
409 @param ParentDevicePath Parent Device Path
410 @param RemainingDevicePath Remaining Device Path
412 @retval EFI_SUCCESS If a child handle was added
413 @retval other A child handle was not added
417 FbGopChildHandleInstall (
418 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
419 IN EFI_HANDLE ParentHandle
,
420 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
421 IN VOID
*ParentLegacyBios
,
422 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
423 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
427 FB_VIDEO_DEV
*FbGopPrivate
;
429 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
432 // Allocate the private device structure for video device
434 FbGopPrivate
= (FB_VIDEO_DEV
*) AllocateZeroPool (
435 sizeof (FB_VIDEO_DEV
)
437 if (NULL
== FbGopPrivate
) {
438 Status
= EFI_OUT_OF_RESOURCES
;
443 // See if this is a VGA compatible controller or not
445 Status
= ParentPciIo
->Pci
.Read (
449 sizeof (Pci
) / sizeof (UINT32
),
452 if (EFI_ERROR (Status
)) {
453 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
454 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
455 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
462 // Initialize the child private structure
464 FbGopPrivate
->Signature
= FB_VIDEO_DEV_SIGNATURE
;
467 // Fill in Graphics Output specific mode structures
469 FbGopPrivate
->ModeData
= NULL
;
471 FbGopPrivate
->VbeFrameBuffer
= NULL
;
473 FbGopPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
474 FbGopPrivate
->EdidDiscovered
.Edid
= NULL
;
475 FbGopPrivate
->EdidActive
.SizeOfEdid
= 0;
476 FbGopPrivate
->EdidActive
.Edid
= NULL
;
479 // Fill in the Graphics Output Protocol
481 FbGopPrivate
->GraphicsOutput
.QueryMode
= FbGopGraphicsOutputQueryMode
;
482 FbGopPrivate
->GraphicsOutput
.SetMode
= FbGopGraphicsOutputSetMode
;
486 // Allocate buffer for Graphics Output Protocol mode information
488 FbGopPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
489 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
491 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
) {
492 Status
= EFI_OUT_OF_RESOURCES
;
496 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
497 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
499 if (NULL
== FbGopPrivate
->GraphicsOutput
.Mode
->Info
) {
500 Status
= EFI_OUT_OF_RESOURCES
;
505 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
507 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
508 if (RemainingDevicePath
== NULL
) {
509 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
510 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
511 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
512 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
513 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
515 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (
517 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
520 FbGopPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
524 // Creat child handle and device path protocol firstly
526 FbGopPrivate
->Handle
= NULL
;
527 Status
= gBS
->InstallMultipleProtocolInterfaces (
528 &FbGopPrivate
->Handle
,
529 &gEfiDevicePathProtocolGuid
,
530 FbGopPrivate
->GopDevicePath
,
533 if (EFI_ERROR (Status
)) {
539 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
541 FbGopPrivate
->PciIo
= ParentPciIo
;
544 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
546 Status
= FbGopCheckForVbe (FbGopPrivate
);
547 DEBUG ((EFI_D_INFO
, "FbGopCheckForVbe - %r\n", Status
));
549 if (EFI_ERROR (Status
)) {
550 Status
= EFI_UNSUPPORTED
;
555 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
557 Status
= gBS
->InstallMultipleProtocolInterfaces (
558 &FbGopPrivate
->Handle
,
559 &gEfiGraphicsOutputProtocolGuid
,
560 &FbGopPrivate
->GraphicsOutput
,
561 &gEfiEdidDiscoveredProtocolGuid
,
562 &FbGopPrivate
->EdidDiscovered
,
563 &gEfiEdidActiveProtocolGuid
,
564 &FbGopPrivate
->EdidActive
,
568 if (!EFI_ERROR (Status
)) {
570 // Open the Parent Handle for the child
572 Status
= gBS
->OpenProtocol (
574 &gEfiPciIoProtocolGuid
,
575 (VOID
**) &FbGopPrivate
->PciIo
,
576 This
->DriverBindingHandle
,
577 FbGopPrivate
->Handle
,
578 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
580 if (EFI_ERROR (Status
)) {
586 if (EFI_ERROR (Status
)) {
588 // Free private data structure
590 FbGopDeviceReleaseResource (FbGopPrivate
);
598 Deregister an video child handle and free resources.
600 @param This Protocol instance pointer.
601 @param Controller Video controller handle
602 @param Handle Video child handle
608 FbGopChildHandleUninstall (
609 EFI_DRIVER_BINDING_PROTOCOL
*This
,
610 EFI_HANDLE Controller
,
615 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
616 FB_VIDEO_DEV
*FbGopPrivate
;
617 EFI_PCI_IO_PROTOCOL
*PciIo
;
620 GraphicsOutput
= NULL
;
622 Status
= EFI_UNSUPPORTED
;
624 Status
= gBS
->OpenProtocol (
626 &gEfiGraphicsOutputProtocolGuid
,
627 (VOID
**) &GraphicsOutput
,
628 This
->DriverBindingHandle
,
630 EFI_OPEN_PROTOCOL_GET_PROTOCOL
632 if (!EFI_ERROR (Status
)) {
633 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
636 if (FbGopPrivate
== NULL
) {
637 return EFI_UNSUPPORTED
;
641 // Close PCI I/O protocol that opened by child handle
643 Status
= gBS
->CloseProtocol (
645 &gEfiPciIoProtocolGuid
,
646 This
->DriverBindingHandle
,
651 // Uninstall protocols on child handle
653 Status
= gBS
->UninstallMultipleProtocolInterfaces (
654 FbGopPrivate
->Handle
,
655 &gEfiDevicePathProtocolGuid
,
656 FbGopPrivate
->GopDevicePath
,
657 &gEfiGraphicsOutputProtocolGuid
,
658 &FbGopPrivate
->GraphicsOutput
,
662 if (EFI_ERROR (Status
)) {
665 &gEfiPciIoProtocolGuid
,
667 This
->DriverBindingHandle
,
669 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
675 // Release all allocated resources
677 FbGopDeviceReleaseResource (FbGopPrivate
);
684 Release resource for bios video instance.
686 @param FbGopPrivate Video child device private data structure
690 FbGopDeviceReleaseResource (
691 FB_VIDEO_DEV
*FbGopPrivate
694 if (FbGopPrivate
== NULL
) {
699 // Release all the resources occupied by the FB_VIDEO_DEV
703 // Free VBE Frame Buffer
705 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
706 FreePool (FbGopPrivate
->VbeFrameBuffer
);
712 if (FbGopPrivate
->ModeData
!= NULL
) {
713 FreePool (FbGopPrivate
->ModeData
);
717 // Free graphics output protocol occupied resource
719 if (FbGopPrivate
->GraphicsOutput
.Mode
!= NULL
) {
720 if (FbGopPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
721 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
->Info
);
722 FbGopPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
724 FreePool (FbGopPrivate
->GraphicsOutput
.Mode
);
725 FbGopPrivate
->GraphicsOutput
.Mode
= NULL
;
728 if (FbGopPrivate
->GopDevicePath
!= NULL
) {
729 FreePool (FbGopPrivate
->GopDevicePath
);
732 FreePool (FbGopPrivate
);
740 Check if all video child handles have been uninstalled.
742 @param Controller Video controller handle
744 @return TRUE Child handles exist.
745 @return FALSE All video child handles have been uninstalled.
750 IN EFI_HANDLE Controller
754 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
760 gBS
->OpenProtocolInformation (
762 &gEfiPciIoProtocolGuid
,
766 for (Index
= 0; Index
< EntryCount
; Index
++) {
767 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
776 Check for VBE device.
778 @param FbGopPrivate Pointer to FB_VIDEO_DEV structure
780 @retval EFI_SUCCESS VBE device found
785 IN OUT FB_VIDEO_DEV
*FbGopPrivate
789 FB_VIDEO_MODE_DATA
*ModeBuffer
;
790 FB_VIDEO_MODE_DATA
*CurrentModeData
;
793 UINTN BytesPerScanLine
;
794 UINT32 HorizontalResolution
;
795 UINT32 VerticalResolution
;
796 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
797 EFI_HOB_GUID_TYPE
*GuidHob
;
798 FRAME_BUFFER_INFO
*pFbInfo
;
800 Status
= EFI_SUCCESS
;
802 // Find the frame buffer information guid hob
804 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
805 ASSERT (GuidHob
!= NULL
);
806 pFbInfo
= (FRAME_BUFFER_INFO
*)GET_GUID_HOB_DATA (GuidHob
);
809 // Add mode to the list of available modes
811 VbeFrameBuffer
= NULL
;
815 BitsPerPixel
= pFbInfo
->BitsPerPixel
;
816 HorizontalResolution
= pFbInfo
->HorizontalResolution
;
817 VerticalResolution
= pFbInfo
->VerticalResolution
;
818 BytesPerScanLine
= pFbInfo
->BytesPerScanLine
;
820 ModeBuffer
= (FB_VIDEO_MODE_DATA
*) AllocatePool (
821 ModeNumber
* sizeof (FB_VIDEO_MODE_DATA
)
823 if (NULL
== ModeBuffer
) {
824 Status
= EFI_OUT_OF_RESOURCES
;
829 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
830 BytesPerScanLine
* VerticalResolution
832 if (NULL
== VbeFrameBuffer
) {
833 Status
= EFI_OUT_OF_RESOURCES
;
837 if (FbGopPrivate
->ModeData
!= NULL
) {
838 FreePool (FbGopPrivate
->ModeData
);
841 if (FbGopPrivate
->VbeFrameBuffer
!= NULL
) {
842 FreePool (FbGopPrivate
->VbeFrameBuffer
);
845 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
846 CurrentModeData
->BytesPerScanLine
= (UINT16
)BytesPerScanLine
;
848 CurrentModeData
->Red
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Red
);
849 CurrentModeData
->Blue
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Blue
);
850 CurrentModeData
->Green
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Green
);
851 CurrentModeData
->Reserved
= *(FB_VIDEO_COLOR_PLACEMENT
*)&(pFbInfo
->Reserved
);
853 CurrentModeData
->BitsPerPixel
= (UINT32
)BitsPerPixel
;
854 CurrentModeData
->HorizontalResolution
= HorizontalResolution
;
855 CurrentModeData
->VerticalResolution
= VerticalResolution
;
856 CurrentModeData
->FrameBufferSize
= CurrentModeData
->BytesPerScanLine
* CurrentModeData
->VerticalResolution
;
857 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
) pFbInfo
->LinearFrameBuffer
;
858 CurrentModeData
->VbeModeNumber
= 0;
859 CurrentModeData
->ColorDepth
= 32;
860 CurrentModeData
->RefreshRate
= 60;
862 CurrentModeData
->PixelFormat
= PixelBitMask
;
863 if ((CurrentModeData
->BitsPerPixel
== 32) &&
864 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
865 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
866 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
867 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
868 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
872 CopyMem (&(CurrentModeData
->PixelBitMask
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
874 FbGopPrivate
->ModeData
= ModeBuffer
;
875 FbGopPrivate
->VbeFrameBuffer
= VbeFrameBuffer
;
878 // Assign Gop's Blt function
880 FbGopPrivate
->GraphicsOutput
.Blt
= FbGopGraphicsOutputVbeBlt
;
882 FbGopPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
883 FbGopPrivate
->GraphicsOutput
.Mode
->Mode
= 0;
884 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->Version
= 0;
885 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->HorizontalResolution
= HorizontalResolution
;
886 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->VerticalResolution
= VerticalResolution
;
887 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelFormat
= CurrentModeData
->PixelFormat
;
888 CopyMem (&(FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelInformation
), &mPixelBitMask
, sizeof (EFI_PIXEL_BITMASK
));
889 FbGopPrivate
->GraphicsOutput
.Mode
->Info
->PixelsPerScanLine
= (UINT32
)(BytesPerScanLine
* 8 / BitsPerPixel
);
890 FbGopPrivate
->GraphicsOutput
.Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
891 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) CurrentModeData
->LinearFrameBuffer
;
892 FbGopPrivate
->GraphicsOutput
.Mode
->FrameBufferSize
= CurrentModeData
->FrameBufferSize
;
895 // Find the best mode to initialize
900 // If there was an error, then free the mode structure
902 if (EFI_ERROR (Status
)) {
904 if (VbeFrameBuffer
!= NULL
) {
905 FreePool (VbeFrameBuffer
);
908 if (ModeBuffer
!= NULL
) {
909 FreePool (ModeBuffer
);
918 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
922 Graphics Output protocol interface to get video mode.
924 @param This Protocol instance pointer.
925 @param ModeNumber The mode number to return information on.
926 @param SizeOfInfo A pointer to the size, in bytes, of the Info
928 @param Info Caller allocated buffer that returns information
931 @retval EFI_SUCCESS Mode information returned.
932 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
934 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
935 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
940 FbGopGraphicsOutputQueryMode (
941 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
942 IN UINT32 ModeNumber
,
943 OUT UINTN
*SizeOfInfo
,
944 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
947 FB_VIDEO_DEV
*FbGopPrivate
;
948 FB_VIDEO_MODE_DATA
*ModeData
;
950 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
952 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
953 return EFI_INVALID_PARAMETER
;
956 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
957 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
960 return EFI_OUT_OF_RESOURCES
;
963 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
965 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
966 (*Info
)->Version
= 0;
967 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
968 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
969 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
970 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
972 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
978 Graphics Output protocol interface to set video mode.
980 @param This Protocol instance pointer.
981 @param ModeNumber The mode number to be set.
983 @retval EFI_SUCCESS Graphics mode was changed.
984 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
986 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
991 FbGopGraphicsOutputSetMode (
992 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
996 FB_VIDEO_DEV
*FbGopPrivate
;
997 FB_VIDEO_MODE_DATA
*ModeData
;
998 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1001 return EFI_INVALID_PARAMETER
;
1004 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1006 ModeData
= &FbGopPrivate
->ModeData
[ModeNumber
];
1008 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1009 return EFI_UNSUPPORTED
;
1012 if (ModeNumber
== This
->Mode
->Mode
) {
1014 // Clear screen to black
1016 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1017 FbGopGraphicsOutputVbeBlt (
1025 ModeData
->HorizontalResolution
,
1026 ModeData
->VerticalResolution
,
1031 return EFI_UNSUPPORTED
;
1037 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1039 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
1040 @param VbeBuffer The data to transfer to screen
1041 @param MemAddress Physical frame buffer base address
1042 @param DestinationX The X coordinate of the destination for BltOperation
1043 @param DestinationY The Y coordinate of the destination for BltOperation
1044 @param TotalBytes The total bytes of copy
1045 @param VbePixelWidth Bytes per pixel
1046 @param BytesPerScanLine Bytes per scan line
1051 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1052 IN UINT8
*VbeBuffer
,
1053 IN VOID
*MemAddress
,
1054 IN UINTN DestinationX
,
1055 IN UINTN DestinationY
,
1056 IN UINTN TotalBytes
,
1057 IN UINT32 VbePixelWidth
,
1058 IN UINTN BytesPerScanLine
1061 UINTN FrameBufferAddr
;
1063 UINTN RemainingBytes
;
1064 UINTN UnalignedBytes
;
1067 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1070 // If TotalBytes is less than 4 bytes, only start byte copy.
1072 if (TotalBytes
< 4) {
1073 Status
= PciIo
->Mem
.Write (
1076 EFI_PCI_IO_PASS_THROUGH_BAR
,
1077 (UINT64
) FrameBufferAddr
,
1081 ASSERT_EFI_ERROR (Status
);
1086 // If VbeBuffer is not 4-byte aligned, start byte copy.
1088 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1090 if (UnalignedBytes
!= 0) {
1091 Status
= PciIo
->Mem
.Write (
1094 EFI_PCI_IO_PASS_THROUGH_BAR
,
1095 (UINT64
) FrameBufferAddr
,
1099 ASSERT_EFI_ERROR (Status
);
1100 FrameBufferAddr
+= UnalignedBytes
;
1101 VbeBuffer
+= UnalignedBytes
;
1105 // Calculate 4-byte block count and remaining bytes.
1107 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1108 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1111 // Copy 4-byte block and remaining bytes to physical frame buffer.
1113 if (CopyBlockNum
!= 0) {
1114 Status
= PciIo
->Mem
.Write (
1116 EfiPciIoWidthUint32
,
1117 EFI_PCI_IO_PASS_THROUGH_BAR
,
1118 (UINT64
) FrameBufferAddr
,
1122 ASSERT_EFI_ERROR (Status
);
1125 if (RemainingBytes
!= 0) {
1126 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1127 VbeBuffer
+= (CopyBlockNum
<< 2);
1128 Status
= PciIo
->Mem
.Write (
1131 EFI_PCI_IO_PASS_THROUGH_BAR
,
1132 (UINT64
) FrameBufferAddr
,
1136 ASSERT_EFI_ERROR (Status
);
1141 Worker function to block transfer for VBE device.
1143 @param FbGopPrivate Instance of FB_VIDEO_DEV
1144 @param BltBuffer The data to transfer to screen
1145 @param BltOperation The operation to perform
1146 @param SourceX The X coordinate of the source for BltOperation
1147 @param SourceY The Y coordinate of the source for BltOperation
1148 @param DestinationX The X coordinate of the destination for
1150 @param DestinationY The Y coordinate of the destination for
1152 @param Width The width of a rectangle in the blt rectangle in
1154 @param Height The height of a rectangle in the blt rectangle in
1156 @param Delta Not used for EfiBltVideoFill and
1157 EfiBltVideoToVideo operation. If a Delta of 0 is
1158 used, the entire BltBuffer will be operated on. If
1159 a subrectangle of the BltBuffer is used, then
1160 Delta represents the number of bytes in a row of
1162 @param Mode Mode data.
1164 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1165 @retval EFI_SUCCESS Blt operation success
1170 IN FB_VIDEO_DEV
*FbGopPrivate
,
1171 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1172 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1175 IN UINTN DestinationX
,
1176 IN UINTN DestinationY
,
1180 IN FB_VIDEO_MODE_DATA
*Mode
1183 EFI_PCI_IO_PROTOCOL
*PciIo
;
1184 EFI_TPL OriginalTPL
;
1188 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1190 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1191 UINTN BytesPerScanLine
;
1196 UINT32 VbePixelWidth
;
1200 PciIo
= FbGopPrivate
->PciIo
;
1202 VbeFrameBuffer
= FbGopPrivate
->VbeFrameBuffer
;
1203 MemAddress
= Mode
->LinearFrameBuffer
;
1204 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1205 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1206 BltUint8
= (UINT8
*) BltBuffer
;
1207 TotalBytes
= Width
* VbePixelWidth
;
1209 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1210 return EFI_INVALID_PARAMETER
;
1213 if (Width
== 0 || Height
== 0) {
1214 return EFI_INVALID_PARAMETER
;
1217 // We need to fill the Virtual Screen buffer with the blt data.
1218 // The virtual screen is upside down, as the first row is the bottom row of
1221 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1223 // Video to BltBuffer: Source is Video, destination is BltBuffer
1225 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1226 return EFI_INVALID_PARAMETER
;
1229 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1230 return EFI_INVALID_PARAMETER
;
1234 // BltBuffer to Video: Source is BltBuffer, destination is Video
1236 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1237 return EFI_INVALID_PARAMETER
;
1240 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1241 return EFI_INVALID_PARAMETER
;
1245 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1246 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1247 // the number of bytes in each row can be computed.
1250 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1253 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1254 // We would not want a timer based event (Cursor, ...) to come in while we are
1255 // doing this operation.
1257 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1259 switch (BltOperation
) {
1260 case EfiBltVideoToBltBuffer
:
1261 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1262 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1264 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1266 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1267 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1268 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
1269 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1270 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1271 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1274 VbeBuffer
+= VbePixelWidth
;
1280 case EfiBltVideoToVideo
:
1281 for (Index
= 0; Index
< Height
; Index
++) {
1282 if (DestinationY
<= SourceY
) {
1283 SrcY
= SourceY
+ Index
;
1284 DstY
= DestinationY
+ Index
;
1286 SrcY
= SourceY
+ Height
- Index
- 1;
1287 DstY
= DestinationY
+ Height
- Index
- 1;
1290 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
1291 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
1300 // Update physical frame buffer.
1315 case EfiBltVideoFill
:
1316 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1317 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
1319 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1321 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1323 (Blt
->Green
& Mode
->Green
.Mask
) <<
1324 Mode
->Green
.Position
1326 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1328 for (Index
= 0; Index
< Width
; Index
++) {
1334 VbeBuffer
+= VbePixelWidth
;
1337 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1338 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
1340 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
1346 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
1348 // Update physical frame buffer.
1363 case EfiBltBufferToVideo
:
1364 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
1365 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1366 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1367 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1369 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
1371 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1372 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
1373 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1380 VbeBuffer
+= VbePixelWidth
;
1383 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1386 // Update physical frame buffer.
1404 gBS
->RestoreTPL (OriginalTPL
);
1410 Graphics Output protocol instance to block transfer for VBE device.
1412 @param This Pointer to Graphics Output protocol instance
1413 @param BltBuffer The data to transfer to screen
1414 @param BltOperation The operation to perform
1415 @param SourceX The X coordinate of the source for BltOperation
1416 @param SourceY The Y coordinate of the source for BltOperation
1417 @param DestinationX The X coordinate of the destination for
1419 @param DestinationY The Y coordinate of the destination for
1421 @param Width The width of a rectangle in the blt rectangle in
1423 @param Height The height of a rectangle in the blt rectangle in
1425 @param Delta Not used for EfiBltVideoFill and
1426 EfiBltVideoToVideo operation. If a Delta of 0 is
1427 used, the entire BltBuffer will be operated on. If
1428 a subrectangle of the BltBuffer is used, then
1429 Delta represents the number of bytes in a row of
1432 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
1433 @retval EFI_SUCCESS Blt operation success
1438 FbGopGraphicsOutputVbeBlt (
1439 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1440 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1441 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1444 IN UINTN DestinationX
,
1445 IN UINTN DestinationY
,
1451 FB_VIDEO_DEV
*FbGopPrivate
;
1452 FB_VIDEO_MODE_DATA
*Mode
;
1455 return EFI_INVALID_PARAMETER
;
1458 FbGopPrivate
= FB_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1459 Mode
= &FbGopPrivate
->ModeData
[This
->Mode
->Mode
];
1461 return FbGopVbeBltWorker (
1478 The user Entry Point for module UefiFbGop. The user code starts with this function.
1480 @param[in] ImageHandle The firmware allocated handle for the EFI image.
1481 @param[in] SystemTable A pointer to the EFI System Table.
1483 @retval EFI_SUCCESS The entry point is executed successfully.
1484 @retval other Some error occurs when executing this entry point.
1490 IN EFI_HANDLE ImageHandle
,
1491 IN EFI_SYSTEM_TABLE
*SystemTable
1495 EFI_HOB_GUID_TYPE
*GuidHob
;
1498 // Find the frame buffer information guid hob
1500 GuidHob
= GetFirstGuidHob (&gUefiFrameBufferInfoGuid
);
1501 if (GuidHob
!= NULL
) {
1503 // Install driver model protocol(s).
1505 Status
= EfiLibInstallDriverBindingComponentName2 (
1508 &gFbGopDriverBinding
,
1510 &gFbGopComponentName
,
1511 &gFbGopComponentName2
1513 ASSERT_EFI_ERROR (Status
);
1515 DEBUG ((EFI_D_ERROR
, "No FrameBuffer information from coreboot. NO GOP driver !!!\n"));
1516 Status
= EFI_ABORTED
;