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.
17 #include "BiosVideo.h"
20 // EFI Driver Binding Protocol Instance
22 EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding
= {
23 BiosVideoDriverBindingSupported
,
24 BiosVideoDriverBindingStart
,
25 BiosVideoDriverBindingStop
,
32 // Global lookup tables for VGA graphics modes
34 UINT8 mVgaLeftMaskTable
[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
36 UINT8 mVgaRightMaskTable
[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
38 UINT8 mVgaBitMaskTable
[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
41 // Save controller attributes during first start
43 UINT64 mOriginalPciAttributes
;
44 BOOLEAN mPciAttributesSaved
= FALSE
;
46 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor
[] = {
47 { 0x00, 0x00, 0x00, 0x00 },
48 { 0x98, 0x00, 0x00, 0x00 },
49 { 0x00, 0x98, 0x00, 0x00 },
50 { 0x98, 0x98, 0x00, 0x00 },
51 { 0x00, 0x00, 0x98, 0x00 },
52 { 0x98, 0x00, 0x98, 0x00 },
53 { 0x00, 0x98, 0x98, 0x00 },
54 { 0x98, 0x98, 0x98, 0x00 },
55 { 0x10, 0x10, 0x10, 0x00 },
56 { 0xff, 0x10, 0x10, 0x00 },
57 { 0x10, 0xff, 0x10, 0x00 },
58 { 0xff, 0xff, 0x10, 0x00 },
59 { 0x10, 0x10, 0xff, 0x00 },
60 { 0xf0, 0x10, 0xff, 0x00 },
61 { 0x10, 0xff, 0xff, 0x00 },
62 { 0xff, 0xff, 0xff, 0x00 }
66 // Standard timing defined by VESA EDID
68 VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming
[] = {
70 // Established Timing I
81 // Established Timing II
92 // Established Timing III
100 @param This Pointer to driver binding protocol
101 @param Controller Controller handle to connect
102 @param RemainingDevicePath A pointer to the remaining portion of a device
105 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
106 driver, Otherwise, this controller cannot be
107 managed by this driver
112 BiosVideoDriverBindingSupported (
113 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
114 IN EFI_HANDLE Controller
,
115 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
119 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
120 EFI_PCI_IO_PROTOCOL
*PciIo
;
125 // See if the Legacy BIOS Protocol is available
127 Status
= gBS
->LocateProtocol (&gEfiLegacyBiosProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
128 if (EFI_ERROR (Status
)) {
133 // Open the IO Abstraction(s) needed to perform the supported test
135 Status
= gBS
->OpenProtocol (
137 &gEfiPciIoProtocolGuid
,
139 This
->DriverBindingHandle
,
141 EFI_OPEN_PROTOCOL_BY_DRIVER
143 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
147 if (Status
== EFI_ALREADY_STARTED
) {
149 // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,
150 // because VgaMiniPort protocol is installed on controller handle directly.
152 Status
= gBS
->OpenProtocol (
154 &gEfiVgaMiniPortProtocolGuid
,
158 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
160 if (!EFI_ERROR (Status
)) {
161 return EFI_ALREADY_STARTED
;
165 // See if this is a PCI Graphics Controller by looking at the Command register and
166 // Class Code Register
168 Status
= PciIo
->Pci
.Read (
172 sizeof (Pci
) / sizeof (UINT32
),
175 if (EFI_ERROR (Status
)) {
176 Status
= EFI_UNSUPPORTED
;
180 Status
= EFI_UNSUPPORTED
;
181 if (Pci
.Hdr
.ClassCode
[2] == 0x03 || (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01)) {
183 Status
= EFI_SUCCESS
;
185 // If this is a graphics controller,
186 // go further check RemainingDevicePath validation
188 if (RemainingDevicePath
!= NULL
) {
189 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
191 // Check if RemainingDevicePath is the End of Device Path Node,
192 // if yes, return EFI_SUCCESS
194 if (!IsDevicePathEnd (Node
)) {
196 // If RemainingDevicePath isn't the End of Device Path Node,
197 // check its validation
199 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
200 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
201 DevicePathNodeLength(&Node
->DevPath
) < sizeof(ACPI_ADR_DEVICE_PATH
)) {
202 Status
= EFI_UNSUPPORTED
;
211 &gEfiPciIoProtocolGuid
,
212 This
->DriverBindingHandle
,
221 Install Graphics Output Protocol onto VGA device handles.
223 @param This Pointer to driver binding protocol
224 @param Controller Controller handle to connect
225 @param RemainingDevicePath A pointer to the remaining portion of a device
233 BiosVideoDriverBindingStart (
234 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
235 IN EFI_HANDLE Controller
,
236 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
240 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
241 EFI_PCI_IO_PROTOCOL
*PciIo
;
242 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
247 // Initialize local variables
250 ParentDevicePath
= NULL
;
254 // See if the Legacy BIOS Protocol is available
256 Status
= gBS
->LocateProtocol (&gEfiLegacyBiosProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
257 if (EFI_ERROR (Status
)) {
262 // Prepare for status code
264 Status
= gBS
->HandleProtocol (
266 &gEfiDevicePathProtocolGuid
,
267 (VOID
**) &ParentDevicePath
269 if (EFI_ERROR (Status
)) {
274 // Open the IO Abstraction(s) needed
276 Status
= gBS
->OpenProtocol (
278 &gEfiPciIoProtocolGuid
,
280 This
->DriverBindingHandle
,
282 EFI_OPEN_PROTOCOL_BY_DRIVER
284 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
289 // Save original PCI attributes
291 if (!mPciAttributesSaved
) {
292 Status
= PciIo
->Attributes (
294 EfiPciIoAttributeOperationGet
,
296 &mOriginalPciAttributes
299 if (EFI_ERROR (Status
)) {
302 mPciAttributesSaved
= TRUE
;
306 // Get supported PCI attributes
308 Status
= PciIo
->Attributes (
310 EfiPciIoAttributeOperationSupported
,
314 if (EFI_ERROR (Status
)) {
318 Supports
&= (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
319 if (Supports
== 0 || Supports
== (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
320 Status
= EFI_UNSUPPORTED
;
324 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
326 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_ENABLE
,
330 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
332 Status
= PciIo
->Attributes (
334 EfiPciIoAttributeOperationEnable
,
335 EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
| Supports
,
338 if (EFI_ERROR (Status
)) {
339 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
340 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
341 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_RESOURCE_CONFLICT
,
347 // Check to see if there is a legacy option ROM image associated with this PCI device
349 Status
= LegacyBios
->CheckPciRom (
356 if (EFI_ERROR (Status
)) {
360 // Post the legacy option ROM if it is available.
362 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
367 Status
= LegacyBios
->InstallPciRom (
377 if (EFI_ERROR (Status
)) {
378 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
379 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
380 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
386 if (RemainingDevicePath
!= NULL
) {
387 if (IsDevicePathEnd (RemainingDevicePath
) &&
388 (FeaturePcdGet (PcdBiosVideoCheckVbeEnable
) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable
))) {
390 // If RemainingDevicePath is the End of Device Path Node,
391 // don't create any child device and return EFI_SUCESS
392 Status
= EFI_SUCCESS
;
398 // Create child handle and install GraphicsOutputProtocol on it
400 Status
= BiosVideoChildHandleInstall (
410 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
411 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
413 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_DISABLE
,
417 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
419 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_NOT_DETECTED
,
422 if (!HasChildHandle (Controller
)) {
423 if (mPciAttributesSaved
) {
425 // Restore original PCI attributes
429 EfiPciIoAttributeOperationSet
,
430 mOriginalPciAttributes
,
436 // Release PCI I/O Protocols on the controller handle.
440 &gEfiPciIoProtocolGuid
,
441 This
->DriverBindingHandle
,
453 @param This Pointer to driver binding protocol
454 @param Controller Controller handle to connect
455 @param NumberOfChildren Number of children handle created by this driver
456 @param ChildHandleBuffer Buffer containing child handle created
458 @retval EFI_SUCCESS Driver disconnected successfully from controller
459 @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure
464 BiosVideoDriverBindingStop (
465 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
466 IN EFI_HANDLE Controller
,
467 IN UINTN NumberOfChildren
,
468 IN EFI_HANDLE
*ChildHandleBuffer
472 BOOLEAN AllChildrenStopped
;
474 EFI_PCI_IO_PROTOCOL
*PciIo
;
476 AllChildrenStopped
= TRUE
;
478 if (NumberOfChildren
== 0) {
480 // Close PCI I/O protocol on the controller handle
484 &gEfiPciIoProtocolGuid
,
485 This
->DriverBindingHandle
,
492 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
493 Status
= BiosVideoChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
495 if (EFI_ERROR (Status
)) {
496 AllChildrenStopped
= FALSE
;
500 if (!AllChildrenStopped
) {
501 return EFI_DEVICE_ERROR
;
504 if (!HasChildHandle (Controller
)) {
505 if (mPciAttributesSaved
) {
506 Status
= gBS
->HandleProtocol (
508 &gEfiPciIoProtocolGuid
,
511 ASSERT_EFI_ERROR (Status
);
514 // Restore original PCI attributes
516 Status
= PciIo
->Attributes (
518 EfiPciIoAttributeOperationSet
,
519 mOriginalPciAttributes
,
522 ASSERT_EFI_ERROR (Status
);
532 Install child handles if the Handle supports MBR format.
534 @param This Calling context.
535 @param ParentHandle Parent Handle
536 @param ParentPciIo Parent PciIo interface
537 @param ParentLegacyBios Parent LegacyBios interface
538 @param ParentDevicePath Parent Device Path
539 @param RemainingDevicePath Remaining Device Path
541 @retval EFI_SUCCESS If a child handle was added
542 @retval other A child handle was not added
546 BiosVideoChildHandleInstall (
547 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
548 IN EFI_HANDLE ParentHandle
,
549 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
550 IN EFI_LEGACY_BIOS_PROTOCOL
*ParentLegacyBios
,
551 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
552 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
556 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
558 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
559 BOOLEAN ProtocolInstalled
;
562 // Allocate the private device structure for video device
564 BiosVideoPrivate
= (BIOS_VIDEO_DEV
*) AllocateZeroPool (
565 sizeof (BIOS_VIDEO_DEV
)
567 if (NULL
== BiosVideoPrivate
) {
568 Status
= EFI_OUT_OF_RESOURCES
;
573 // See if this is a VGA compatible controller or not
575 Status
= ParentPciIo
->Pci
.Read (
579 sizeof (Pci
) / sizeof (UINT32
),
582 if (EFI_ERROR (Status
)) {
583 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
584 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
585 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
590 BiosVideoPrivate
->VgaCompatible
= FALSE
;
591 if (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01) {
592 BiosVideoPrivate
->VgaCompatible
= TRUE
;
595 if (Pci
.Hdr
.ClassCode
[2] == 0x03 && Pci
.Hdr
.ClassCode
[1] == 0x00 && Pci
.Hdr
.ClassCode
[0] == 0x00) {
596 BiosVideoPrivate
->VgaCompatible
= TRUE
;
599 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable
)) {
601 // Create EXIT_BOOT_SERIVES Event
603 Status
= gBS
->CreateEventEx (
606 BiosVideoNotifyExitBootServices
,
608 &gEfiEventExitBootServicesGuid
,
609 &BiosVideoPrivate
->ExitBootServicesEvent
611 if (EFI_ERROR (Status
)) {
617 // Initialize the child private structure
619 BiosVideoPrivate
->Signature
= BIOS_VIDEO_DEV_SIGNATURE
;
622 // Fill in Graphics Output specific mode structures
624 BiosVideoPrivate
->HardwareNeedsStarting
= TRUE
;
625 BiosVideoPrivate
->ModeData
= NULL
;
626 BiosVideoPrivate
->LineBuffer
= NULL
;
627 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
628 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
631 // Fill in the Graphics Output Protocol
633 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
634 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
638 // Allocate buffer for Graphics Output Protocol mode information
640 BiosVideoPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
641 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
643 if (NULL
== BiosVideoPrivate
->GraphicsOutput
.Mode
) {
644 Status
= EFI_OUT_OF_RESOURCES
;
648 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
649 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
651 if (NULL
== BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
) {
652 Status
= EFI_OUT_OF_RESOURCES
;
657 // Assume that Graphics Output Protocol will be produced until proven otherwise
659 BiosVideoPrivate
->ProduceGraphicsOutput
= TRUE
;
662 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
664 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
665 if (RemainingDevicePath
== NULL
) {
666 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
667 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
668 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
669 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
670 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
672 BiosVideoPrivate
->GopDevicePath
= AppendDevicePathNode (
674 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
677 BiosVideoPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
681 // Creat child handle and device path protocol firstly
683 BiosVideoPrivate
->Handle
= NULL
;
684 Status
= gBS
->InstallMultipleProtocolInterfaces (
685 &BiosVideoPrivate
->Handle
,
686 &gEfiDevicePathProtocolGuid
,
687 BiosVideoPrivate
->GopDevicePath
,
690 if (EFI_ERROR (Status
)) {
696 // Fill in the VGA Mini Port Protocol fields
698 BiosVideoPrivate
->VgaMiniPort
.SetMode
= BiosVideoVgaMiniPortSetMode
;
699 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryOffset
= 0xb8000;
700 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterOffset
= 0x3d4;
701 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterOffset
= 0x3d5;
702 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
703 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
704 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
707 // Child handle need to consume the Legacy Bios protocol
709 BiosVideoPrivate
->LegacyBios
= ParentLegacyBios
;
712 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
714 BiosVideoPrivate
->PciIo
= ParentPciIo
;
717 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
719 if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable
)) {
720 Status
= BiosVideoCheckForVbe (BiosVideoPrivate
);
721 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVbe - %r\n", Status
));
723 Status
= EFI_UNSUPPORTED
;
725 if (EFI_ERROR (Status
)) {
727 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
728 // for the standard 640x480 16 color VGA mode
730 DEBUG ((EFI_D_INFO
, "VgaCompatible - %x\n", BiosVideoPrivate
->VgaCompatible
));
731 if (BiosVideoPrivate
->VgaCompatible
) {
732 if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable
)) {
733 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
734 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVga - %r\n", Status
));
736 Status
= EFI_UNSUPPORTED
;
740 if (EFI_ERROR (Status
)) {
742 // Free GOP mode structure if it is not freed before
743 // VgaMiniPort does not need this structure any more
745 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
746 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
747 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
748 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
750 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
751 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
755 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
756 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
758 BiosVideoPrivate
->ProduceGraphicsOutput
= FALSE
;
761 // INT services are available, so on the 80x25 and 80x50 text mode are supported
763 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
767 ProtocolInstalled
= FALSE
;
769 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
771 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
773 Status
= gBS
->InstallMultipleProtocolInterfaces (
774 &BiosVideoPrivate
->Handle
,
775 &gEfiGraphicsOutputProtocolGuid
,
776 &BiosVideoPrivate
->GraphicsOutput
,
777 &gEfiEdidDiscoveredProtocolGuid
,
778 &BiosVideoPrivate
->EdidDiscovered
,
779 &gEfiEdidActiveProtocolGuid
,
780 &BiosVideoPrivate
->EdidActive
,
784 if (!EFI_ERROR (Status
)) {
786 // Open the Parent Handle for the child
788 Status
= gBS
->OpenProtocol (
790 &gEfiPciIoProtocolGuid
,
791 (VOID
**) &BiosVideoPrivate
->PciIo
,
792 This
->DriverBindingHandle
,
793 BiosVideoPrivate
->Handle
,
794 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
796 if (EFI_ERROR (Status
)) {
799 ProtocolInstalled
= TRUE
;
803 if (!ProtocolInstalled
) {
805 // Install VGA Mini Port Protocol
807 Status
= gBS
->InstallMultipleProtocolInterfaces (
809 &gEfiVgaMiniPortProtocolGuid
,
810 &BiosVideoPrivate
->VgaMiniPort
,
816 if (EFI_ERROR (Status
)) {
817 if ((BiosVideoPrivate
!= NULL
) && (BiosVideoPrivate
->ExitBootServicesEvent
!= NULL
)) {
818 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
821 // Free private data structure
823 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
831 Deregister an video child handle and free resources.
833 @param This Protocol instance pointer.
834 @param Controller Video controller handle
835 @param Handle Video child handle
841 BiosVideoChildHandleUninstall (
842 EFI_DRIVER_BINDING_PROTOCOL
*This
,
843 EFI_HANDLE Controller
,
848 EFI_IA32_REGISTER_SET Regs
;
849 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
850 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
851 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
852 EFI_PCI_IO_PROTOCOL
*PciIo
;
854 BiosVideoPrivate
= NULL
;
855 GraphicsOutput
= NULL
;
857 Status
= EFI_UNSUPPORTED
;
859 Status
= gBS
->OpenProtocol (
861 &gEfiGraphicsOutputProtocolGuid
,
862 (VOID
**) &GraphicsOutput
,
863 This
->DriverBindingHandle
,
865 EFI_OPEN_PROTOCOL_GET_PROTOCOL
867 if (!EFI_ERROR (Status
)) {
868 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
871 if (EFI_ERROR (Status
)) {
872 Status
= gBS
->OpenProtocol (
874 &gEfiVgaMiniPortProtocolGuid
,
875 (VOID
**) &VgaMiniPort
,
876 This
->DriverBindingHandle
,
878 EFI_OPEN_PROTOCOL_GET_PROTOCOL
880 if (!EFI_ERROR (Status
)) {
881 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
885 if (BiosVideoPrivate
== NULL
) {
886 return EFI_UNSUPPORTED
;
890 // Set the 80x25 Text VGA Mode
894 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
899 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
902 // Close PCI I/O protocol that opened by child handle
904 Status
= gBS
->CloseProtocol (
906 &gEfiPciIoProtocolGuid
,
907 This
->DriverBindingHandle
,
912 // Uninstall protocols on child handle
914 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
915 Status
= gBS
->UninstallMultipleProtocolInterfaces (
916 BiosVideoPrivate
->Handle
,
917 &gEfiDevicePathProtocolGuid
,
918 BiosVideoPrivate
->GopDevicePath
,
919 &gEfiGraphicsOutputProtocolGuid
,
920 &BiosVideoPrivate
->GraphicsOutput
,
921 &gEfiEdidDiscoveredProtocolGuid
,
922 &BiosVideoPrivate
->EdidDiscovered
,
923 &gEfiEdidActiveProtocolGuid
,
924 &BiosVideoPrivate
->EdidActive
,
928 if (!BiosVideoPrivate
->ProduceGraphicsOutput
) {
929 Status
= gBS
->UninstallMultipleProtocolInterfaces (
931 &gEfiVgaMiniPortProtocolGuid
,
932 &BiosVideoPrivate
->VgaMiniPort
,
937 if (EFI_ERROR (Status
)) {
940 &gEfiPciIoProtocolGuid
,
942 This
->DriverBindingHandle
,
944 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
949 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable
)) {
951 // Close EXIT_BOOT_SERIVES Event
953 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
957 // Release all allocated resources
959 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
966 Release resource for biso video instance.
968 @param BiosVideoPrivate Video child device private data structure
972 BiosVideoDeviceReleaseResource (
973 BIOS_VIDEO_DEV
*BiosVideoPrivate
976 if (BiosVideoPrivate
== NULL
) {
981 // Release all the resourses occupied by the BIOS_VIDEO_DEV
985 // Free VGA Frame Buffer
987 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
988 FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
991 // Free VBE Frame Buffer
993 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
994 FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
999 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
1000 FreePool (BiosVideoPrivate
->LineBuffer
);
1005 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1006 FreePool (BiosVideoPrivate
->ModeData
);
1009 // Free memory allocated below 1MB
1011 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
1012 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
1015 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
1016 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
1020 // Free graphics output protocol occupied resource
1022 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1023 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1024 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1025 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
1027 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1028 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1031 // Free EDID discovered protocol occupied resource
1033 if (BiosVideoPrivate
->EdidDiscovered
.Edid
!= NULL
) {
1034 FreePool (BiosVideoPrivate
->EdidDiscovered
.Edid
);
1037 // Free EDID active protocol occupied resource
1039 if (BiosVideoPrivate
->EdidActive
.Edid
!= NULL
) {
1040 FreePool (BiosVideoPrivate
->EdidActive
.Edid
);
1043 if (BiosVideoPrivate
->GopDevicePath
!= NULL
) {
1044 FreePool (BiosVideoPrivate
->GopDevicePath
);
1047 FreePool (BiosVideoPrivate
);
1054 Generate a search key for a specified timing data.
1056 @param EdidTiming Pointer to EDID timing
1058 @return The 32 bit unique key for search.
1063 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
1069 // Be sure no conflicts for all standard timing defined by VESA.
1071 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
1077 Parse the Established Timing and Standard Timing in EDID data block.
1079 @param EdidBuffer Pointer to EDID data block
1080 @param ValidEdidTiming Valid EDID timing information
1082 @retval TRUE The EDID data is valid.
1083 @retval FALSE The EDID data is invalid.
1089 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
1097 UINT16 HorizontalResolution
;
1098 UINT16 VerticalResolution
;
1101 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming
;
1102 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*EdidDataBlock
;
1104 EdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) EdidBuffer
;
1107 // Check the checksum of EDID data
1110 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
; Index
++) {
1111 CheckSum
= (UINT8
) (CheckSum
+ EdidBuffer
[Index
]);
1113 if (CheckSum
!= 0) {
1118 gBS
->SetMem (ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
), 0);
1120 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
1121 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
1122 (EdidDataBlock
->EstablishedTimings
[2] != 0)
1125 // Established timing data
1127 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
1128 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
1129 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
1130 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
1131 if ((TimingBits
& 0x1) != 0) {
1132 DEBUG ((EFI_D_INFO
, "Established Timing: %d x %d\n",
1133 mEstablishedEdidTiming
[Index
].HorizontalResolution
, mEstablishedEdidTiming
[Index
].VerticalResolution
));
1134 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mEstablishedEdidTiming
[Index
]);
1137 TimingBits
= TimingBits
>> 1;
1142 // Parse the standard timing data
1144 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
1145 for (Index
= 0; Index
< 8; Index
++) {
1147 // Check if this is a valid Standard Timing entry
1148 // VESA documents unused fields should be set to 01h
1150 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
1152 // A valid Standard Timing
1154 HorizontalResolution
= (UINT16
) (BufferIndex
[0] * 8 + 248);
1155 AspectRatio
= (UINT8
) (BufferIndex
[1] >> 6);
1156 switch (AspectRatio
) {
1158 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 10);
1161 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
1164 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 5 * 4);
1167 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 9);
1170 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
1173 RefreshRate
= (UINT8
) ((BufferIndex
[1] & 0x1f) + 60);
1174 DEBUG ((EFI_D_INFO
, "Standard Timing: %d x %d\n", HorizontalResolution
, VerticalResolution
));
1175 TempTiming
.HorizontalResolution
= HorizontalResolution
;
1176 TempTiming
.VerticalResolution
= VerticalResolution
;
1177 TempTiming
.RefreshRate
= RefreshRate
;
1178 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
1185 // Parse the Detailed Timing data
1187 BufferIndex
= &EdidDataBlock
->DetailedTimingDescriptions
[0];
1188 for (Index
= 0; Index
< 4; Index
++, BufferIndex
+= VESA_BIOS_EXTENSIONS_DETAILED_TIMING_EACH_DESCRIPTOR_SIZE
) {
1189 if ((BufferIndex
[0] == 0x0) && (BufferIndex
[1] == 0x0)) {
1191 // Check if this is a valid Detailed Timing Descriptor
1192 // If first 2 bytes are zero, it is monitor descriptor other than detailed timing descriptor
1197 // Calculate Horizontal and Vertical resolution
1199 TempTiming
.HorizontalResolution
= ((UINT16
)(BufferIndex
[4] & 0xF0) << 4) | (BufferIndex
[2]);
1200 TempTiming
.VerticalResolution
= ((UINT16
)(BufferIndex
[7] & 0xF0) << 4) | (BufferIndex
[5]);
1201 DEBUG ((EFI_D_INFO
, "Detailed Timing %d: %d x %d\n",
1202 Index
, TempTiming
.HorizontalResolution
, TempTiming
.VerticalResolution
));
1203 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
1207 ValidEdidTiming
->ValidNumber
= ValidNumber
;
1213 Search a specified Timing in all the valid EDID timings.
1215 @param ValidEdidTiming All valid EDID timing information.
1216 @param EdidTiming The Timing to search for.
1219 @retval FALSE Not found.
1224 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
,
1225 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
1231 Key
= CalculateEdidKey (EdidTiming
);
1233 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
1234 if (Key
== ValidEdidTiming
->Key
[Index
]) {
1243 Check if all video child handles have been uninstalled.
1245 @param Controller Video controller handle
1247 @return TRUE Child handles exist.
1248 @return FALSE All video child handles have been uninstalled.
1253 IN EFI_HANDLE Controller
1257 EFI_OPEN_PROTOCOL_INFORMATION_ENTRY
*OpenInfoBuffer
;
1264 Status
= gBS
->OpenProtocolInformation (
1266 &gEfiPciIoProtocolGuid
,
1270 for (Index
= 0; Index
< EntryCount
; Index
++) {
1271 if ((OpenInfoBuffer
[Index
].Attributes
& EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
) != 0) {
1280 Check for VBE device.
1282 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
1284 @retval EFI_SUCCESS VBE device found
1288 BiosVideoCheckForVbe (
1289 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1293 EFI_IA32_REGISTER_SET Regs
;
1294 UINT16
*ModeNumberPtr
;
1295 UINT16 VbeModeNumber
;
1298 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1299 BIOS_VIDEO_MODE_DATA
*CurrentModeData
;
1302 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing
;
1303 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming
;
1304 EFI_EDID_OVERRIDE_PROTOCOL
*EdidOverride
;
1305 UINT32 EdidAttributes
;
1306 BOOLEAN EdidOverrideFound
;
1307 UINTN EdidOverrideDataSize
;
1308 UINT8
*EdidOverrideDataBlock
;
1309 UINTN EdidActiveDataSize
;
1310 UINT8
*EdidActiveDataBlock
;
1311 UINT32 HighestHorizontalResolution
;
1312 UINT32 HighestVerticalResolution
;
1313 UINTN HighestResolutionMode
;
1316 EdidOverrideFound
= FALSE
;
1317 EdidOverrideDataBlock
= NULL
;
1318 EdidActiveDataSize
= 0;
1319 EdidActiveDataBlock
= NULL
;
1320 HighestHorizontalResolution
= 0;
1321 HighestVerticalResolution
= 0;
1322 HighestResolutionMode
= 0;
1325 // Allocate buffer under 1MB for VBE data structures
1327 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
1328 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) +
1329 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
1330 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
) +
1331 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
1334 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
1336 Status
= gBS
->AllocatePages (
1338 EfiBootServicesData
,
1339 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
1340 &BiosVideoPrivate
->PagesBelow1MB
1342 if (EFI_ERROR (Status
)) {
1346 ZeroMem (&ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
));
1349 // Fill in the VBE related data structures
1351 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
1352 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
1353 BiosVideoPrivate
->VbeEdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
1354 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeEdidDataBlock
+ 1);
1355 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
1356 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
1359 // Test to see if the Video Adapter is compliant with VBE 3.0
1361 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1362 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1363 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1364 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1365 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1366 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1368 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1370 Status
= EFI_DEVICE_ERROR
;
1373 // See if the VESA call succeeded
1375 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1379 // Check for 'VESA' signature
1381 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1385 // Check to see if this is VBE 2.0 or higher
1387 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1392 EdidAttributes
= 0xff;
1393 EdidOverrideDataSize
= 0;
1396 // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
1398 Status
= gBS
->LocateProtocol (
1399 &gEfiEdidOverrideProtocolGuid
,
1401 (VOID
**) &EdidOverride
1403 if (!EFI_ERROR (Status
)) {
1405 // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
1407 EdidOverrideDataBlock
= AllocatePool (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
* 2);
1408 if (NULL
== EdidOverrideDataBlock
) {
1409 Status
= EFI_OUT_OF_RESOURCES
;
1413 Status
= EdidOverride
->GetEdid (
1415 BiosVideoPrivate
->Handle
,
1417 &EdidOverrideDataSize
,
1418 (UINT8
**) &EdidOverrideDataBlock
1420 if (!EFI_ERROR (Status
) &&
1421 EdidAttributes
== 0 &&
1422 EdidOverrideDataSize
!= 0) {
1424 // Succeeded to get EDID Override Data
1426 EdidOverrideFound
= TRUE
;
1430 if (!EdidOverrideFound
|| EdidAttributes
== EFI_EDID_OVERRIDE_DONT_OVERRIDE
) {
1432 // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
1433 // read EDID information through INT10 call
1436 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1437 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1441 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1442 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1444 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1446 // See if the VESA call succeeded
1448 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1450 // Set EDID Discovered Data
1452 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1453 BiosVideoPrivate
->EdidDiscovered
.Edid
= (UINT8
*) AllocateCopyPool (
1454 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1455 BiosVideoPrivate
->VbeEdidDataBlock
1458 if (NULL
== BiosVideoPrivate
->EdidDiscovered
.Edid
) {
1459 Status
= EFI_OUT_OF_RESOURCES
;
1468 EdidActiveDataSize
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1469 EdidActiveDataBlock
= BiosVideoPrivate
->EdidDiscovered
.Edid
;
1470 } else if (EdidOverrideFound
) {
1471 EdidActiveDataSize
= EdidOverrideDataSize
;
1472 EdidActiveDataBlock
= EdidOverrideDataBlock
;
1478 // Parse EDID data structure to retrieve modes supported by monitor
1480 if (ParseEdidData ((UINT8
*) EdidActiveDataBlock
, &ValidEdidTiming
)) {
1482 // Copy EDID Override Data to EDID Active Data
1484 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= (UINT32
) EdidActiveDataSize
;
1485 BiosVideoPrivate
->EdidActive
.Edid
= (UINT8
*) AllocateCopyPool (
1489 if (NULL
== BiosVideoPrivate
->EdidActive
.Edid
) {
1490 Status
= EFI_OUT_OF_RESOURCES
;
1495 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1496 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1501 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1503 ModeNumberPtr
= (UINT16
*)
1505 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1506 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1513 // ModeNumberPtr may be not 16-byte aligned, so ReadUnaligned16 is used to access the buffer pointed by ModeNumberPtr.
1515 for (VbeModeNumber
= ReadUnaligned16 (ModeNumberPtr
);
1516 VbeModeNumber
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
;
1517 VbeModeNumber
= ReadUnaligned16 (++ModeNumberPtr
)) {
1519 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1521 if ((VbeModeNumber
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1525 // Get the information about the mode
1527 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1528 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1529 Regs
.X
.CX
= VbeModeNumber
;
1530 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1531 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1532 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1534 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1537 // See if the call succeeded. If it didn't, then try the next mode.
1539 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1543 // See if the mode supports color. If it doesn't then try the next mode.
1545 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1549 // See if the mode supports graphics. If it doesn't then try the next mode.
1551 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1555 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1557 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1561 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1562 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1563 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1565 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1569 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1573 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1577 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1579 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1583 DEBUG ((EFI_D_INFO
, "Video Controller Mode 0x%x: %d x %d\n",
1584 VbeModeNumber
, BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
, BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
));
1586 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1588 // EDID exist, check whether this mode match with any mode in EDID
1590 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1591 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1592 if (!SearchEdidTiming (&ValidEdidTiming
, &Timing
)) {
1594 // When EDID comes from INT10 call, EDID does not include 800x600, 640x480 and 1024x768,
1595 // but INT10 can support these modes, we add them into GOP mode.
1597 if ((BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
!= 0) &&
1598 !((Timing
.HorizontalResolution
) == 1024 && (Timing
.VerticalResolution
== 768)) &&
1599 !((Timing
.HorizontalResolution
) == 800 && (Timing
.VerticalResolution
== 600)) &&
1600 !((Timing
.HorizontalResolution
) == 640 && (Timing
.VerticalResolution
== 480))) {
1607 // Select a reasonable mode to be set for current display mode
1611 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1612 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1616 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1617 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1620 PreferMode
= ModeNumber
;
1622 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1623 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1628 if ((!EdidFound
) && (!ModeFound
)) {
1630 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1636 // Record the highest resolution mode to set later
1638 if ((BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
> HighestHorizontalResolution
) ||
1639 ((BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== HighestHorizontalResolution
) &&
1640 (BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
> HighestVerticalResolution
))) {
1641 HighestHorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1642 HighestVerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1643 HighestResolutionMode
= ModeNumber
;
1647 // Add mode to the list of available modes
1650 ModeBuffer
= (BIOS_VIDEO_MODE_DATA
*) AllocatePool (
1651 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
)
1653 if (NULL
== ModeBuffer
) {
1654 Status
= EFI_OUT_OF_RESOURCES
;
1658 if (ModeNumber
> 1) {
1661 BiosVideoPrivate
->ModeData
,
1662 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1666 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1667 FreePool (BiosVideoPrivate
->ModeData
);
1670 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1671 CurrentModeData
->VbeModeNumber
= VbeModeNumber
;
1672 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1673 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1674 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1675 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1676 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1677 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1678 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1679 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1680 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1681 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1683 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1684 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1685 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1686 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1687 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1688 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1689 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1690 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1691 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1694 CurrentModeData
->PixelFormat
= PixelBitMask
;
1695 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1696 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1697 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1698 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1699 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1700 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1704 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1705 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1706 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1707 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1709 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1710 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1711 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1713 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1714 CurrentModeData
->FrameBufferSize
= CurrentModeData
->BytesPerScanLine
* CurrentModeData
->VerticalResolution
;
1716 // Make sure the FrameBufferSize does not exceed the max available frame buffer size reported by VEB.
1718 ASSERT (CurrentModeData
->FrameBufferSize
<= (UINTN
)(BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024));
1720 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1723 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1725 if (ModeNumber
== 0) {
1726 Status
= EFI_DEVICE_ERROR
;
1731 // Assign Gop's Blt function
1733 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVbeBlt
;
1735 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) ModeNumber
;
1737 // Current mode is unknow till now, set it to an invalid mode.
1739 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1742 // Find the best mode to initialize
1744 if ((PcdGet32 (PcdVideoHorizontalResolution
) == 0x0) || (PcdGet32 (PcdVideoVerticalResolution
) == 0x0)) {
1746 BIOS_VIDEO_MODE_DATA
*ModeData
;
1747 ModeData
= &BiosVideoPrivate
->ModeData
[HighestResolutionMode
];
1748 DEBUG ((EFI_D_INFO
, "BiosVideo set highest resolution %d x %d\n",
1749 ModeData
->HorizontalResolution
, ModeData
->VerticalResolution
));
1751 PreferMode
= HighestResolutionMode
;
1753 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1754 if (EFI_ERROR (Status
)) {
1755 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1756 Status
= BiosVideoGraphicsOutputSetMode (
1757 &BiosVideoPrivate
->GraphicsOutput
,
1760 if (!EFI_ERROR (Status
)) {
1764 if (PreferMode
== ModeNumber
) {
1766 // None mode is set successfully.
1774 // If there was an error, then free the mode structure
1776 if (EFI_ERROR (Status
)) {
1777 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1778 FreePool (BiosVideoPrivate
->ModeData
);
1779 BiosVideoPrivate
->ModeData
= NULL
;
1780 BiosVideoPrivate
->MaxMode
= 0;
1782 if (EdidOverrideDataBlock
!= NULL
) {
1783 FreePool (EdidOverrideDataBlock
);
1792 Check for VGA device.
1794 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
1796 @retval EFI_SUCCESS Standard VGA device found
1800 BiosVideoCheckForVga (
1801 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1805 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1807 Status
= EFI_UNSUPPORTED
;
1810 // Assign Gop's Blt function
1812 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1815 // Add mode to the list of available modes
1816 // caller should guarantee that Mode has been allocated.
1818 ASSERT (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
);
1819 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1821 ModeBuffer
= (BIOS_VIDEO_MODE_DATA
*) AllocatePool (
1822 sizeof (BIOS_VIDEO_MODE_DATA
)
1824 if (NULL
== ModeBuffer
) {
1825 Status
= EFI_OUT_OF_RESOURCES
;
1829 ModeBuffer
->VbeModeNumber
= 0x0012;
1830 ModeBuffer
->BytesPerScanLine
= 640;
1831 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1832 ModeBuffer
->HorizontalResolution
= 640;
1833 ModeBuffer
->VerticalResolution
= 480;
1834 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1835 ModeBuffer
->BitsPerPixel
= 8;
1836 ModeBuffer
->ColorDepth
= 32;
1837 ModeBuffer
->RefreshRate
= 60;
1839 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1842 // Test to see if the Video Adapter support the 640x480 16 color mode
1844 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1845 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1849 // If there was an error, then free the mode structure
1851 if (EFI_ERROR (Status
)) {
1852 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1853 FreePool (BiosVideoPrivate
->ModeData
);
1854 BiosVideoPrivate
->ModeData
= NULL
;
1856 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1857 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1858 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1859 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
1861 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1862 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1869 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1873 Graphics Output protocol interface to get video mode.
1875 @param This Protocol instance pointer.
1876 @param ModeNumber The mode number to return information on.
1877 @param SizeOfInfo A pointer to the size, in bytes, of the Info
1879 @param Info Caller allocated buffer that returns information
1882 @retval EFI_SUCCESS Mode information returned.
1883 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
1885 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
1886 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
1891 BiosVideoGraphicsOutputQueryMode (
1892 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1893 IN UINT32 ModeNumber
,
1894 OUT UINTN
*SizeOfInfo
,
1895 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1898 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1899 BIOS_VIDEO_MODE_DATA
*ModeData
;
1901 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1903 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1904 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1905 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1906 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_OUTPUT_ERROR
,
1907 BiosVideoPrivate
->GopDevicePath
1909 return EFI_NOT_STARTED
;
1912 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1913 return EFI_INVALID_PARAMETER
;
1916 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
1917 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
1919 if (NULL
== *Info
) {
1920 return EFI_OUT_OF_RESOURCES
;
1923 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1925 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1926 (*Info
)->Version
= 0;
1927 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1928 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1929 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1930 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
1932 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1938 Worker function to set video mode.
1940 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.
1941 @param ModeData The mode data to be set.
1942 @param DevicePath Pointer to Device Path Protocol.
1944 @retval EFI_SUCCESS Graphics mode was changed.
1945 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1947 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1951 BiosVideoSetModeWorker (
1952 IN BIOS_VIDEO_DEV
*BiosVideoPrivate
,
1953 IN BIOS_VIDEO_MODE_DATA
*ModeData
,
1954 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1958 EFI_IA32_REGISTER_SET Regs
;
1960 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
1961 FreePool (BiosVideoPrivate
->LineBuffer
);
1964 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
1965 FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1968 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
1969 FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1972 BiosVideoPrivate
->LineBuffer
= (UINT8
*) AllocatePool (
1973 ModeData
->BytesPerScanLine
1975 if (NULL
== BiosVideoPrivate
->LineBuffer
) {
1976 return EFI_OUT_OF_RESOURCES
;
1979 // Clear all registers
1981 ZeroMem (&Regs
, sizeof (Regs
));
1983 if (ModeData
->VbeModeNumber
< 0x100) {
1985 // Allocate a working buffer for BLT operations to the VGA frame buffer
1987 BiosVideoPrivate
->VgaFrameBuffer
= (UINT8
*) AllocatePool (4 * 480 * 80);
1988 if (NULL
== BiosVideoPrivate
->VgaFrameBuffer
) {
1989 return EFI_OUT_OF_RESOURCES
;
1994 Regs
.X
.AX
= ModeData
->VbeModeNumber
;
1995 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1999 // Allocate a working buffer for BLT operations to the VBE frame buffer
2001 BiosVideoPrivate
->VbeFrameBuffer
=
2002 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
2003 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
2005 if (NULL
== BiosVideoPrivate
->VbeFrameBuffer
) {
2006 return EFI_OUT_OF_RESOURCES
;
2011 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
2012 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
2013 ZeroMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
));
2014 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
2015 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
2016 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
2019 // Check to see if the call succeeded
2021 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
2022 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
2023 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
2024 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_OUTPUT_ERROR
,
2027 return EFI_DEVICE_ERROR
;
2030 // Initialize the state of the VbeFrameBuffer
2032 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
2033 BiosVideoPrivate
->PciIo
,
2034 EfiPciIoWidthUint32
,
2035 EFI_PCI_IO_PASS_THROUGH_BAR
,
2036 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
2037 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
2038 BiosVideoPrivate
->VbeFrameBuffer
2040 if (EFI_ERROR (Status
)) {
2049 Graphics Output protocol interface to set video mode.
2051 @param This Protocol instance pointer.
2052 @param ModeNumber The mode number to be set.
2054 @retval EFI_SUCCESS Graphics mode was changed.
2055 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
2057 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
2062 BiosVideoGraphicsOutputSetMode (
2063 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
2064 IN UINT32 ModeNumber
2068 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2069 BIOS_VIDEO_MODE_DATA
*ModeData
;
2070 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
2073 return EFI_INVALID_PARAMETER
;
2076 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2078 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
2080 if (ModeNumber
>= This
->Mode
->MaxMode
) {
2081 return EFI_UNSUPPORTED
;
2084 if (ModeNumber
== This
->Mode
->Mode
) {
2086 // Clear screen to black
2088 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2089 BiosVideoGraphicsOutputVbeBlt (
2097 ModeData
->HorizontalResolution
,
2098 ModeData
->VerticalResolution
,
2104 Status
= BiosVideoSetModeWorker (BiosVideoPrivate
, ModeData
, BiosVideoPrivate
->GopDevicePath
);
2105 if (EFI_ERROR (Status
)) {
2109 This
->Mode
->Mode
= ModeNumber
;
2110 This
->Mode
->Info
->Version
= 0;
2111 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
2112 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
2113 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
2114 CopyMem (&(This
->Mode
->Info
->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof (ModeData
->PixelBitMask
));
2115 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
2116 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
2117 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
2118 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) ModeData
->LinearFrameBuffer
;
2120 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
2126 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
2128 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
2129 @param VbeBuffer The data to transfer to screen
2130 @param MemAddress Physical frame buffer base address
2131 @param DestinationX The X coordinate of the destination for BltOperation
2132 @param DestinationY The Y coordinate of the destination for BltOperation
2133 @param TotalBytes The total bytes of copy
2134 @param VbePixelWidth Bytes per pixel
2135 @param BytesPerScanLine Bytes per scan line
2140 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2141 IN UINT8
*VbeBuffer
,
2142 IN VOID
*MemAddress
,
2143 IN UINTN DestinationX
,
2144 IN UINTN DestinationY
,
2145 IN UINTN TotalBytes
,
2146 IN UINT32 VbePixelWidth
,
2147 IN UINTN BytesPerScanLine
2150 UINTN FrameBufferAddr
;
2152 UINTN RemainingBytes
;
2153 UINTN UnalignedBytes
;
2156 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
2159 // If TotalBytes is less than 4 bytes, only start byte copy.
2161 if (TotalBytes
< 4) {
2162 Status
= PciIo
->Mem
.Write (
2165 EFI_PCI_IO_PASS_THROUGH_BAR
,
2166 (UINT64
) FrameBufferAddr
,
2170 ASSERT_EFI_ERROR (Status
);
2175 // If VbeBuffer is not 4-byte aligned, start byte copy.
2177 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
2179 if (UnalignedBytes
!= 0) {
2180 Status
= PciIo
->Mem
.Write (
2183 EFI_PCI_IO_PASS_THROUGH_BAR
,
2184 (UINT64
) FrameBufferAddr
,
2188 ASSERT_EFI_ERROR (Status
);
2189 FrameBufferAddr
+= UnalignedBytes
;
2190 VbeBuffer
+= UnalignedBytes
;
2194 // Calculate 4-byte block count and remaining bytes.
2196 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
2197 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
2200 // Copy 4-byte block and remaining bytes to physical frame buffer.
2202 if (CopyBlockNum
!= 0) {
2203 Status
= PciIo
->Mem
.Write (
2205 EfiPciIoWidthUint32
,
2206 EFI_PCI_IO_PASS_THROUGH_BAR
,
2207 (UINT64
) FrameBufferAddr
,
2211 ASSERT_EFI_ERROR (Status
);
2214 if (RemainingBytes
!= 0) {
2215 FrameBufferAddr
+= (CopyBlockNum
<< 2);
2216 VbeBuffer
+= (CopyBlockNum
<< 2);
2217 Status
= PciIo
->Mem
.Write (
2220 EFI_PCI_IO_PASS_THROUGH_BAR
,
2221 (UINT64
) FrameBufferAddr
,
2225 ASSERT_EFI_ERROR (Status
);
2230 Worker function to block transfer for VBE device.
2232 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV
2233 @param BltBuffer The data to transfer to screen
2234 @param BltOperation The operation to perform
2235 @param SourceX The X coordinate of the source for BltOperation
2236 @param SourceY The Y coordinate of the source for BltOperation
2237 @param DestinationX The X coordinate of the destination for
2239 @param DestinationY The Y coordinate of the destination for
2241 @param Width The width of a rectangle in the blt rectangle in
2243 @param Height The height of a rectangle in the blt rectangle in
2245 @param Delta Not used for EfiBltVideoFill and
2246 EfiBltVideoToVideo operation. If a Delta of 0 is
2247 used, the entire BltBuffer will be operated on. If
2248 a subrectangle of the BltBuffer is used, then
2249 Delta represents the number of bytes in a row of
2251 @param Mode Mode data.
2253 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2254 @retval EFI_SUCCESS Blt operation success
2258 BiosVideoVbeBltWorker (
2259 IN BIOS_VIDEO_DEV
*BiosVideoPrivate
,
2260 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2261 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2264 IN UINTN DestinationX
,
2265 IN UINTN DestinationY
,
2269 IN BIOS_VIDEO_MODE_DATA
*Mode
2272 EFI_PCI_IO_PROTOCOL
*PciIo
;
2273 EFI_TPL OriginalTPL
;
2277 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
2279 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
2280 UINTN BytesPerScanLine
;
2285 UINT32 VbePixelWidth
;
2289 PciIo
= BiosVideoPrivate
->PciIo
;
2291 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
2292 MemAddress
= Mode
->LinearFrameBuffer
;
2293 BytesPerScanLine
= Mode
->BytesPerScanLine
;
2294 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
2295 BltUint8
= (UINT8
*) BltBuffer
;
2296 TotalBytes
= Width
* VbePixelWidth
;
2298 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2299 return EFI_INVALID_PARAMETER
;
2302 if (Width
== 0 || Height
== 0) {
2303 return EFI_INVALID_PARAMETER
;
2306 // We need to fill the Virtual Screen buffer with the blt data.
2307 // The virtual screen is upside down, as the first row is the bootom row of
2310 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2312 // Video to BltBuffer: Source is Video, destination is BltBuffer
2314 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
2315 return EFI_INVALID_PARAMETER
;
2318 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
2319 return EFI_INVALID_PARAMETER
;
2323 // BltBuffer to Video: Source is BltBuffer, destination is Video
2325 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
2326 return EFI_INVALID_PARAMETER
;
2329 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
2330 return EFI_INVALID_PARAMETER
;
2334 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2335 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2336 // the number of bytes in each row can be computed.
2339 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2342 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2343 // We would not want a timer based event (Cursor, ...) to come in while we are
2344 // doing this operation.
2346 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2348 switch (BltOperation
) {
2349 case EfiBltVideoToBltBuffer
:
2350 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
2351 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2353 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
2355 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
2356 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2357 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
2358 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
2359 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
2360 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
2363 VbeBuffer
+= VbePixelWidth
;
2369 case EfiBltVideoToVideo
:
2370 for (Index
= 0; Index
< Height
; Index
++) {
2371 if (DestinationY
<= SourceY
) {
2372 SrcY
= SourceY
+ Index
;
2373 DstY
= DestinationY
+ Index
;
2375 SrcY
= SourceY
+ Height
- Index
- 1;
2376 DstY
= DestinationY
+ Height
- Index
- 1;
2379 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2380 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2389 // Update physical frame buffer.
2404 case EfiBltVideoFill
:
2405 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2406 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2408 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2410 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2412 (Blt
->Green
& Mode
->Green
.Mask
) <<
2413 Mode
->Green
.Position
2415 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2417 for (Index
= 0; Index
< Width
; Index
++) {
2423 VbeBuffer
+= VbePixelWidth
;
2426 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2427 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2429 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2435 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2437 // Update physical frame buffer.
2452 case EfiBltBufferToVideo
:
2453 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2454 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2455 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2456 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2458 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2460 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2461 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2462 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2469 VbeBuffer
+= VbePixelWidth
;
2472 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2475 // Update physical frame buffer.
2493 gBS
->RestoreTPL (OriginalTPL
);
2499 Graphics Output protocol instance to block transfer for VBE device.
2501 @param This Pointer to Graphics Output protocol instance
2502 @param BltBuffer The data to transfer to screen
2503 @param BltOperation The operation to perform
2504 @param SourceX The X coordinate of the source for BltOperation
2505 @param SourceY The Y coordinate of the source for BltOperation
2506 @param DestinationX The X coordinate of the destination for
2508 @param DestinationY The Y coordinate of the destination for
2510 @param Width The width of a rectangle in the blt rectangle in
2512 @param Height The height of a rectangle in the blt rectangle in
2514 @param Delta Not used for EfiBltVideoFill and
2515 EfiBltVideoToVideo operation. If a Delta of 0 is
2516 used, the entire BltBuffer will be operated on. If
2517 a subrectangle of the BltBuffer is used, then
2518 Delta represents the number of bytes in a row of
2521 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2522 @retval EFI_SUCCESS Blt operation success
2527 BiosVideoGraphicsOutputVbeBlt (
2528 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2529 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2530 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2533 IN UINTN DestinationX
,
2534 IN UINTN DestinationY
,
2540 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2541 BIOS_VIDEO_MODE_DATA
*Mode
;
2544 return EFI_INVALID_PARAMETER
;
2547 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2548 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
2550 return BiosVideoVbeBltWorker (
2566 Write graphics controller registers.
2568 @param PciIo Pointer to PciIo protocol instance of the
2570 @param Address Register address
2571 @param Data Data to be written to register
2577 WriteGraphicsController (
2578 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2583 Address
= Address
| (Data
<< 8);
2586 EfiPciIoWidthUint16
,
2587 EFI_PCI_IO_PASS_THROUGH_BAR
,
2588 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2596 Read the four bit plane of VGA frame buffer.
2598 @param PciIo Pointer to PciIo protocol instance of the
2600 @param HardwareBuffer Hardware VGA frame buffer address
2601 @param MemoryBuffer Memory buffer address
2602 @param WidthInBytes Number of bytes in a line to read
2603 @param Height Height of the area to read
2610 EFI_PCI_IO_PROTOCOL
*PciIo
,
2611 UINT8
*HardwareBuffer
,
2612 UINT8
*MemoryBuffer
,
2619 UINTN FrameBufferOffset
;
2624 // Program the Mode Register Write mode 0, Read mode 0
2626 WriteGraphicsController (
2628 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2629 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2632 for (BitPlane
= 0, FrameBufferOffset
= 0;
2633 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2634 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2637 // Program the Read Map Select Register to select the correct bit plane
2639 WriteGraphicsController (
2641 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2645 Source
= HardwareBuffer
;
2646 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2648 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2652 EFI_PCI_IO_PASS_THROUGH_BAR
,
2653 (UINT64
) (UINTN
) Source
,
2655 (VOID
*) Destination
2663 Internal routine to convert VGA color to Grahpics Output color.
2665 @param MemoryBuffer Buffer containing VGA color
2666 @param CoordinateX The X coordinate of pixel on screen
2667 @param CoordinateY The Y coordinate of pixel on screen
2668 @param BltBuffer Buffer to contain converted Grahpics Output color
2674 VgaConvertToGraphicsOutputColor (
2675 UINT8
*MemoryBuffer
,
2678 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2685 MemoryBuffer
+= ((CoordinateY
<< 6) + (CoordinateY
<< 4) + (CoordinateX
>> 3));
2686 Mask
= mVgaBitMaskTable
[CoordinateX
& 0x07];
2687 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2688 if ((*MemoryBuffer
& Mask
) != 0) {
2693 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2697 Internal routine to convert Grahpics Output color to VGA color.
2699 @param BltBuffer buffer containing Grahpics Output color
2701 @return Converted VGA color
2706 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2711 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2712 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2721 Grahpics Output protocol instance to block transfer for VGA device.
2723 @param This Pointer to Grahpics Output protocol instance
2724 @param BltBuffer The data to transfer to screen
2725 @param BltOperation The operation to perform
2726 @param SourceX The X coordinate of the source for BltOperation
2727 @param SourceY The Y coordinate of the source for BltOperation
2728 @param DestinationX The X coordinate of the destination for
2730 @param DestinationY The Y coordinate of the destination for
2732 @param Width The width of a rectangle in the blt rectangle in
2734 @param Height The height of a rectangle in the blt rectangle in
2736 @param Delta Not used for EfiBltVideoFill and
2737 EfiBltVideoToVideo operation. If a Delta of 0 is
2738 used, the entire BltBuffer will be operated on. If
2739 a subrectangle of the BltBuffer is used, then
2740 Delta represents the number of bytes in a row of
2743 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2744 @retval EFI_SUCCESS Blt operation success
2749 BiosVideoGraphicsOutputVgaBlt (
2750 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2751 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2752 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2755 IN UINTN DestinationX
,
2756 IN UINTN DestinationY
,
2762 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2763 EFI_TPL OriginalTPL
;
2765 UINTN BytesPerScanLine
;
2777 UINT8
*SourceAddress
;
2778 UINT8
*DestinationAddress
;
2779 EFI_PCI_IO_PROTOCOL
*PciIo
;
2782 UINT8
*VgaFrameBuffer
;
2791 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2792 return EFI_INVALID_PARAMETER
;
2795 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2797 CurrentMode
= This
->Mode
->Mode
;
2798 PciIo
= BiosVideoPrivate
->PciIo
;
2799 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2800 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2801 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2804 if (Width
== 0 || Height
== 0) {
2805 return EFI_INVALID_PARAMETER
;
2808 // We need to fill the Virtual Screen buffer with the blt data.
2809 // The virtual screen is upside down, as the first row is the bootom row of
2812 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2814 // Video to BltBuffer: Source is Video, destination is BltBuffer
2816 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2817 return EFI_INVALID_PARAMETER
;
2820 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2821 return EFI_INVALID_PARAMETER
;
2825 // BltBuffer to Video: Source is BltBuffer, destination is Video
2827 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2828 return EFI_INVALID_PARAMETER
;
2831 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2832 return EFI_INVALID_PARAMETER
;
2836 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2837 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2838 // the number of bytes in each row can be computed.
2841 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2844 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2845 // We would not want a timer based event (Cursor, ...) to come in while we are
2846 // doing this operation.
2848 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2851 // Compute some values we need for VGA
2853 switch (BltOperation
) {
2854 case EfiBltVideoToBltBuffer
:
2856 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2857 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2860 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2864 MemAddress
+ SourceOffset
,
2865 VgaFrameBuffer
+ SourceOffset
,
2871 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2873 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2874 for (Rows
= 0, CoordinateY
= SourceY
; Rows
< Height
; Rows
++, CoordinateY
++, BltBuffer
+= (Delta
>> 2)) {
2875 for (Columns
= 0, CoordinateX
= SourceX
; Columns
< Width
; Columns
++, CoordinateX
++, BltBuffer
++) {
2876 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, CoordinateX
, CoordinateY
, BltBuffer
);
2884 case EfiBltVideoToVideo
:
2886 // Check for an aligned Video to Video operation
2888 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2890 // Program the Mode Register Write mode 1, Read mode 0
2892 WriteGraphicsController (
2894 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2895 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2898 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2899 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2901 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2905 EFI_PCI_IO_PASS_THROUGH_BAR
,
2906 (UINT64
) (UINTN
) (DestinationAddress
+ Offset
),
2907 EFI_PCI_IO_PASS_THROUGH_BAR
,
2908 (UINT64
) (UINTN
) (SourceAddress
+ Offset
),
2913 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2914 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2917 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2921 MemAddress
+ SourceOffset
,
2922 VgaFrameBuffer
+ SourceOffset
,
2930 case EfiBltVideoFill
:
2931 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2932 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2933 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2934 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2936 LeftMask
= (UINT8
) (LeftMask
& RightMask
);
2940 if (LeftMask
== 0xff) {
2946 if (RightMask
== 0xff) {
2951 PixelColor
= VgaConvertColor (BltBuffer
);
2954 // Program the Mode Register Write mode 2, Read mode 0
2956 WriteGraphicsController (
2958 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2959 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2963 // Program the Data Rotate/Function Select Register to replace
2965 WriteGraphicsController (
2967 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2968 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2971 if (LeftMask
!= 0) {
2973 // Program the BitMask register with the Left column mask
2975 WriteGraphicsController (
2977 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2981 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2983 // Read data from the bit planes into the latches
2988 EFI_PCI_IO_PASS_THROUGH_BAR
,
2989 (UINT64
) (UINTN
) Address
,
2994 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2999 EFI_PCI_IO_PASS_THROUGH_BAR
,
3000 (UINT64
) (UINTN
) Address
,
3009 // Program the BitMask register with the middle column mask of 0xff
3011 WriteGraphicsController (
3013 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
3017 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
3020 EfiPciIoWidthFillUint8
,
3021 EFI_PCI_IO_PASS_THROUGH_BAR
,
3022 (UINT64
) (UINTN
) Address
,
3029 if (RightMask
!= 0) {
3031 // Program the BitMask register with the Right column mask
3033 WriteGraphicsController (
3035 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
3039 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
3041 // Read data from the bit planes into the latches
3046 EFI_PCI_IO_PASS_THROUGH_BAR
,
3047 (UINT64
) (UINTN
) Address
,
3052 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
3057 EFI_PCI_IO_PASS_THROUGH_BAR
,
3058 (UINT64
) (UINTN
) Address
,
3066 case EfiBltBufferToVideo
:
3067 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
3068 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
3071 // Program the Mode Register Write mode 2, Read mode 0
3073 WriteGraphicsController (
3075 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
3076 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
3080 // Program the Data Rotate/Function Select Register to replace
3082 WriteGraphicsController (
3084 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
3085 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
3088 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
3089 for (Index1
= 0; Index1
< Width
; Index1
++) {
3090 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
3092 AddressFix
= Address
;
3094 for (Bit
= 0; Bit
< 8; Bit
++) {
3096 // Program the BitMask register with the Left column mask
3098 WriteGraphicsController (
3100 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
3104 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
3106 // Read data from the bit planes into the latches
3111 EFI_PCI_IO_PASS_THROUGH_BAR
,
3112 (UINT64
) (UINTN
) Address1
,
3120 EFI_PCI_IO_PASS_THROUGH_BAR
,
3121 (UINT64
) (UINTN
) Address1
,
3123 &BiosVideoPrivate
->LineBuffer
[Index1
]
3127 LeftMask
= (UINT8
) (LeftMask
>> 1);
3128 if (LeftMask
== 0) {
3140 gBS
->RestoreTPL (OriginalTPL
);
3146 // VGA Mini Port Protocol Functions
3150 VgaMiniPort protocol interface to set mode.
3152 @param This Pointer to VgaMiniPort protocol instance
3153 @param ModeNumber The index of the mode
3155 @retval EFI_UNSUPPORTED The requested mode is not supported
3156 @retval EFI_SUCCESS The requested mode is set successfully
3161 BiosVideoVgaMiniPortSetMode (
3162 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
3166 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
3167 EFI_IA32_REGISTER_SET Regs
;
3170 return EFI_INVALID_PARAMETER
;
3174 // Make sure the ModeNumber is a valid value
3176 if (ModeNumber
>= This
->MaxMode
) {
3177 return EFI_UNSUPPORTED
;
3180 // Get the device structure for this device
3182 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
3184 switch (ModeNumber
) {
3187 // Set the 80x25 Text VGA Mode
3191 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3196 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3201 // Set the 80x50 Text VGA Mode
3205 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3209 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3213 return EFI_UNSUPPORTED
;
3220 Event handler for Exit Boot Service.
3222 @param Event The event that be siganlled when exiting boot service.
3223 @param Context Pointer to instance of BIOS_VIDEO_DEV.
3228 BiosVideoNotifyExitBootServices (
3233 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
3234 EFI_IA32_REGISTER_SET Regs
;
3236 BiosVideoPrivate
= (BIOS_VIDEO_DEV
*)Context
;
3239 // Set the 80x25 Text VGA Mode
3243 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3247 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3252 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3256 The user Entry Point for module UefiBiosVideo. The user code starts with this function.
3258 @param[in] ImageHandle The firmware allocated handle for the EFI image.
3259 @param[in] SystemTable A pointer to the EFI System Table.
3261 @retval EFI_SUCCESS The entry point is executed successfully.
3262 @retval other Some error occurs when executing this entry point.
3267 BiosVideoEntryPoint(
3268 IN EFI_HANDLE ImageHandle
,
3269 IN EFI_SYSTEM_TABLE
*SystemTable
3275 // Install driver model protocol(s).
3277 Status
= EfiLibInstallDriverBindingComponentName2 (
3280 &gBiosVideoDriverBinding
,
3282 &gBiosVideoComponentName
,
3283 &gBiosVideoComponentName2
3285 ASSERT_EFI_ERROR (Status
);
3288 // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
3290 return gBS
->InstallMultipleProtocolInterfaces (
3292 &gEfiLegacyBiosGuid
,