2 ConsoleOut Routines that speak VGA.
4 Copyright (c) 2007 - 2011, 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 };
40 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor
[] = {
41 { 0x00, 0x00, 0x00, 0x00 },
42 { 0x98, 0x00, 0x00, 0x00 },
43 { 0x00, 0x98, 0x00, 0x00 },
44 { 0x98, 0x98, 0x00, 0x00 },
45 { 0x00, 0x00, 0x98, 0x00 },
46 { 0x98, 0x00, 0x98, 0x00 },
47 { 0x00, 0x98, 0x98, 0x00 },
48 { 0x98, 0x98, 0x98, 0x00 },
49 { 0x10, 0x10, 0x10, 0x00 },
50 { 0xff, 0x10, 0x10, 0x00 },
51 { 0x10, 0xff, 0x10, 0x00 },
52 { 0xff, 0xff, 0x10, 0x00 },
53 { 0x10, 0x10, 0xff, 0x00 },
54 { 0xf0, 0x10, 0xff, 0x00 },
55 { 0x10, 0xff, 0xff, 0x00 },
56 { 0xff, 0xff, 0xff, 0x00 }
60 // Standard timing defined by VESA EDID
62 VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming
[] = {
64 // Established Timing I
75 // Established Timing II
86 // Established Timing III
94 @param This Pointer to driver binding protocol
95 @param Controller Controller handle to connect
96 @param RemainingDevicePath A pointer to the remaining portion of a device
99 @retval EFI_STATUS EFI_SUCCESS:This controller can be managed by this
100 driver, Otherwise, this controller cannot be
101 managed by this driver
106 BiosVideoDriverBindingSupported (
107 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
108 IN EFI_HANDLE Controller
,
109 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
113 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
114 EFI_PCI_IO_PROTOCOL
*PciIo
;
119 // See if the Legacy BIOS Protocol is available
121 Status
= gBS
->LocateProtocol (&gEfiLegacyBiosProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
122 if (EFI_ERROR (Status
)) {
127 // Open the IO Abstraction(s) needed to perform the supported test
129 Status
= gBS
->OpenProtocol (
131 &gEfiPciIoProtocolGuid
,
133 This
->DriverBindingHandle
,
135 EFI_OPEN_PROTOCOL_BY_DRIVER
137 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
141 if (Status
== EFI_ALREADY_STARTED
) {
143 // If VgaMiniPort protocol is installed, EFI_ALREADY_STARTED indicates failure,
144 // because VgaMiniPort protocol is installed on controller handle directly.
146 Status
= gBS
->OpenProtocol (
148 &gEfiVgaMiniPortProtocolGuid
,
152 EFI_OPEN_PROTOCOL_TEST_PROTOCOL
154 if (!EFI_ERROR (Status
)) {
155 return EFI_ALREADY_STARTED
;
159 // See if this is a PCI Graphics Controller by looking at the Command register and
160 // Class Code Register
162 Status
= PciIo
->Pci
.Read (
166 sizeof (Pci
) / sizeof (UINT32
),
169 if (EFI_ERROR (Status
)) {
170 Status
= EFI_UNSUPPORTED
;
174 Status
= EFI_UNSUPPORTED
;
175 if (Pci
.Hdr
.ClassCode
[2] == 0x03 || (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01)) {
177 Status
= EFI_SUCCESS
;
179 // If this is a graphics controller,
180 // go further check RemainingDevicePath validation
182 if (RemainingDevicePath
!= NULL
) {
183 Node
= (EFI_DEV_PATH
*) RemainingDevicePath
;
185 // Check if RemainingDevicePath is the End of Device Path Node,
186 // if yes, return EFI_SUCCESS
188 if (!IsDevicePathEnd (Node
)) {
190 // If RemainingDevicePath isn't the End of Device Path Node,
191 // check its validation
193 if (Node
->DevPath
.Type
!= ACPI_DEVICE_PATH
||
194 Node
->DevPath
.SubType
!= ACPI_ADR_DP
||
195 DevicePathNodeLength(&Node
->DevPath
) != sizeof(ACPI_ADR_DEVICE_PATH
)) {
196 Status
= EFI_UNSUPPORTED
;
205 &gEfiPciIoProtocolGuid
,
206 This
->DriverBindingHandle
,
215 Install Graphics Output Protocol onto VGA device handles.
217 @param This Pointer to driver binding protocol
218 @param Controller Controller handle to connect
219 @param RemainingDevicePath A pointer to the remaining portion of a device
227 BiosVideoDriverBindingStart (
228 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
229 IN EFI_HANDLE Controller
,
230 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
234 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
235 EFI_PCI_IO_PROTOCOL
*PciIo
;
236 EFI_LEGACY_BIOS_PROTOCOL
*LegacyBios
;
238 UINT64 OriginalPciAttributes
;
240 BOOLEAN PciAttributesSaved
;
243 // Initialize local variables
246 ParentDevicePath
= NULL
;
250 // See if the Legacy BIOS Protocol is available
252 Status
= gBS
->LocateProtocol (&gEfiLegacyBiosProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
253 if (EFI_ERROR (Status
)) {
258 // Prepare for status code
260 Status
= gBS
->HandleProtocol (
262 &gEfiDevicePathProtocolGuid
,
263 (VOID
**) &ParentDevicePath
265 if (EFI_ERROR (Status
)) {
270 // Open the IO Abstraction(s) needed
272 Status
= gBS
->OpenProtocol (
274 &gEfiPciIoProtocolGuid
,
276 This
->DriverBindingHandle
,
278 EFI_OPEN_PROTOCOL_BY_DRIVER
280 if (EFI_ERROR (Status
) && (Status
!= EFI_ALREADY_STARTED
)) {
284 PciAttributesSaved
= FALSE
;
286 // Save original PCI attributes
288 Status
= PciIo
->Attributes (
290 EfiPciIoAttributeOperationGet
,
292 &OriginalPciAttributes
295 if (EFI_ERROR (Status
)) {
298 PciAttributesSaved
= TRUE
;
301 // Get supported PCI attributes
303 Status
= PciIo
->Attributes (
305 EfiPciIoAttributeOperationSupported
,
309 if (EFI_ERROR (Status
)) {
313 Supports
&= (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
);
314 if (Supports
== 0 || Supports
== (EFI_PCI_IO_ATTRIBUTE_VGA_IO
| EFI_PCI_IO_ATTRIBUTE_VGA_IO_16
)) {
315 Status
= EFI_UNSUPPORTED
;
319 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
321 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_ENABLE
,
325 // Enable the device and make sure VGA cycles are being forwarded to this VGA device
327 Status
= PciIo
->Attributes (
329 EfiPciIoAttributeOperationEnable
,
330 EFI_PCI_DEVICE_ENABLE
| EFI_PCI_IO_ATTRIBUTE_VGA_MEMORY
| Supports
,
333 if (EFI_ERROR (Status
)) {
334 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
335 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
336 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_RESOURCE_CONFLICT
,
342 // Check to see if there is a legacy option ROM image associated with this PCI device
344 Status
= LegacyBios
->CheckPciRom (
351 if (EFI_ERROR (Status
)) {
355 // Post the legacy option ROM if it is available.
357 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
362 Status
= LegacyBios
->InstallPciRom (
372 if (EFI_ERROR (Status
)) {
373 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
374 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
375 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
381 if (RemainingDevicePath
!= NULL
) {
382 if (IsDevicePathEnd (RemainingDevicePath
) &&
383 (FeaturePcdGet (PcdBiosVideoCheckVbeEnable
) || FeaturePcdGet (PcdBiosVideoCheckVgaEnable
))) {
385 // If RemainingDevicePath is the End of Device Path Node,
386 // don't create any child device and return EFI_SUCESS
387 Status
= EFI_SUCCESS
;
393 // Create child handle and install GraphicsOutputProtocol on it
395 Status
= BiosVideoChildHandleInstall (
402 OriginalPciAttributes
406 if ((EFI_ERROR (Status
)) && (Status
!= EFI_ALREADY_STARTED
)) {
407 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
409 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_PC_DISABLE
,
413 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
415 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_NOT_DETECTED
,
418 if (PciAttributesSaved
) {
420 // Restore original PCI attributes
424 EfiPciIoAttributeOperationSet
,
425 OriginalPciAttributes
,
430 // Release PCI I/O Protocols on the controller handle.
434 &gEfiPciIoProtocolGuid
,
435 This
->DriverBindingHandle
,
447 @param This Pointer to driver binding protocol
448 @param Controller Controller handle to connect
449 @param NumberOfChildren Number of children handle created by this driver
450 @param ChildHandleBuffer Buffer containing child handle created
452 @retval EFI_SUCCESS Driver disconnected successfully from controller
453 @retval EFI_UNSUPPORTED Cannot find BIOS_VIDEO_DEV structure
458 BiosVideoDriverBindingStop (
459 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
460 IN EFI_HANDLE Controller
,
461 IN UINTN NumberOfChildren
,
462 IN EFI_HANDLE
*ChildHandleBuffer
466 BOOLEAN AllChildrenStopped
;
469 AllChildrenStopped
= TRUE
;
471 if (NumberOfChildren
== 0) {
473 // Close PCI I/O protocol on the controller handle
477 &gEfiPciIoProtocolGuid
,
478 This
->DriverBindingHandle
,
485 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
486 Status
= BiosVideoChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
488 if (EFI_ERROR (Status
)) {
489 AllChildrenStopped
= FALSE
;
493 if (!AllChildrenStopped
) {
494 return EFI_DEVICE_ERROR
;
502 Install child handles if the Handle supports MBR format.
504 @param This Calling context.
505 @param ParentHandle Parent Handle
506 @param ParentPciIo Parent PciIo interface
507 @param ParentLegacyBios Parent LegacyBios interface
508 @param ParentDevicePath Parent Device Path
509 @param RemainingDevicePath Remaining Device Path
510 @param OriginalPciAttributes Original PCI Attributes
512 @retval EFI_SUCCESS If a child handle was added
513 @retval other A child handle was not added
517 BiosVideoChildHandleInstall (
518 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
519 IN EFI_HANDLE ParentHandle
,
520 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
521 IN EFI_LEGACY_BIOS_PROTOCOL
*ParentLegacyBios
,
522 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
523 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
,
524 IN UINT64 OriginalPciAttributes
528 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
530 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
531 BOOLEAN ProtocolInstalled
;
534 // Allocate the private device structure for video device
536 BiosVideoPrivate
= (BIOS_VIDEO_DEV
*) AllocateZeroPool (
537 sizeof (BIOS_VIDEO_DEV
)
539 if (NULL
== BiosVideoPrivate
) {
540 Status
= EFI_OUT_OF_RESOURCES
;
545 // See if this is a VGA compatible controller or not
547 Status
= ParentPciIo
->Pci
.Read (
551 sizeof (Pci
) / sizeof (UINT32
),
554 if (EFI_ERROR (Status
)) {
555 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
556 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
557 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_CONTROLLER_ERROR
,
562 BiosVideoPrivate
->VgaCompatible
= FALSE
;
563 if (Pci
.Hdr
.ClassCode
[2] == 0x00 && Pci
.Hdr
.ClassCode
[1] == 0x01) {
564 BiosVideoPrivate
->VgaCompatible
= TRUE
;
567 if (Pci
.Hdr
.ClassCode
[2] == 0x03 && Pci
.Hdr
.ClassCode
[1] == 0x00 && Pci
.Hdr
.ClassCode
[0] == 0x00) {
568 BiosVideoPrivate
->VgaCompatible
= TRUE
;
571 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable
)) {
573 // Create EXIT_BOOT_SERIVES Event
575 Status
= gBS
->CreateEventEx (
578 BiosVideoNotifyExitBootServices
,
580 &gEfiEventExitBootServicesGuid
,
581 &BiosVideoPrivate
->ExitBootServicesEvent
583 if (EFI_ERROR (Status
)) {
589 // Initialize the child private structure
591 BiosVideoPrivate
->Signature
= BIOS_VIDEO_DEV_SIGNATURE
;
594 // Fill in Graphics Output specific mode structures
596 BiosVideoPrivate
->HardwareNeedsStarting
= TRUE
;
597 BiosVideoPrivate
->ModeData
= NULL
;
598 BiosVideoPrivate
->LineBuffer
= NULL
;
599 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
600 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
603 // Fill in the Graphics Output Protocol
605 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
606 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
610 // Allocate buffer for Graphics Output Protocol mode information
612 BiosVideoPrivate
->GraphicsOutput
.Mode
= (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*) AllocatePool (
613 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
)
615 if (NULL
== BiosVideoPrivate
->GraphicsOutput
.Mode
) {
616 Status
= EFI_OUT_OF_RESOURCES
;
620 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
621 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
623 if (NULL
== BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
) {
624 Status
= EFI_OUT_OF_RESOURCES
;
629 // Assume that Graphics Output Protocol will be produced until proven otherwise
631 BiosVideoPrivate
->ProduceGraphicsOutput
= TRUE
;
634 // Set Gop Device Path, here RemainingDevicePath will not be one End of Device Path Node.
636 if ((RemainingDevicePath
== NULL
) || (!IsDevicePathEnd (RemainingDevicePath
))) {
637 if (RemainingDevicePath
== NULL
) {
638 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
639 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
640 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
641 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
642 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
644 BiosVideoPrivate
->GopDevicePath
= AppendDevicePathNode (
646 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
649 BiosVideoPrivate
->GopDevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
653 // Creat child handle and device path protocol firstly
655 BiosVideoPrivate
->Handle
= NULL
;
656 Status
= gBS
->InstallMultipleProtocolInterfaces (
657 &BiosVideoPrivate
->Handle
,
658 &gEfiDevicePathProtocolGuid
,
659 BiosVideoPrivate
->GopDevicePath
,
662 if (EFI_ERROR (Status
)) {
668 // Fill in the VGA Mini Port Protocol fields
670 BiosVideoPrivate
->VgaMiniPort
.SetMode
= BiosVideoVgaMiniPortSetMode
;
671 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryOffset
= 0xb8000;
672 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterOffset
= 0x3d4;
673 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterOffset
= 0x3d5;
674 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
675 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
676 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
679 // Child handle need to consume the Legacy Bios protocol
681 BiosVideoPrivate
->LegacyBios
= ParentLegacyBios
;
684 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
686 BiosVideoPrivate
->PciIo
= ParentPciIo
;
687 BiosVideoPrivate
->OriginalPciAttributes
= OriginalPciAttributes
;
690 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
692 if (FeaturePcdGet (PcdBiosVideoCheckVbeEnable
)) {
693 Status
= BiosVideoCheckForVbe (BiosVideoPrivate
);
694 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVbe - %r\n", Status
));
696 Status
= EFI_UNSUPPORTED
;
698 if (EFI_ERROR (Status
)) {
700 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
701 // for the standard 640x480 16 color VGA mode
703 DEBUG ((EFI_D_INFO
, "VgaCompatible - %x\n", BiosVideoPrivate
->VgaCompatible
));
704 if (BiosVideoPrivate
->VgaCompatible
) {
705 if (FeaturePcdGet (PcdBiosVideoCheckVgaEnable
)) {
706 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
707 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVga - %r\n", Status
));
709 Status
= EFI_UNSUPPORTED
;
713 if (EFI_ERROR (Status
)) {
715 // Free GOP mode structure if it is not freed before
716 // VgaMiniPort does not need this structure any more
718 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
719 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
720 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
721 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
723 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
724 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
728 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
729 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
731 BiosVideoPrivate
->ProduceGraphicsOutput
= FALSE
;
734 // INT services are available, so on the 80x25 and 80x50 text mode are supported
736 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
740 ProtocolInstalled
= FALSE
;
742 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
744 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
746 Status
= gBS
->InstallMultipleProtocolInterfaces (
747 &BiosVideoPrivate
->Handle
,
748 &gEfiGraphicsOutputProtocolGuid
,
749 &BiosVideoPrivate
->GraphicsOutput
,
750 &gEfiEdidDiscoveredProtocolGuid
,
751 &BiosVideoPrivate
->EdidDiscovered
,
752 &gEfiEdidActiveProtocolGuid
,
753 &BiosVideoPrivate
->EdidActive
,
757 if (!EFI_ERROR (Status
)) {
759 // Open the Parent Handle for the child
761 Status
= gBS
->OpenProtocol (
763 &gEfiPciIoProtocolGuid
,
764 (VOID
**) &BiosVideoPrivate
->PciIo
,
765 This
->DriverBindingHandle
,
766 BiosVideoPrivate
->Handle
,
767 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
769 if (EFI_ERROR (Status
)) {
772 ProtocolInstalled
= TRUE
;
776 if (!ProtocolInstalled
) {
778 // Install VGA Mini Port Protocol
780 Status
= gBS
->InstallMultipleProtocolInterfaces (
782 &gEfiVgaMiniPortProtocolGuid
,
783 &BiosVideoPrivate
->VgaMiniPort
,
789 if (EFI_ERROR (Status
)) {
790 if ((BiosVideoPrivate
!= NULL
) && (BiosVideoPrivate
->ExitBootServicesEvent
!= NULL
)) {
791 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
794 // Free private data structure
796 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
804 Deregister an video child handle and free resources.
806 @param This Protocol instance pointer.
807 @param Controller Video controller handle
808 @param Handle Video child handle
814 BiosVideoChildHandleUninstall (
815 EFI_DRIVER_BINDING_PROTOCOL
*This
,
816 EFI_HANDLE Controller
,
821 EFI_IA32_REGISTER_SET Regs
;
822 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
823 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
824 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
825 EFI_PCI_IO_PROTOCOL
*PciIo
;
827 BiosVideoPrivate
= NULL
;
828 GraphicsOutput
= NULL
;
830 Status
= EFI_UNSUPPORTED
;
832 Status
= gBS
->OpenProtocol (
834 &gEfiGraphicsOutputProtocolGuid
,
835 (VOID
**) &GraphicsOutput
,
836 This
->DriverBindingHandle
,
838 EFI_OPEN_PROTOCOL_GET_PROTOCOL
840 if (!EFI_ERROR (Status
)) {
841 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
844 if (EFI_ERROR (Status
)) {
845 Status
= gBS
->OpenProtocol (
847 &gEfiVgaMiniPortProtocolGuid
,
848 (VOID
**) &VgaMiniPort
,
849 This
->DriverBindingHandle
,
851 EFI_OPEN_PROTOCOL_GET_PROTOCOL
853 if (!EFI_ERROR (Status
)) {
854 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
858 if (BiosVideoPrivate
== NULL
) {
859 return EFI_UNSUPPORTED
;
863 // Set the 80x25 Text VGA Mode
867 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
872 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
875 // Restore original PCI attributes
877 Status
= BiosVideoPrivate
->PciIo
->Attributes (
878 BiosVideoPrivate
->PciIo
,
879 EfiPciIoAttributeOperationSet
,
880 BiosVideoPrivate
->OriginalPciAttributes
,
883 ASSERT_EFI_ERROR (Status
);
886 // Close PCI I/O protocol that opened by child handle
888 Status
= gBS
->CloseProtocol (
890 &gEfiPciIoProtocolGuid
,
891 This
->DriverBindingHandle
,
896 // Uninstall protocols on child handle
898 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
899 Status
= gBS
->UninstallMultipleProtocolInterfaces (
900 BiosVideoPrivate
->Handle
,
901 &gEfiDevicePathProtocolGuid
,
902 BiosVideoPrivate
->GopDevicePath
,
903 &gEfiGraphicsOutputProtocolGuid
,
904 &BiosVideoPrivate
->GraphicsOutput
,
905 &gEfiEdidDiscoveredProtocolGuid
,
906 &BiosVideoPrivate
->EdidDiscovered
,
907 &gEfiEdidActiveProtocolGuid
,
908 &BiosVideoPrivate
->EdidActive
,
912 if (!BiosVideoPrivate
->ProduceGraphicsOutput
) {
913 Status
= gBS
->UninstallMultipleProtocolInterfaces (
915 &gEfiVgaMiniPortProtocolGuid
,
916 &BiosVideoPrivate
->VgaMiniPort
,
921 if (EFI_ERROR (Status
)) {
924 &gEfiPciIoProtocolGuid
,
926 This
->DriverBindingHandle
,
928 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
933 if (PcdGetBool (PcdBiosVideoSetTextVgaModeEnable
)) {
935 // Close EXIT_BOOT_SERIVES Event
937 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
941 // Release all allocated resources
943 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
950 Release resource for biso video instance.
952 @param BiosVideoPrivate Video child device private data structure
956 BiosVideoDeviceReleaseResource (
957 BIOS_VIDEO_DEV
*BiosVideoPrivate
960 if (BiosVideoPrivate
== NULL
) {
965 // Release all the resourses occupied by the BIOS_VIDEO_DEV
969 // Free VGA Frame Buffer
971 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
972 FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
975 // Free VBE Frame Buffer
977 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
978 FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
983 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
984 FreePool (BiosVideoPrivate
->LineBuffer
);
989 if (BiosVideoPrivate
->ModeData
!= NULL
) {
990 FreePool (BiosVideoPrivate
->ModeData
);
993 // Free memory allocated below 1MB
995 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
996 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
999 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
1000 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
1004 // Free graphics output protocol occupied resource
1006 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1007 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1008 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1009 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
1011 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1012 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1015 // Free EDID discovered protocol occupied resource
1017 if (BiosVideoPrivate
->EdidDiscovered
.Edid
!= NULL
) {
1018 FreePool (BiosVideoPrivate
->EdidDiscovered
.Edid
);
1021 // Free EDID active protocol occupied resource
1023 if (BiosVideoPrivate
->EdidActive
.Edid
!= NULL
) {
1024 FreePool (BiosVideoPrivate
->EdidActive
.Edid
);
1027 if (BiosVideoPrivate
->GopDevicePath
!= NULL
) {
1028 FreePool (BiosVideoPrivate
->GopDevicePath
);
1031 FreePool (BiosVideoPrivate
);
1038 Generate a search key for a specified timing data.
1040 @param EdidTiming Pointer to EDID timing
1042 @return The 32 bit unique key for search.
1047 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
1053 // Be sure no conflicts for all standard timing defined by VESA.
1055 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
1061 Parse the Established Timing and Standard Timing in EDID data block.
1063 @param EdidBuffer Pointer to EDID data block
1064 @param ValidEdidTiming Valid EDID timing information
1066 @retval TRUE The EDID data is valid.
1067 @retval FALSE The EDID data is invalid.
1073 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
1081 UINT16 HorizontalResolution
;
1082 UINT16 VerticalResolution
;
1085 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming
;
1086 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*EdidDataBlock
;
1088 EdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) EdidBuffer
;
1091 // Check the checksum of EDID data
1094 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
; Index
++) {
1095 CheckSum
= (UINT8
) (CheckSum
+ EdidBuffer
[Index
]);
1097 if (CheckSum
!= 0) {
1102 gBS
->SetMem (ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
), 0);
1104 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
1105 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
1106 (EdidDataBlock
->EstablishedTimings
[2] != 0)
1109 // Established timing data
1111 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
1112 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
1113 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
1114 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
1115 if ((TimingBits
& 0x1) != 0) {
1116 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mEstablishedEdidTiming
[Index
]);
1119 TimingBits
= TimingBits
>> 1;
1123 // If no Established timing data, read the standard timing data
1125 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
1126 for (Index
= 0; Index
< 8; Index
++) {
1127 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
1129 // A valid Standard Timing
1131 HorizontalResolution
= (UINT16
) (BufferIndex
[0] * 8 + 248);
1132 AspectRatio
= (UINT8
) (BufferIndex
[1] >> 6);
1133 switch (AspectRatio
) {
1135 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 10);
1138 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
1141 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 5 * 4);
1144 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 16 * 9);
1147 VerticalResolution
= (UINT16
) (HorizontalResolution
/ 4 * 3);
1150 RefreshRate
= (UINT8
) ((BufferIndex
[1] & 0x1f) + 60);
1151 TempTiming
.HorizontalResolution
= HorizontalResolution
;
1152 TempTiming
.VerticalResolution
= VerticalResolution
;
1153 TempTiming
.RefreshRate
= RefreshRate
;
1154 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
1161 ValidEdidTiming
->ValidNumber
= ValidNumber
;
1167 Search a specified Timing in all the valid EDID timings.
1169 @param ValidEdidTiming All valid EDID timing information.
1170 @param EdidTiming The Timing to search for.
1173 @retval FALSE Not found.
1178 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
,
1179 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
1185 Key
= CalculateEdidKey (EdidTiming
);
1187 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
1188 if (Key
== ValidEdidTiming
->Key
[Index
]) {
1198 Check for VBE device.
1200 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
1202 @retval EFI_SUCCESS VBE device found
1206 BiosVideoCheckForVbe (
1207 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1211 EFI_IA32_REGISTER_SET Regs
;
1212 UINT16
*ModeNumberPtr
;
1215 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1216 BIOS_VIDEO_MODE_DATA
*CurrentModeData
;
1219 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing
;
1220 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming
;
1221 EFI_EDID_OVERRIDE_PROTOCOL
*EdidOverride
;
1222 UINT32 EdidAttributes
;
1223 BOOLEAN EdidOverrideFound
;
1224 UINTN EdidOverrideDataSize
;
1225 UINT8
*EdidOverrideDataBlock
;
1226 UINTN EdidActiveDataSize
;
1227 UINT8
*EdidActiveDataBlock
;
1230 EdidOverrideFound
= FALSE
;
1231 EdidOverrideDataBlock
= NULL
;
1232 EdidActiveDataSize
= 0;
1233 EdidActiveDataBlock
= NULL
;
1236 // Allocate buffer under 1MB for VBE data structures
1238 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
1239 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) +
1240 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
1241 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
) +
1242 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
1245 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
1247 Status
= gBS
->AllocatePages (
1249 EfiBootServicesData
,
1250 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
1251 &BiosVideoPrivate
->PagesBelow1MB
1253 if (EFI_ERROR (Status
)) {
1257 ZeroMem (&ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
));
1260 // Fill in the VBE related data structures
1262 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
1263 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
1264 BiosVideoPrivate
->VbeEdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
1265 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeEdidDataBlock
+ 1);
1266 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
1267 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
1270 // Test to see if the Video Adapter is compliant with VBE 3.0
1272 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1273 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1274 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1275 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1276 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1277 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1279 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1281 Status
= EFI_DEVICE_ERROR
;
1284 // See if the VESA call succeeded
1286 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1290 // Check for 'VESA' signature
1292 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1296 // Check to see if this is VBE 2.0 or higher
1298 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1303 EdidAttributes
= 0xff;
1304 EdidOverrideDataSize
= 0;
1307 // Find EDID Override protocol firstly, this protocol is installed by platform if needed.
1309 Status
= gBS
->LocateProtocol (
1310 &gEfiEdidOverrideProtocolGuid
,
1312 (VOID
**) &EdidOverride
1314 if (!EFI_ERROR (Status
)) {
1316 // Allocate double size of VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE to avoid overflow
1318 EdidOverrideDataBlock
= AllocatePool (sizeof (VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
* 2));
1319 if (NULL
== EdidOverrideDataBlock
) {
1320 Status
= EFI_OUT_OF_RESOURCES
;
1324 Status
= EdidOverride
->GetEdid (
1326 BiosVideoPrivate
->Handle
,
1328 &EdidOverrideDataSize
,
1329 (UINT8
**) &EdidOverrideDataBlock
1331 if (!EFI_ERROR (Status
) &&
1332 EdidAttributes
== 0 &&
1333 EdidOverrideDataSize
!= 0) {
1335 // Succeeded to get EDID Override Data
1337 EdidOverrideFound
= TRUE
;
1341 if (!EdidOverrideFound
|| EdidAttributes
== EFI_EDID_OVERRIDE_DONT_OVERRIDE
) {
1343 // If EDID Override data doesn't exist or EFI_EDID_OVERRIDE_DONT_OVERRIDE returned,
1344 // read EDID information through INT10 call
1347 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1348 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1352 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1353 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1355 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1357 // See if the VESA call succeeded
1359 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1361 // Set EDID Discovered Data
1363 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1364 BiosVideoPrivate
->EdidDiscovered
.Edid
= (UINT8
*) AllocateCopyPool (
1365 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1366 BiosVideoPrivate
->VbeEdidDataBlock
1369 if (NULL
== BiosVideoPrivate
->EdidDiscovered
.Edid
) {
1370 Status
= EFI_OUT_OF_RESOURCES
;
1379 EdidActiveDataSize
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1380 EdidActiveDataBlock
= BiosVideoPrivate
->EdidDiscovered
.Edid
;
1381 } else if (EdidOverrideFound
) {
1382 EdidActiveDataSize
= EdidOverrideDataSize
;
1383 EdidActiveDataBlock
= EdidOverrideDataBlock
;
1389 // Parse EDID data structure to retrieve modes supported by monitor
1391 if (ParseEdidData ((UINT8
*) EdidActiveDataBlock
, &ValidEdidTiming
)) {
1393 // Copy EDID Override Data to EDID Active Data
1395 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= (UINT32
) EdidActiveDataSize
;
1396 BiosVideoPrivate
->EdidActive
.Edid
= (UINT8
*) AllocateCopyPool (
1400 if (NULL
== BiosVideoPrivate
->EdidActive
.Edid
) {
1401 Status
= EFI_OUT_OF_RESOURCES
;
1406 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1407 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1412 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1414 ModeNumberPtr
= (UINT16
*)
1416 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1417 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1423 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
1425 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1427 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1431 // Get the information about the mode
1433 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1434 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1435 Regs
.X
.CX
= *ModeNumberPtr
;
1436 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1437 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1438 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1440 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1443 // See if the call succeeded. If it didn't, then try the next mode.
1445 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1449 // See if the mode supports color. If it doesn't then try the next mode.
1451 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1455 // See if the mode supports graphics. If it doesn't then try the next mode.
1457 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1461 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1463 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1467 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1468 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1469 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1471 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1475 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1479 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1483 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1485 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1489 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1491 // EDID exist, check whether this mode match with any mode in EDID
1493 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1494 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1495 if (!SearchEdidTiming (&ValidEdidTiming
, &Timing
)) {
1501 // Select a reasonable mode to be set for current display mode
1505 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1506 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1510 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1511 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1514 PreferMode
= ModeNumber
;
1516 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1517 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1522 if ((!EdidFound
) && (!ModeFound
)) {
1524 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1530 // Add mode to the list of available modes
1533 ModeBuffer
= (BIOS_VIDEO_MODE_DATA
*) AllocatePool (
1534 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
)
1536 if (NULL
== ModeBuffer
) {
1537 Status
= EFI_OUT_OF_RESOURCES
;
1541 if (ModeNumber
> 1) {
1544 BiosVideoPrivate
->ModeData
,
1545 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1549 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1550 FreePool (BiosVideoPrivate
->ModeData
);
1553 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1554 CurrentModeData
->VbeModeNumber
= *ModeNumberPtr
;
1555 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1556 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1557 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1558 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1559 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1560 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1561 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1562 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1563 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1564 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1566 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1567 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1568 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1569 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1570 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1571 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1572 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1573 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1574 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1577 CurrentModeData
->PixelFormat
= PixelBitMask
;
1578 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1579 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1580 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1581 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1582 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1583 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1587 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1588 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1589 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1590 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1591 CurrentModeData
->FrameBufferSize
= BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024;
1593 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1594 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1595 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1597 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1599 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1602 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1604 if (ModeNumber
== 0) {
1605 Status
= EFI_DEVICE_ERROR
;
1610 // Assign Gop's Blt function
1612 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVbeBlt
;
1614 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= (UINT32
) ModeNumber
;
1616 // Current mode is unknow till now, set it to an invalid mode.
1618 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1621 // Find the best mode to initialize
1623 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1624 if (EFI_ERROR (Status
)) {
1625 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1626 Status
= BiosVideoGraphicsOutputSetMode (
1627 &BiosVideoPrivate
->GraphicsOutput
,
1630 if (!EFI_ERROR (Status
)) {
1634 if (PreferMode
== ModeNumber
) {
1636 // None mode is set successfully.
1644 // If there was an error, then free the mode structure
1646 if (EFI_ERROR (Status
)) {
1647 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1648 FreePool (BiosVideoPrivate
->ModeData
);
1649 BiosVideoPrivate
->ModeData
= NULL
;
1650 BiosVideoPrivate
->MaxMode
= 0;
1652 if (EdidOverrideDataBlock
!= NULL
) {
1653 FreePool (EdidOverrideDataBlock
);
1662 Check for VGA device.
1664 @param BiosVideoPrivate Pointer to BIOS_VIDEO_DEV structure
1666 @retval EFI_SUCCESS Standard VGA device found
1670 BiosVideoCheckForVga (
1671 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1675 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1677 Status
= EFI_UNSUPPORTED
;
1680 // Assign Gop's Blt function
1682 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1685 // Add mode to the list of available modes
1686 // caller should guarantee that Mode has been allocated.
1688 ASSERT (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
);
1689 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1691 ModeBuffer
= (BIOS_VIDEO_MODE_DATA
*) AllocatePool (
1692 sizeof (BIOS_VIDEO_MODE_DATA
)
1694 if (NULL
== ModeBuffer
) {
1695 Status
= EFI_OUT_OF_RESOURCES
;
1699 ModeBuffer
->VbeModeNumber
= 0x0012;
1700 ModeBuffer
->BytesPerScanLine
= 640;
1701 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1702 ModeBuffer
->HorizontalResolution
= 640;
1703 ModeBuffer
->VerticalResolution
= 480;
1704 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1705 ModeBuffer
->BitsPerPixel
= 8;
1706 ModeBuffer
->ColorDepth
= 32;
1707 ModeBuffer
->RefreshRate
= 60;
1709 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1712 // Test to see if the Video Adapter support the 640x480 16 color mode
1714 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1715 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1719 // If there was an error, then free the mode structure
1721 if (EFI_ERROR (Status
)) {
1722 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1723 FreePool (BiosVideoPrivate
->ModeData
);
1724 BiosVideoPrivate
->ModeData
= NULL
;
1726 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1727 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1728 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1729 BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
= NULL
;
1731 FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1732 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1739 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1743 Graphics Output protocol interface to get video mode.
1745 @param This Protocol instance pointer.
1746 @param ModeNumber The mode number to return information on.
1747 @param SizeOfInfo A pointer to the size, in bytes, of the Info
1749 @param Info Caller allocated buffer that returns information
1752 @retval EFI_SUCCESS Mode information returned.
1753 @retval EFI_DEVICE_ERROR A hardware error occurred trying to retrieve the
1755 @retval EFI_NOT_STARTED Video display is not initialized. Call SetMode ()
1756 @retval EFI_INVALID_PARAMETER One of the input args was NULL.
1761 BiosVideoGraphicsOutputQueryMode (
1762 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1763 IN UINT32 ModeNumber
,
1764 OUT UINTN
*SizeOfInfo
,
1765 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1768 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1769 BIOS_VIDEO_MODE_DATA
*ModeData
;
1771 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1773 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1774 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1775 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1776 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_OUTPUT_ERROR
,
1777 BiosVideoPrivate
->GopDevicePath
1779 return EFI_NOT_STARTED
;
1782 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1783 return EFI_INVALID_PARAMETER
;
1786 *Info
= (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
*) AllocatePool (
1787 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
)
1789 if (NULL
== *Info
) {
1790 return EFI_OUT_OF_RESOURCES
;
1793 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1795 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1796 (*Info
)->Version
= 0;
1797 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1798 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1799 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1800 CopyMem (&((*Info
)->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof(ModeData
->PixelBitMask
));
1802 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1808 Worker function to set video mode.
1810 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV.
1811 @param ModeData The mode data to be set.
1812 @param DevicePath Pointer to Device Path Protocol.
1814 @retval EFI_SUCCESS Graphics mode was changed.
1815 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1817 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1821 BiosVideoSetModeWorker (
1822 IN BIOS_VIDEO_DEV
*BiosVideoPrivate
,
1823 IN BIOS_VIDEO_MODE_DATA
*ModeData
,
1824 IN EFI_DEVICE_PATH_PROTOCOL
*DevicePath
1828 EFI_IA32_REGISTER_SET Regs
;
1830 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
1831 FreePool (BiosVideoPrivate
->LineBuffer
);
1834 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
1835 FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1838 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
1839 FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1842 BiosVideoPrivate
->LineBuffer
= (UINT8
*) AllocatePool (
1843 ModeData
->BytesPerScanLine
1845 if (NULL
== BiosVideoPrivate
->LineBuffer
) {
1846 return EFI_OUT_OF_RESOURCES
;
1849 // Clear all registers
1851 ZeroMem (&Regs
, sizeof (Regs
));
1853 if (ModeData
->VbeModeNumber
< 0x100) {
1855 // Allocate a working buffer for BLT operations to the VGA frame buffer
1857 BiosVideoPrivate
->VgaFrameBuffer
= (UINT8
*) AllocatePool (4 * 480 * 80);
1858 if (NULL
== BiosVideoPrivate
->VgaFrameBuffer
) {
1859 return EFI_OUT_OF_RESOURCES
;
1864 Regs
.X
.AX
= ModeData
->VbeModeNumber
;
1865 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1869 // Allocate a working buffer for BLT operations to the VBE frame buffer
1871 BiosVideoPrivate
->VbeFrameBuffer
=
1872 (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) AllocatePool (
1873 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
1875 if (NULL
== BiosVideoPrivate
->VbeFrameBuffer
) {
1876 return EFI_OUT_OF_RESOURCES
;
1881 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1882 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1883 ZeroMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
));
1884 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1885 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1886 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
1889 // Check to see if the call succeeded
1891 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1892 REPORT_STATUS_CODE_WITH_DEVICE_PATH (
1893 EFI_ERROR_CODE
| EFI_ERROR_MINOR
,
1894 EFI_PERIPHERAL_LOCAL_CONSOLE
| EFI_P_EC_OUTPUT_ERROR
,
1897 return EFI_DEVICE_ERROR
;
1900 // Initialize the state of the VbeFrameBuffer
1902 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1903 BiosVideoPrivate
->PciIo
,
1904 EfiPciIoWidthUint32
,
1905 EFI_PCI_IO_PASS_THROUGH_BAR
,
1906 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
1907 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
1908 BiosVideoPrivate
->VbeFrameBuffer
1910 if (EFI_ERROR (Status
)) {
1919 Graphics Output protocol interface to set video mode.
1921 @param This Protocol instance pointer.
1922 @param ModeNumber The mode number to be set.
1924 @retval EFI_SUCCESS Graphics mode was changed.
1925 @retval EFI_DEVICE_ERROR The device had an error and could not complete the
1927 @retval EFI_UNSUPPORTED ModeNumber is not supported by this device.
1932 BiosVideoGraphicsOutputSetMode (
1933 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1934 IN UINT32 ModeNumber
1938 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1939 BIOS_VIDEO_MODE_DATA
*ModeData
;
1940 EFI_GRAPHICS_OUTPUT_BLT_PIXEL Background
;
1943 return EFI_INVALID_PARAMETER
;
1946 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1948 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1950 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1951 return EFI_UNSUPPORTED
;
1954 if (ModeNumber
== This
->Mode
->Mode
) {
1956 // Clear screen to black
1958 ZeroMem (&Background
, sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1959 BiosVideoGraphicsOutputVbeBlt (
1967 ModeData
->HorizontalResolution
,
1968 ModeData
->VerticalResolution
,
1974 Status
= BiosVideoSetModeWorker (BiosVideoPrivate
, ModeData
, BiosVideoPrivate
->GopDevicePath
);
1975 if (EFI_ERROR (Status
)) {
1979 This
->Mode
->Mode
= ModeNumber
;
1980 This
->Mode
->Info
->Version
= 0;
1981 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
1982 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
1983 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
1984 CopyMem (&(This
->Mode
->Info
->PixelInformation
), &(ModeData
->PixelBitMask
), sizeof (ModeData
->PixelBitMask
));
1985 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1986 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1989 // Frame BufferSize remain unchanged
1991 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) (UINTN
) ModeData
->LinearFrameBuffer
;
1992 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
1994 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
2000 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
2002 @param PciIo The pointer of EFI_PCI_IO_PROTOCOL
2003 @param VbeBuffer The data to transfer to screen
2004 @param MemAddress Physical frame buffer base address
2005 @param DestinationX The X coordinate of the destination for BltOperation
2006 @param DestinationY The Y coordinate of the destination for BltOperation
2007 @param TotalBytes The total bytes of copy
2008 @param VbePixelWidth Bytes per pixel
2009 @param BytesPerScanLine Bytes per scan line
2014 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2015 IN UINT8
*VbeBuffer
,
2016 IN VOID
*MemAddress
,
2017 IN UINTN DestinationX
,
2018 IN UINTN DestinationY
,
2019 IN UINTN TotalBytes
,
2020 IN UINT32 VbePixelWidth
,
2021 IN UINTN BytesPerScanLine
2024 UINTN FrameBufferAddr
;
2026 UINTN RemainingBytes
;
2027 UINTN UnalignedBytes
;
2030 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
2033 // If TotalBytes is less than 4 bytes, only start byte copy.
2035 if (TotalBytes
< 4) {
2036 Status
= PciIo
->Mem
.Write (
2039 EFI_PCI_IO_PASS_THROUGH_BAR
,
2040 (UINT64
) FrameBufferAddr
,
2044 ASSERT_EFI_ERROR (Status
);
2049 // If VbeBuffer is not 4-byte aligned, start byte copy.
2051 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
2053 if (UnalignedBytes
!= 0) {
2054 Status
= PciIo
->Mem
.Write (
2057 EFI_PCI_IO_PASS_THROUGH_BAR
,
2058 (UINT64
) FrameBufferAddr
,
2062 ASSERT_EFI_ERROR (Status
);
2063 FrameBufferAddr
+= UnalignedBytes
;
2064 VbeBuffer
+= UnalignedBytes
;
2068 // Calculate 4-byte block count and remaining bytes.
2070 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
2071 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
2074 // Copy 4-byte block and remaining bytes to physical frame buffer.
2076 if (CopyBlockNum
!= 0) {
2077 Status
= PciIo
->Mem
.Write (
2079 EfiPciIoWidthUint32
,
2080 EFI_PCI_IO_PASS_THROUGH_BAR
,
2081 (UINT64
) FrameBufferAddr
,
2085 ASSERT_EFI_ERROR (Status
);
2088 if (RemainingBytes
!= 0) {
2089 FrameBufferAddr
+= (CopyBlockNum
<< 2);
2090 VbeBuffer
+= (CopyBlockNum
<< 2);
2091 Status
= PciIo
->Mem
.Write (
2094 EFI_PCI_IO_PASS_THROUGH_BAR
,
2095 (UINT64
) FrameBufferAddr
,
2099 ASSERT_EFI_ERROR (Status
);
2104 Worker function to block transfer for VBE device.
2106 @param BiosVideoPrivate Instance of BIOS_VIDEO_DEV
2107 @param BltBuffer The data to transfer to screen
2108 @param BltOperation The operation to perform
2109 @param SourceX The X coordinate of the source for BltOperation
2110 @param SourceY The Y coordinate of the source for BltOperation
2111 @param DestinationX The X coordinate of the destination for
2113 @param DestinationY The Y coordinate of the destination for
2115 @param Width The width of a rectangle in the blt rectangle in
2117 @param Height The height of a rectangle in the blt rectangle in
2119 @param Delta Not used for EfiBltVideoFill and
2120 EfiBltVideoToVideo operation. If a Delta of 0 is
2121 used, the entire BltBuffer will be operated on. If
2122 a subrectangle of the BltBuffer is used, then
2123 Delta represents the number of bytes in a row of
2125 @param Mode Mode data.
2127 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2128 @retval EFI_SUCCESS Blt operation success
2132 BiosVideoVbeBltWorker (
2133 IN BIOS_VIDEO_DEV
*BiosVideoPrivate
,
2134 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2135 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2138 IN UINTN DestinationX
,
2139 IN UINTN DestinationY
,
2143 IN BIOS_VIDEO_MODE_DATA
*Mode
2146 EFI_PCI_IO_PROTOCOL
*PciIo
;
2147 EFI_TPL OriginalTPL
;
2151 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
2153 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
2154 UINTN BytesPerScanLine
;
2159 UINT32 VbePixelWidth
;
2163 PciIo
= BiosVideoPrivate
->PciIo
;
2165 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
2166 MemAddress
= Mode
->LinearFrameBuffer
;
2167 BytesPerScanLine
= Mode
->BytesPerScanLine
;
2168 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
2169 BltUint8
= (UINT8
*) BltBuffer
;
2170 TotalBytes
= Width
* VbePixelWidth
;
2172 if (((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2173 return EFI_INVALID_PARAMETER
;
2176 if (Width
== 0 || Height
== 0) {
2177 return EFI_INVALID_PARAMETER
;
2180 // We need to fill the Virtual Screen buffer with the blt data.
2181 // The virtual screen is upside down, as the first row is the bootom row of
2184 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2186 // Video to BltBuffer: Source is Video, destination is BltBuffer
2188 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
2189 return EFI_INVALID_PARAMETER
;
2192 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
2193 return EFI_INVALID_PARAMETER
;
2197 // BltBuffer to Video: Source is BltBuffer, destination is Video
2199 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
2200 return EFI_INVALID_PARAMETER
;
2203 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
2204 return EFI_INVALID_PARAMETER
;
2208 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2209 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2210 // the number of bytes in each row can be computed.
2213 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2216 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2217 // We would not want a timer based event (Cursor, ...) to come in while we are
2218 // doing this operation.
2220 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2222 switch (BltOperation
) {
2223 case EfiBltVideoToBltBuffer
:
2224 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
2225 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2227 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
2229 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
2230 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2231 Pixel
= VbeBuffer
[0] | VbeBuffer
[1] << 8 | VbeBuffer
[2] << 16 | VbeBuffer
[3] << 24;
2232 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
2233 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
2234 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
2237 VbeBuffer
+= VbePixelWidth
;
2243 case EfiBltVideoToVideo
:
2244 for (Index
= 0; Index
< Height
; Index
++) {
2245 if (DestinationY
<= SourceY
) {
2246 SrcY
= SourceY
+ Index
;
2247 DstY
= DestinationY
+ Index
;
2249 SrcY
= SourceY
+ Height
- Index
- 1;
2250 DstY
= DestinationY
+ Height
- Index
- 1;
2253 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2254 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2263 // Update physical frame buffer.
2278 case EfiBltVideoFill
:
2279 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2280 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2282 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2284 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2286 (Blt
->Green
& Mode
->Green
.Mask
) <<
2287 Mode
->Green
.Position
2289 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2291 for (Index
= 0; Index
< Width
; Index
++) {
2297 VbeBuffer
+= VbePixelWidth
;
2300 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2301 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2303 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2309 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2311 // Update physical frame buffer.
2326 case EfiBltBufferToVideo
:
2327 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2328 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2329 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2330 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2332 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2334 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2335 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2336 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2343 VbeBuffer
+= VbePixelWidth
;
2346 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2349 // Update physical frame buffer.
2367 gBS
->RestoreTPL (OriginalTPL
);
2373 Graphics Output protocol instance to block transfer for VBE device.
2375 @param This Pointer to Graphics Output protocol instance
2376 @param BltBuffer The data to transfer to screen
2377 @param BltOperation The operation to perform
2378 @param SourceX The X coordinate of the source for BltOperation
2379 @param SourceY The Y coordinate of the source for BltOperation
2380 @param DestinationX The X coordinate of the destination for
2382 @param DestinationY The Y coordinate of the destination for
2384 @param Width The width of a rectangle in the blt rectangle in
2386 @param Height The height of a rectangle in the blt rectangle in
2388 @param Delta Not used for EfiBltVideoFill and
2389 EfiBltVideoToVideo operation. If a Delta of 0 is
2390 used, the entire BltBuffer will be operated on. If
2391 a subrectangle of the BltBuffer is used, then
2392 Delta represents the number of bytes in a row of
2395 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2396 @retval EFI_SUCCESS Blt operation success
2401 BiosVideoGraphicsOutputVbeBlt (
2402 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2403 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2404 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2407 IN UINTN DestinationX
,
2408 IN UINTN DestinationY
,
2414 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2415 BIOS_VIDEO_MODE_DATA
*Mode
;
2418 return EFI_INVALID_PARAMETER
;
2421 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2422 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
2424 return BiosVideoVbeBltWorker (
2440 Write graphics controller registers.
2442 @param PciIo Pointer to PciIo protocol instance of the
2444 @param Address Register address
2445 @param Data Data to be written to register
2451 WriteGraphicsController (
2452 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2457 Address
= Address
| (Data
<< 8);
2460 EfiPciIoWidthUint16
,
2461 EFI_PCI_IO_PASS_THROUGH_BAR
,
2462 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2470 Read the four bit plane of VGA frame buffer.
2472 @param PciIo Pointer to PciIo protocol instance of the
2474 @param HardwareBuffer Hardware VGA frame buffer address
2475 @param MemoryBuffer Memory buffer address
2476 @param WidthInBytes Number of bytes in a line to read
2477 @param Height Height of the area to read
2484 EFI_PCI_IO_PROTOCOL
*PciIo
,
2485 UINT8
*HardwareBuffer
,
2486 UINT8
*MemoryBuffer
,
2493 UINTN FrameBufferOffset
;
2498 // Program the Mode Register Write mode 0, Read mode 0
2500 WriteGraphicsController (
2502 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2503 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2506 for (BitPlane
= 0, FrameBufferOffset
= 0;
2507 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2508 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2511 // Program the Read Map Select Register to select the correct bit plane
2513 WriteGraphicsController (
2515 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2519 Source
= HardwareBuffer
;
2520 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2522 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2526 EFI_PCI_IO_PASS_THROUGH_BAR
,
2527 (UINT64
) (UINTN
) Source
,
2529 (VOID
*) Destination
2537 Internal routine to convert VGA color to Grahpics Output color.
2539 @param MemoryBuffer Buffer containing VGA color
2540 @param CoordinateX The X coordinate of pixel on screen
2541 @param CoordinateY The Y coordinate of pixel on screen
2542 @param BltBuffer Buffer to contain converted Grahpics Output color
2548 VgaConvertToGraphicsOutputColor (
2549 UINT8
*MemoryBuffer
,
2552 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2559 MemoryBuffer
+= ((CoordinateY
<< 6) + (CoordinateY
<< 4) + (CoordinateX
>> 3));
2560 Mask
= mVgaBitMaskTable
[CoordinateX
& 0x07];
2561 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2562 if ((*MemoryBuffer
& Mask
) != 0) {
2567 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2571 Internal routine to convert Grahpics Output color to VGA color.
2573 @param BltBuffer buffer containing Grahpics Output color
2575 @return Converted VGA color
2580 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2585 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2586 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2595 Grahpics Output protocol instance to block transfer for VGA device.
2597 @param This Pointer to Grahpics Output protocol instance
2598 @param BltBuffer The data to transfer to screen
2599 @param BltOperation The operation to perform
2600 @param SourceX The X coordinate of the source for BltOperation
2601 @param SourceY The Y coordinate of the source for BltOperation
2602 @param DestinationX The X coordinate of the destination for
2604 @param DestinationY The Y coordinate of the destination for
2606 @param Width The width of a rectangle in the blt rectangle in
2608 @param Height The height of a rectangle in the blt rectangle in
2610 @param Delta Not used for EfiBltVideoFill and
2611 EfiBltVideoToVideo operation. If a Delta of 0 is
2612 used, the entire BltBuffer will be operated on. If
2613 a subrectangle of the BltBuffer is used, then
2614 Delta represents the number of bytes in a row of
2617 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2618 @retval EFI_SUCCESS Blt operation success
2623 BiosVideoGraphicsOutputVgaBlt (
2624 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2625 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2626 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2629 IN UINTN DestinationX
,
2630 IN UINTN DestinationY
,
2636 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2637 EFI_TPL OriginalTPL
;
2639 UINTN BytesPerScanLine
;
2651 UINT8
*SourceAddress
;
2652 UINT8
*DestinationAddress
;
2653 EFI_PCI_IO_PROTOCOL
*PciIo
;
2656 UINT8
*VgaFrameBuffer
;
2665 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2666 return EFI_INVALID_PARAMETER
;
2669 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2671 CurrentMode
= This
->Mode
->Mode
;
2672 PciIo
= BiosVideoPrivate
->PciIo
;
2673 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2674 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2675 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2678 if (Width
== 0 || Height
== 0) {
2679 return EFI_INVALID_PARAMETER
;
2682 // We need to fill the Virtual Screen buffer with the blt data.
2683 // The virtual screen is upside down, as the first row is the bootom row of
2686 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2688 // Video to BltBuffer: Source is Video, destination is BltBuffer
2690 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2691 return EFI_INVALID_PARAMETER
;
2694 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2695 return EFI_INVALID_PARAMETER
;
2699 // BltBuffer to Video: Source is BltBuffer, destination is Video
2701 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2702 return EFI_INVALID_PARAMETER
;
2705 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2706 return EFI_INVALID_PARAMETER
;
2710 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2711 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2712 // the number of bytes in each row can be computed.
2715 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2718 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2719 // We would not want a timer based event (Cursor, ...) to come in while we are
2720 // doing this operation.
2722 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2725 // Compute some values we need for VGA
2727 switch (BltOperation
) {
2728 case EfiBltVideoToBltBuffer
:
2730 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2731 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2734 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2738 MemAddress
+ SourceOffset
,
2739 VgaFrameBuffer
+ SourceOffset
,
2745 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2747 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2748 for (Rows
= 0, CoordinateY
= SourceY
; Rows
< Height
; Rows
++, CoordinateY
++, BltBuffer
+= (Delta
>> 2)) {
2749 for (Columns
= 0, CoordinateX
= SourceX
; Columns
< Width
; Columns
++, CoordinateX
++, BltBuffer
++) {
2750 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, CoordinateX
, CoordinateY
, BltBuffer
);
2758 case EfiBltVideoToVideo
:
2760 // Check for an aligned Video to Video operation
2762 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2764 // Program the Mode Register Write mode 1, Read mode 0
2766 WriteGraphicsController (
2768 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2769 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2772 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2773 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2775 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2779 EFI_PCI_IO_PASS_THROUGH_BAR
,
2780 (UINT64
) (UINTN
) (DestinationAddress
+ Offset
),
2781 EFI_PCI_IO_PASS_THROUGH_BAR
,
2782 (UINT64
) (UINTN
) (SourceAddress
+ Offset
),
2787 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2788 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2791 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2795 MemAddress
+ SourceOffset
,
2796 VgaFrameBuffer
+ SourceOffset
,
2804 case EfiBltVideoFill
:
2805 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2806 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2807 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2808 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2810 LeftMask
= (UINT8
) (LeftMask
& RightMask
);
2814 if (LeftMask
== 0xff) {
2820 if (RightMask
== 0xff) {
2825 PixelColor
= VgaConvertColor (BltBuffer
);
2828 // Program the Mode Register Write mode 2, Read mode 0
2830 WriteGraphicsController (
2832 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2833 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2837 // Program the Data Rotate/Function Select Register to replace
2839 WriteGraphicsController (
2841 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2842 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2845 if (LeftMask
!= 0) {
2847 // Program the BitMask register with the Left column mask
2849 WriteGraphicsController (
2851 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2855 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2857 // Read data from the bit planes into the latches
2862 EFI_PCI_IO_PASS_THROUGH_BAR
,
2863 (UINT64
) (UINTN
) Address
,
2868 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2873 EFI_PCI_IO_PASS_THROUGH_BAR
,
2874 (UINT64
) (UINTN
) Address
,
2883 // Program the BitMask register with the middle column mask of 0xff
2885 WriteGraphicsController (
2887 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2891 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2894 EfiPciIoWidthFillUint8
,
2895 EFI_PCI_IO_PASS_THROUGH_BAR
,
2896 (UINT64
) (UINTN
) Address
,
2903 if (RightMask
!= 0) {
2905 // Program the BitMask register with the Right column mask
2907 WriteGraphicsController (
2909 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2913 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2915 // Read data from the bit planes into the latches
2920 EFI_PCI_IO_PASS_THROUGH_BAR
,
2921 (UINT64
) (UINTN
) Address
,
2926 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2931 EFI_PCI_IO_PASS_THROUGH_BAR
,
2932 (UINT64
) (UINTN
) Address
,
2940 case EfiBltBufferToVideo
:
2941 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2942 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2945 // Program the Mode Register Write mode 2, Read mode 0
2947 WriteGraphicsController (
2949 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2950 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2954 // Program the Data Rotate/Function Select Register to replace
2956 WriteGraphicsController (
2958 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2959 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2962 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2963 for (Index1
= 0; Index1
< Width
; Index1
++) {
2964 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2966 AddressFix
= Address
;
2968 for (Bit
= 0; Bit
< 8; Bit
++) {
2970 // Program the BitMask register with the Left column mask
2972 WriteGraphicsController (
2974 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2978 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2980 // Read data from the bit planes into the latches
2985 EFI_PCI_IO_PASS_THROUGH_BAR
,
2986 (UINT64
) (UINTN
) Address1
,
2994 EFI_PCI_IO_PASS_THROUGH_BAR
,
2995 (UINT64
) (UINTN
) Address1
,
2997 &BiosVideoPrivate
->LineBuffer
[Index1
]
3001 LeftMask
= (UINT8
) (LeftMask
>> 1);
3002 if (LeftMask
== 0) {
3014 gBS
->RestoreTPL (OriginalTPL
);
3020 // VGA Mini Port Protocol Functions
3024 VgaMiniPort protocol interface to set mode.
3026 @param This Pointer to VgaMiniPort protocol instance
3027 @param ModeNumber The index of the mode
3029 @retval EFI_UNSUPPORTED The requested mode is not supported
3030 @retval EFI_SUCCESS The requested mode is set successfully
3035 BiosVideoVgaMiniPortSetMode (
3036 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
3040 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
3041 EFI_IA32_REGISTER_SET Regs
;
3044 return EFI_INVALID_PARAMETER
;
3048 // Make sure the ModeNumber is a valid value
3050 if (ModeNumber
>= This
->MaxMode
) {
3051 return EFI_UNSUPPORTED
;
3054 // Get the device structure for this device
3056 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
3058 switch (ModeNumber
) {
3061 // Set the 80x25 Text VGA Mode
3065 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3070 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3075 // Set the 80x50 Text VGA Mode
3079 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3083 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3087 return EFI_UNSUPPORTED
;
3094 Event handler for Exit Boot Service.
3096 @param Event The event that be siganlled when exiting boot service.
3097 @param Context Pointer to instance of BIOS_VIDEO_DEV.
3102 BiosVideoNotifyExitBootServices (
3107 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
3108 EFI_IA32_REGISTER_SET Regs
;
3110 BiosVideoPrivate
= (BIOS_VIDEO_DEV
*)Context
;
3113 // Set the 80x25 Text VGA Mode
3117 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3121 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3126 BiosVideoPrivate
->LegacyBios
->Int86 (BiosVideoPrivate
->LegacyBios
, 0x10, &Regs
);
3130 The user Entry Point for module UefiBiosVideo. The user code starts with this function.
3132 @param[in] ImageHandle The firmware allocated handle for the EFI image.
3133 @param[in] SystemTable A pointer to the EFI System Table.
3135 @retval EFI_SUCCESS The entry point is executed successfully.
3136 @retval other Some error occurs when executing this entry point.
3141 BiosVideoEntryPoint(
3142 IN EFI_HANDLE ImageHandle
,
3143 IN EFI_SYSTEM_TABLE
*SystemTable
3149 // Install driver model protocol(s).
3151 Status
= EfiLibInstallDriverBindingComponentName2 (
3154 &gBiosVideoDriverBinding
,
3156 &gBiosVideoComponentName
,
3157 &gBiosVideoComponentName2
3159 ASSERT_EFI_ERROR (Status
);
3162 // Install Legacy BIOS GUID to mark this driver as a BIOS Thunk Driver
3164 return gBS
->InstallMultipleProtocolInterfaces (
3166 &gEfiLegacyBiosGuid
,