3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 ConsoleOut Routines that speak VGA.
24 #include "BiosVideo.h"
27 // EFI Driver Binding Protocol Instance
29 EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding
= {
30 BiosVideoDriverBindingSupported
,
31 BiosVideoDriverBindingStart
,
32 BiosVideoDriverBindingStop
,
39 // Global lookup tables for VGA graphics modes
41 UINT8 mVgaLeftMaskTable
[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
43 UINT8 mVgaRightMaskTable
[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
45 UINT8 mVgaBitMaskTable
[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
47 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor
[] = {
147 // Standard timing defined by VESA EDID
149 VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming
[] = {
151 // Established Timing I
162 // Established Timing II
173 // Established Timing III
179 BiosVideoChildHandleInstall (
180 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
181 IN EFI_HANDLE ParentHandle
,
182 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
183 IN EFI_LEGACY_8259_PROTOCOL
*ParentLegacy8259
,
184 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
185 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
190 BiosVideoChildHandleUninstall (
191 EFI_DRIVER_BINDING_PROTOCOL
*This
,
192 EFI_HANDLE Controller
,
198 BiosVideoDeviceReleaseResource (
199 BIOS_VIDEO_DEV
*BiosVideoPrivate
205 BiosVideoDriverEntryPoint (
206 IN EFI_HANDLE ImageHandle
,
207 IN EFI_SYSTEM_TABLE
*SystemTable
217 ImageHandle - Handle of driver image.
218 SystemTable - Pointer to system table.
228 Status
= EfiLibInstallDriverBindingComponentName2 (
231 &gBiosVideoDriverBinding
,
233 &gBiosVideoComponentName
,
234 &gBiosVideoComponentName2
242 BiosVideoExitBootServices (
250 Callback function for exit boot service event
254 Event - EFI_EVENT structure
255 Context - Event context
264 BIOS_VIDEO_DEV *BiosVideoPrivate;
265 EFI_IA32_REGISTER_SET Regs;
270 BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context;
273 // Set the 80x25 Text VGA Mode
277 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
282 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
288 BiosVideoDriverBindingSupported (
289 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
290 IN EFI_HANDLE Controller
,
291 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
301 This - Pointer to driver binding protocol
302 Controller - Controller handle to connect
303 RemainingDevicePath - A pointer to the remaining portion of a device path
308 EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,
309 Otherwise, this controller cannot be managed by this driver
314 EFI_LEGACY_8259_PROTOCOL
*LegacyBios
;
315 EFI_PCI_IO_PROTOCOL
*PciIo
;
318 // See if the Legacy 8259 Protocol is available
320 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
321 if (EFI_ERROR (Status
)) {
326 // Open the IO Abstraction(s) needed to perform the supported test
328 Status
= gBS
->OpenProtocol (
330 &gEfiPciIoProtocolGuid
,
332 This
->DriverBindingHandle
,
334 EFI_OPEN_PROTOCOL_BY_DRIVER
336 if (EFI_ERROR (Status
)) {
340 if (!BiosVideoIsVga (PciIo
)) {
341 Status
= EFI_UNSUPPORTED
;
346 &gEfiPciIoProtocolGuid
,
347 This
->DriverBindingHandle
,
356 BiosVideoDriverBindingStart (
357 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
358 IN EFI_HANDLE Controller
,
359 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
365 Install Graphics Output Protocol onto VGA device handles
369 This - Pointer to driver binding protocol
370 Controller - Controller handle to connect
371 RemainingDevicePath - A pointer to the remaining portion of a device path
380 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
381 EFI_PCI_IO_PROTOCOL
*PciIo
;
382 EFI_LEGACY_8259_PROTOCOL
*Legacy8259
;
386 // Prepare for status code
388 Status
= gBS
->HandleProtocol (
390 &gEfiDevicePathProtocolGuid
,
391 (VOID
**) &ParentDevicePath
393 if (EFI_ERROR (Status
)) {
398 // Open the IO Abstraction(s) needed
400 Status
= gBS
->OpenProtocol (
402 &gEfiPciIoProtocolGuid
,
404 This
->DriverBindingHandle
,
406 EFI_OPEN_PROTOCOL_BY_DRIVER
408 if (EFI_ERROR (Status
)) {
413 // See if the Legacy BIOS Protocol is available
415 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &Legacy8259
);
416 if (EFI_ERROR (Status
)) {
422 // Create child handle and install GraphicsOutputProtocol on it
424 Status
= BiosVideoChildHandleInstall (
434 if (EFI_ERROR (Status
)) {
437 // Release PCI I/O Protocols on the controller handle.
441 &gEfiPciIoProtocolGuid
,
442 This
->DriverBindingHandle
,
453 BiosVideoDriverBindingStop (
454 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
455 IN EFI_HANDLE Controller
,
456 IN UINTN NumberOfChildren
,
457 IN EFI_HANDLE
*ChildHandleBuffer
467 This - Pointer to driver binding protocol
468 Controller - Controller handle to connect
469 NumberOfChilren - Number of children handle created by this driver
470 ChildHandleBuffer - Buffer containing child handle created
474 EFI_SUCCESS - Driver disconnected successfully from controller
475 EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure
480 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
481 BOOLEAN AllChildrenStopped
;
484 BiosVideoPrivate
= NULL
;
486 if (NumberOfChildren
== 0) {
488 // Close PCI I/O protocol on the controller handle
492 &gEfiPciIoProtocolGuid
,
493 This
->DriverBindingHandle
,
500 AllChildrenStopped
= TRUE
;
501 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
502 Status
= BiosVideoChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
504 if (EFI_ERROR (Status
)) {
505 AllChildrenStopped
= FALSE
;
509 if (!AllChildrenStopped
) {
510 return EFI_DEVICE_ERROR
;
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_8259_PROTOCOL
*ParentLegacy8259
,
522 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
523 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
528 Install child handles if the Handle supports MBR format.
531 This - Calling context.
532 Handle - Parent Handle
533 PciIo - Parent PciIo interface
534 LegacyBios - Parent LegacyBios interface
535 DevicePath - Parent Device Path
538 EFI_SUCCESS - If a child handle was added
539 other - A child handle was not added
544 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
545 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
548 // Allocate the private device structure for video device
550 Status
= gBS
->AllocatePool (
552 sizeof (BIOS_VIDEO_DEV
),
555 if (EFI_ERROR (Status
)) {
559 ZeroMem (BiosVideoPrivate
, sizeof (BIOS_VIDEO_DEV
));
561 if (!BiosVideoIsVga (ParentPciIo
)) {
562 Status
= EFI_UNSUPPORTED
;
566 BiosVideoPrivate
->VgaCompatible
= TRUE
;
569 // Initialize the child private structure
571 BiosVideoPrivate
->Signature
= BIOS_VIDEO_DEV_SIGNATURE
;
572 BiosVideoPrivate
->Handle
= NULL
;
575 Status = gBS->CreateEvent (
576 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
578 BiosVideoExitBootServices,
580 &BiosVideoPrivate->ExitBootServicesEvent
582 if (EFI_ERROR (Status)) {
588 // Fill in Graphics Output specific mode structures
590 BiosVideoPrivate
->HardwareNeedsStarting
= TRUE
;
591 BiosVideoPrivate
->ModeData
= NULL
;
592 BiosVideoPrivate
->LineBuffer
= NULL
;
593 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
594 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
597 // Fill in the VGA Mini Port Protocol fields
599 BiosVideoPrivate
->VgaMiniPort
.SetMode
= BiosVideoVgaMiniPortSetMode
;
600 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryOffset
= 0xb8000;
601 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterOffset
= 0x3d4;
602 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterOffset
= 0x3d5;
603 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
604 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
605 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
608 // Assume that Graphics Output Protocol will be produced until proven otherwise
610 BiosVideoPrivate
->ProduceGraphicsOutput
= TRUE
;
613 // Child handle need to consume the Legacy Bios protocol
615 BiosVideoPrivate
->Legacy8259
= ParentLegacy8259
;
618 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
620 BiosVideoPrivate
->PciIo
= ParentPciIo
;
622 InitializeBiosIntCaller(BiosVideoPrivate
);
623 InitializeInterruptRedirection(BiosVideoPrivate
);
626 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
628 Status
= BiosVideoCheckForVbe (BiosVideoPrivate
);
629 if (EFI_ERROR (Status
)) {
631 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
632 // for the standard 640x480 16 color VGA mode
634 if (BiosVideoPrivate
->VgaCompatible
) {
635 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
638 if (EFI_ERROR (Status
)) {
640 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
641 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
643 BiosVideoPrivate
->ProduceGraphicsOutput
= FALSE
;
646 // INT services are available, so on the 80x25 and 80x50 text mode are supported
648 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
652 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
653 if (RemainingDevicePath
== NULL
) {
654 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
655 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
656 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
657 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
658 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
660 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (
662 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
665 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
669 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
671 Status
= gBS
->InstallMultipleProtocolInterfaces (
672 &BiosVideoPrivate
->Handle
,
673 &gEfiDevicePathProtocolGuid
,
674 BiosVideoPrivate
->DevicePath
,
675 &gEfiGraphicsOutputProtocolGuid
,
676 &BiosVideoPrivate
->GraphicsOutput
,
677 &gEfiEdidDiscoveredProtocolGuid
,
678 &BiosVideoPrivate
->EdidDiscovered
,
679 &gEfiEdidActiveProtocolGuid
,
680 &BiosVideoPrivate
->EdidActive
,
684 if (!EFI_ERROR (Status
)) {
686 // Open the Parent Handle for the child
688 Status
= gBS
->OpenProtocol (
690 &gEfiPciIoProtocolGuid
,
691 (VOID
**) &BiosVideoPrivate
->PciIo
,
692 This
->DriverBindingHandle
,
693 BiosVideoPrivate
->Handle
,
694 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
696 if (EFI_ERROR (Status
)) {
702 // Install VGA Mini Port Protocol
704 Status
= gBS
->InstallMultipleProtocolInterfaces (
705 &BiosVideoPrivate
->Handle
,
706 &gEfiVgaMiniPortProtocolGuid
,
707 &BiosVideoPrivate
->VgaMiniPort
,
713 if (EFI_ERROR (Status
)) {
715 // Free private data structure
717 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
724 BiosVideoChildHandleUninstall (
725 EFI_DRIVER_BINDING_PROTOCOL
*This
,
726 EFI_HANDLE Controller
,
733 Deregister an video child handle and free resources
737 This - Protocol instance pointer.
738 Controller - Video controller handle
739 Handle - Video child handle
748 EFI_IA32_REGISTER_SET Regs
;
749 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
750 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
751 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
752 EFI_PCI_IO_PROTOCOL
*PciIo
;
754 BiosVideoPrivate
= NULL
;
756 Status
= gBS
->OpenProtocol (
758 &gEfiGraphicsOutputProtocolGuid
,
759 (VOID
**) &GraphicsOutput
,
760 This
->DriverBindingHandle
,
762 EFI_OPEN_PROTOCOL_GET_PROTOCOL
764 if (!EFI_ERROR (Status
)) {
765 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
768 Status
= gBS
->OpenProtocol (
770 &gEfiVgaMiniPortProtocolGuid
,
771 (VOID
**) &VgaMiniPort
,
772 This
->DriverBindingHandle
,
774 EFI_OPEN_PROTOCOL_GET_PROTOCOL
776 if (!EFI_ERROR (Status
)) {
777 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
780 if (BiosVideoPrivate
== NULL
) {
781 return EFI_UNSUPPORTED
;
785 // Close PCI I/O protocol that opened by child handle
787 Status
= gBS
->CloseProtocol (
789 &gEfiPciIoProtocolGuid
,
790 This
->DriverBindingHandle
,
795 // Uninstall protocols on child handle
797 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
798 Status
= gBS
->UninstallMultipleProtocolInterfaces (
799 BiosVideoPrivate
->Handle
,
800 &gEfiDevicePathProtocolGuid
,
801 BiosVideoPrivate
->DevicePath
,
802 &gEfiGraphicsOutputProtocolGuid
,
803 &BiosVideoPrivate
->GraphicsOutput
,
804 &gEfiEdidDiscoveredProtocolGuid
,
805 &BiosVideoPrivate
->EdidDiscovered
,
806 &gEfiEdidActiveProtocolGuid
,
807 &BiosVideoPrivate
->EdidActive
,
811 Status
= gBS
->UninstallMultipleProtocolInterfaces (
812 BiosVideoPrivate
->Handle
,
813 &gEfiVgaMiniPortProtocolGuid
,
814 &BiosVideoPrivate
->VgaMiniPort
,
818 if (EFI_ERROR (Status
)) {
821 &gEfiPciIoProtocolGuid
,
823 This
->DriverBindingHandle
,
825 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
830 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
833 // Set the 80x25 Text VGA Mode
837 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
842 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
845 // Do not disable IO/memory decode since that would prevent legacy ROM from working
849 // Release all allocated resources
851 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
857 BiosVideoDeviceReleaseResource (
858 BIOS_VIDEO_DEV
*BiosVideoPrivate
863 Release resources of an video child device before stopping it.
867 BiosVideoPrivate - Video child device private data structure
875 if (BiosVideoPrivate
== NULL
) {
880 // Release all the resourses occupied by the BIOS_VIDEO_DEV
884 // Free VGA Frame Buffer
886 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
887 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
890 // Free VBE Frame Buffer
892 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
893 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
898 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
899 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
904 if (BiosVideoPrivate
->ModeData
!= NULL
) {
905 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
908 // Free memory allocated below 1MB
910 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
911 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
914 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
915 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
918 // Free graphics output protocol occupied resource
920 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
921 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
922 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
924 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
927 // Free EDID discovered protocol occupied resource
929 if (BiosVideoPrivate
->EdidDiscovered
.Edid
!= NULL
) {
930 gBS
->FreePool (BiosVideoPrivate
->EdidDiscovered
.Edid
);
933 // Free EDID active protocol occupied resource
935 if (BiosVideoPrivate
->EdidActive
.Edid
!= NULL
) {
936 gBS
->FreePool (BiosVideoPrivate
->EdidActive
.Edid
);
939 if (BiosVideoPrivate
->DevicePath
!= NULL
) {
940 gBS
->FreePool (BiosVideoPrivate
->DevicePath
);
944 // Close the ExitBootServices event
946 if (BiosVideoPrivate
->ExitBootServicesEvent
!= NULL
) {
947 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
950 gBS
->FreePool (BiosVideoPrivate
);
958 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
964 Generate a search key for a specified timing data.
968 EdidTiming - Pointer to EDID timing
971 The 32 bit unique key for search.
978 // Be sure no conflicts for all standard timing defined by VESA.
980 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
988 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
994 Parse the Established Timing and Standard Timing in EDID data block.
998 EdidBuffer - Pointer to EDID data block
999 ValidEdidTiming - Valid EDID timing information
1002 TRUE - The EDID data is valid.
1003 FALSE - The EDID data is invalid.
1012 UINT16 HorizontalResolution
;
1013 UINT16 VerticalResolution
;
1016 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming
;
1017 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*EdidDataBlock
;
1019 EdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) EdidBuffer
;
1022 // Check the checksum of EDID data
1025 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
; Index
++) {
1026 CheckSum
= CheckSum
+ EdidBuffer
[Index
];
1028 if (CheckSum
!= 0) {
1033 gBS
->SetMem (ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
), 0);
1035 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
1036 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
1037 (EdidDataBlock
->EstablishedTimings
[2] != 0)
1040 // Established timing data
1042 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
1043 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
1044 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
1045 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
1046 if (TimingBits
& 0x1) {
1047 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mEstablishedEdidTiming
[Index
]);
1050 TimingBits
= TimingBits
>> 1;
1054 // If no Established timing data, read the standard timing data
1056 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
1057 for (Index
= 0; Index
< 8; Index
++) {
1058 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
1060 // A valid Standard Timing
1062 HorizontalResolution
= BufferIndex
[0] * 8 + 248;
1063 AspectRatio
= BufferIndex
[1] >> 6;
1064 switch (AspectRatio
) {
1066 VerticalResolution
= HorizontalResolution
/ 16 * 10;
1069 VerticalResolution
= HorizontalResolution
/ 4 * 3;
1072 VerticalResolution
= HorizontalResolution
/ 5 * 4;
1075 VerticalResolution
= HorizontalResolution
/ 16 * 9;
1078 VerticalResolution
= HorizontalResolution
/ 4 * 3;
1081 RefreshRate
= (BufferIndex
[1] & 0x1f) + 60;
1082 TempTiming
.HorizontalResolution
= HorizontalResolution
;
1083 TempTiming
.VerticalResolution
= VerticalResolution
;
1084 TempTiming
.RefreshRate
= RefreshRate
;
1085 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
1092 ValidEdidTiming
->ValidNumber
= ValidNumber
;
1099 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
,
1100 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
1104 Routine Description:
1106 Search a specified Timing in all the valid EDID timings.
1110 ValidEdidTiming - All valid EDID timing information.
1111 EdidTiming - The Timing to search for.
1123 Key
= CalculateEdidKey (EdidTiming
);
1125 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
1126 if (Key
== ValidEdidTiming
->Key
[Index
]) {
1134 #define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
1139 IN EFI_PCI_IO_PROTOCOL
*PciIo
1143 BOOLEAN VgaCompatible
;
1146 VgaCompatible
= FALSE
;
1149 // Read the PCI Configuration Header
1151 Status
= PciIo
->Pci
.Read (
1153 EfiPciIoWidthUint32
,
1155 sizeof (Pci
) / sizeof (UINT32
),
1158 if (EFI_ERROR (Status
)) {
1159 return VgaCompatible
;
1163 // See if this is a VGA compatible controller or not
1165 if ((Pci
.Hdr
.Command
& PCI_DEVICE_ENABLED
) == PCI_DEVICE_ENABLED
) {
1166 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_OLD
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_OLD_VGA
) {
1168 // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device
1170 VgaCompatible
= TRUE
;
1173 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_DISPLAY
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_DISPLAY_VGA
&& Pci
.Hdr
.ClassCode
[0] == 0x00) {
1175 // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller
1177 VgaCompatible
= TRUE
;
1181 return VgaCompatible
;
1187 BiosVideoCheckForVbe (
1188 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1192 Routine Description:
1194 Check for VBE device
1198 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1202 EFI_SUCCESS - VBE device found
1207 EFI_IA32_REGISTER_SET Regs
;
1208 UINT16
*ModeNumberPtr
;
1211 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1212 BIOS_VIDEO_MODE_DATA
*CurrentModeData
;
1215 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing
;
1216 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming
;
1217 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*GraphicsOutputMode
;
1220 // Allocate buffer under 1MB for VBE data structures
1222 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
1223 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) +
1224 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
1225 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
) +
1226 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
1229 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
1231 Status
= gBS
->AllocatePages (
1233 EfiBootServicesData
,
1234 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
1235 &BiosVideoPrivate
->PagesBelow1MB
1237 if (EFI_ERROR (Status
)) {
1241 ZeroMem (&ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
));
1244 // Fill in the Graphics Output Protocol
1246 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1247 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1248 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVbeBlt
;
1249 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1252 // Fill in the VBE related data structures
1254 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
1255 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
1256 BiosVideoPrivate
->VbeEdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
1257 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeEdidDataBlock
+ 1);
1258 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
1259 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
1262 // Test to see if the Video Adapter is compliant with VBE 3.0
1264 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1265 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1266 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1267 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1268 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1269 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1271 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1273 Status
= EFI_DEVICE_ERROR
;
1276 // See if the VESA call succeeded
1278 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1282 // Check for 'VESA' signature
1284 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1288 // Check to see if this is VBE 2.0 or higher
1290 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1295 // Read EDID information
1297 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1298 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1302 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1303 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1305 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1308 // See if the VESA call succeeded
1311 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1313 // Parse EDID data structure to retrieve modes supported by monitor
1315 if (ParseEdidData ((UINT8
*) BiosVideoPrivate
->VbeEdidDataBlock
, &ValidEdidTiming
) == TRUE
) {
1318 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1319 Status
= gBS
->AllocatePool (
1320 EfiBootServicesData
,
1321 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1322 &BiosVideoPrivate
->EdidDiscovered
.Edid
1324 if (EFI_ERROR (Status
)) {
1328 BiosVideoPrivate
->EdidDiscovered
.Edid
,
1329 BiosVideoPrivate
->VbeEdidDataBlock
,
1330 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1333 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1334 Status
= gBS
->AllocatePool (
1335 EfiBootServicesData
,
1336 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1337 &BiosVideoPrivate
->EdidActive
.Edid
1339 if (EFI_ERROR (Status
)) {
1343 BiosVideoPrivate
->EdidActive
.Edid
,
1344 BiosVideoPrivate
->VbeEdidDataBlock
,
1345 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1348 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
1349 BiosVideoPrivate
->EdidDiscovered
.Edid
= NULL
;
1351 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1352 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1357 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1359 ModeNumberPtr
= (UINT16
*)
1361 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1362 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1368 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
1370 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1372 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1376 // Get the information about the mode
1378 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1379 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1380 Regs
.X
.CX
= *ModeNumberPtr
;
1381 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1382 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1383 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1385 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1388 // See if the call succeeded. If it didn't, then try the next mode.
1390 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1394 // See if the mode supports color. If it doesn't then try the next mode.
1396 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1400 // See if the mode supports graphics. If it doesn't then try the next mode.
1402 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1406 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1408 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1412 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1413 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1414 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1416 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1420 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1424 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1428 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1430 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1434 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1436 // EDID exist, check whether this mode match with any mode in EDID
1438 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1439 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1440 if (SearchEdidTiming (&ValidEdidTiming
, &Timing
) == FALSE
) {
1446 // Select a reasonable mode to be set for current display mode
1450 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1451 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1455 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1456 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1459 PreferMode
= ModeNumber
;
1461 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1462 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1466 if ((!EdidFound
) && (!ModeFound
)) {
1468 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1474 // Add mode to the list of available modes
1477 Status
= gBS
->AllocatePool (
1478 EfiBootServicesData
,
1479 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
),
1480 (VOID
**) &ModeBuffer
1482 if (EFI_ERROR (Status
)) {
1486 if (ModeNumber
> 1) {
1489 BiosVideoPrivate
->ModeData
,
1490 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1494 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1495 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1498 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1499 CurrentModeData
->VbeModeNumber
= *ModeNumberPtr
;
1500 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1501 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1502 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1503 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1504 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1505 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1506 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1507 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1508 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1509 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1511 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1512 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1513 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1514 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1515 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1516 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1517 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1518 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1519 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1521 CurrentModeData
->PixelFormat
= PixelBitMask
;
1522 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1523 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1524 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1525 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1526 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1527 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1530 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1531 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1532 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1533 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1535 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1536 CurrentModeData
->FrameBufferSize
= BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024;
1537 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1538 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1540 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1542 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1545 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1547 if (ModeNumber
== 0) {
1548 Status
= EFI_DEVICE_ERROR
;
1553 // Allocate buffer for Graphics Output Protocol mode information
1555 Status
= gBS
->AllocatePool (
1556 EfiBootServicesData
,
1557 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1558 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1560 if (EFI_ERROR (Status
)) {
1563 GraphicsOutputMode
= BiosVideoPrivate
->GraphicsOutput
.Mode
;
1564 Status
= gBS
->AllocatePool (
1565 EfiBootServicesData
,
1566 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1567 (VOID
**) &GraphicsOutputMode
->Info
1569 if (EFI_ERROR (Status
)) {
1573 GraphicsOutputMode
->MaxMode
= (UINT32
) ModeNumber
;
1575 // Current mode is unknow till now, set it to an invalid mode.
1577 GraphicsOutputMode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1580 // Find the best mode to initialize
1582 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1583 if (EFI_ERROR (Status
)) {
1584 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1585 Status
= BiosVideoGraphicsOutputSetMode (
1586 &BiosVideoPrivate
->GraphicsOutput
,
1589 if (!EFI_ERROR (Status
)) {
1593 if (PreferMode
== ModeNumber
) {
1595 // None mode is set successfully.
1603 // If there was an error, then free the mode structure
1605 if (EFI_ERROR (Status
)) {
1606 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1607 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1609 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1610 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1611 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1613 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1622 BiosVideoCheckForVga (
1623 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1627 Routine Description:
1629 Check for VGA device
1633 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1637 EFI_SUCCESS - Standard VGA device found
1642 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1645 // Fill in the Graphics Output Protocol
1647 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1648 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1649 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1652 // Allocate buffer for Graphics Output Protocol mode information
1654 Status
= gBS
->AllocatePool (
1655 EfiBootServicesData
,
1656 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1657 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1659 if (EFI_ERROR (Status
)) {
1662 Status
= gBS
->AllocatePool (
1663 EfiBootServicesData
,
1664 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1665 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
1667 if (EFI_ERROR (Status
)) {
1672 // Add mode to the list of available modes
1674 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1676 Status
= gBS
->AllocatePool (
1677 EfiBootServicesData
,
1678 sizeof (BIOS_VIDEO_MODE_DATA
),
1679 (VOID
**) &ModeBuffer
1681 if (EFI_ERROR (Status
)) {
1685 ModeBuffer
->VbeModeNumber
= 0x0012;
1686 ModeBuffer
->BytesPerScanLine
= 640;
1687 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1688 ModeBuffer
->FrameBufferSize
= 0;
1689 ModeBuffer
->HorizontalResolution
= 640;
1690 ModeBuffer
->VerticalResolution
= 480;
1691 ModeBuffer
->BitsPerPixel
= 8;
1692 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1694 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1697 // Test to see if the Video Adapter support the 640x480 16 color mode
1699 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1700 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1704 // If there was an error, then free the mode structure
1706 if (EFI_ERROR (Status
)) {
1707 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1708 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1710 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1711 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1712 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1714 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1720 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1724 BiosVideoGraphicsOutputQueryMode (
1725 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1726 IN UINT32 ModeNumber
,
1727 OUT UINTN
*SizeOfInfo
,
1728 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1732 Routine Description:
1734 Graphics Output protocol interface to get video mode
1737 This - Protocol instance pointer.
1738 ModeNumber - The mode number to return information on.
1739 Info - Caller allocated buffer that returns information about ModeNumber.
1740 SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
1743 EFI_SUCCESS - Mode information returned.
1744 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
1745 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
1746 EFI_INVALID_PARAMETER - One of the input args was NULL.
1750 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1752 BIOS_VIDEO_MODE_DATA
*ModeData
;
1754 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1756 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1757 return EFI_NOT_STARTED
;
1760 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1761 return EFI_INVALID_PARAMETER
;
1764 Status
= gBS
->AllocatePool (
1765 EfiBootServicesData
,
1766 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1769 if (EFI_ERROR (Status
)) {
1773 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1775 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1776 (*Info
)->Version
= 0;
1777 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1778 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1779 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1780 (*Info
)->PixelInformation
= ModeData
->PixelBitMask
;
1782 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1789 BiosVideoGraphicsOutputSetMode (
1790 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1791 IN UINT32 ModeNumber
1795 Routine Description:
1797 Graphics Output protocol interface to set video mode
1800 This - Protocol instance pointer.
1801 ModeNumber - The mode number to be set.
1804 EFI_SUCCESS - Graphics mode was changed.
1805 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
1806 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
1811 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1812 EFI_IA32_REGISTER_SET Regs
;
1813 BIOS_VIDEO_MODE_DATA
*ModeData
;
1815 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1818 return EFI_INVALID_PARAMETER
;
1821 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1822 return EFI_UNSUPPORTED
;
1825 if (ModeNumber
== This
->Mode
->Mode
) {
1829 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1831 if (BiosVideoPrivate
->LineBuffer
) {
1832 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
1835 if (BiosVideoPrivate
->VgaFrameBuffer
) {
1836 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1839 if (BiosVideoPrivate
->VbeFrameBuffer
) {
1840 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1843 BiosVideoPrivate
->LineBuffer
= NULL
;
1844 Status
= gBS
->AllocatePool (
1845 EfiBootServicesData
,
1846 ModeData
->BytesPerScanLine
,
1847 &BiosVideoPrivate
->LineBuffer
1849 if (EFI_ERROR (Status
)) {
1853 // Clear all registers
1855 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1857 if (ModeData
->VbeModeNumber
< 0x100) {
1859 // Allocate a working buffer for BLT operations to the VGA frame buffer
1861 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
1862 Status
= gBS
->AllocatePool (
1863 EfiBootServicesData
,
1865 &BiosVideoPrivate
->VgaFrameBuffer
1867 if (EFI_ERROR (Status
)) {
1873 Regs
.X
.AX
= ModeData
->VbeModeNumber
;
1874 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1878 // Allocate a working buffer for BLT operations to the VBE frame buffer
1880 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
1881 Status
= gBS
->AllocatePool (
1882 EfiBootServicesData
,
1883 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
,
1884 &BiosVideoPrivate
->VbeFrameBuffer
1886 if (EFI_ERROR (Status
)) {
1892 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1893 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1894 gBS
->SetMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
), 0);
1895 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1896 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1897 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1900 // Check to see if the call succeeded
1902 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1903 return EFI_DEVICE_ERROR
;
1906 // Initialize the state of the VbeFrameBuffer
1908 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1909 BiosVideoPrivate
->PciIo
,
1910 EfiPciIoWidthUint32
,
1911 EFI_PCI_IO_PASS_THROUGH_BAR
,
1912 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
1913 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
1914 BiosVideoPrivate
->VbeFrameBuffer
1916 if (EFI_ERROR (Status
)) {
1921 This
->Mode
->Mode
= ModeNumber
;
1922 This
->Mode
->Info
->Version
= 0;
1923 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
1924 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
1925 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
1926 This
->Mode
->Info
->PixelInformation
= ModeData
->PixelBitMask
;
1927 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1928 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1931 // Frame BufferSize remain unchanged
1933 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) ModeData
->LinearFrameBuffer
;
1934 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
1936 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
1943 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1944 IN UINT8
*VbeBuffer
,
1945 IN VOID
*MemAddress
,
1946 IN UINTN DestinationX
,
1947 IN UINTN DestinationY
,
1948 IN UINTN TotalBytes
,
1949 IN UINT32 VbePixelWidth
,
1950 IN UINTN BytesPerScanLine
1954 Routine Description:
1956 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1960 PciIo - The pointer of EFI_PCI_IO_PROTOCOL
1961 VbeBuffer - The data to transfer to screen
1962 MemAddress - Physical frame buffer base address
1963 DestinationX - The X coordinate of the destination for BltOperation
1964 DestinationY - The Y coordinate of the destination for BltOperation
1965 TotalBytes - The total bytes of copy
1966 VbePixelWidth - Bytes per pixel
1967 BytesPerScanLine - Bytes per scan line
1975 UINTN FrameBufferAddr
;
1977 UINTN RemainingBytes
;
1978 UINTN UnalignedBytes
;
1981 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1984 // If TotalBytes is less than 4 bytes, only start byte copy.
1986 if (TotalBytes
< 4) {
1987 Status
= PciIo
->Mem
.Write (
1990 EFI_PCI_IO_PASS_THROUGH_BAR
,
1991 (UINT64
) FrameBufferAddr
,
1995 ASSERT_EFI_ERROR (Status
);
2000 // If VbeBuffer is not 4-byte aligned, start byte copy.
2002 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
2004 if (UnalignedBytes
!= 0) {
2005 Status
= PciIo
->Mem
.Write (
2008 EFI_PCI_IO_PASS_THROUGH_BAR
,
2009 (UINT64
) FrameBufferAddr
,
2013 ASSERT_EFI_ERROR (Status
);
2014 FrameBufferAddr
+= UnalignedBytes
;
2015 VbeBuffer
+= UnalignedBytes
;
2019 // Calculate 4-byte block count and remaining bytes.
2021 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
2022 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
2025 // Copy 4-byte block and remaining bytes to physical frame buffer.
2027 if (CopyBlockNum
!= 0) {
2028 Status
= PciIo
->Mem
.Write (
2030 EfiPciIoWidthUint32
,
2031 EFI_PCI_IO_PASS_THROUGH_BAR
,
2032 (UINT64
) FrameBufferAddr
,
2036 ASSERT_EFI_ERROR (Status
);
2039 if (RemainingBytes
!= 0) {
2040 FrameBufferAddr
+= (CopyBlockNum
<< 2);
2041 VbeBuffer
+= (CopyBlockNum
<< 2);
2042 Status
= PciIo
->Mem
.Write (
2045 EFI_PCI_IO_PASS_THROUGH_BAR
,
2046 (UINT64
) FrameBufferAddr
,
2050 ASSERT_EFI_ERROR (Status
);
2055 // BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
2059 BiosVideoGraphicsOutputVbeBlt (
2060 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2061 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2062 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2065 IN UINTN DestinationX
,
2066 IN UINTN DestinationY
,
2073 Routine Description:
2075 Graphics Output protocol instance to block transfer for VBE device
2079 This - Pointer to Graphics Output protocol instance
2080 BltBuffer - The data to transfer to screen
2081 BltOperation - The operation to perform
2082 SourceX - The X coordinate of the source for BltOperation
2083 SourceY - The Y coordinate of the source for BltOperation
2084 DestinationX - The X coordinate of the destination for BltOperation
2085 DestinationY - The Y coordinate of the destination for BltOperation
2086 Width - The width of a rectangle in the blt rectangle in pixels
2087 Height - The height of a rectangle in the blt rectangle in pixels
2088 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
2089 If a Delta of 0 is used, the entire BltBuffer will be operated on.
2090 If a subrectangle of the BltBuffer is used, then Delta represents
2091 the number of bytes in a row of the BltBuffer.
2095 EFI_INVALID_PARAMETER - Invalid parameter passed in
2096 EFI_SUCCESS - Blt operation success
2100 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2101 BIOS_VIDEO_MODE_DATA
*Mode
;
2102 EFI_PCI_IO_PROTOCOL
*PciIo
;
2103 EFI_TPL OriginalTPL
;
2107 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
2109 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
2110 UINTN BytesPerScanLine
;
2115 UINT32 VbePixelWidth
;
2119 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2120 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
2121 PciIo
= BiosVideoPrivate
->PciIo
;
2123 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
2124 MemAddress
= Mode
->LinearFrameBuffer
;
2125 BytesPerScanLine
= Mode
->BytesPerScanLine
;
2126 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
2127 BltUint8
= (UINT8
*) BltBuffer
;
2128 TotalBytes
= Width
* VbePixelWidth
;
2130 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2131 return EFI_INVALID_PARAMETER
;
2134 if (Width
== 0 || Height
== 0) {
2135 return EFI_INVALID_PARAMETER
;
2138 // We need to fill the Virtual Screen buffer with the blt data.
2139 // The virtual screen is upside down, as the first row is the bootom row of
2142 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2144 // Video to BltBuffer: Source is Video, destination is BltBuffer
2146 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
2147 return EFI_INVALID_PARAMETER
;
2150 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
2151 return EFI_INVALID_PARAMETER
;
2155 // BltBuffer to Video: Source is BltBuffer, destination is Video
2157 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
2158 return EFI_INVALID_PARAMETER
;
2161 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
2162 return EFI_INVALID_PARAMETER
;
2166 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2167 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2168 // the number of bytes in each row can be computed.
2171 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2174 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2175 // We would not want a timer based event (Cursor, ...) to come in while we are
2176 // doing this operation.
2178 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2180 switch (BltOperation
) {
2181 case EfiBltVideoToBltBuffer
:
2182 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
2183 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2185 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
2187 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
2188 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2189 Pixel
= *(UINT32
*) (VbeBuffer
);
2190 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
2191 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
2192 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
2195 VbeBuffer
+= VbePixelWidth
;
2201 case EfiBltVideoToVideo
:
2202 for (Index
= 0; Index
< Height
; Index
++) {
2203 if (DestinationY
<= SourceY
) {
2204 SrcY
= SourceY
+ Index
;
2205 DstY
= DestinationY
+ Index
;
2207 SrcY
= SourceY
+ Height
- Index
- 1;
2208 DstY
= DestinationY
+ Height
- Index
- 1;
2211 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2212 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2221 // Update physical frame buffer.
2236 case EfiBltVideoFill
:
2237 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2238 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2240 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2242 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2244 (Blt
->Green
& Mode
->Green
.Mask
) <<
2245 Mode
->Green
.Position
2247 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2249 for (Index
= 0; Index
< Width
; Index
++) {
2255 VbeBuffer
+= VbePixelWidth
;
2258 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2259 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2261 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2266 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2268 // Update physical frame buffer.
2283 case EfiBltBufferToVideo
:
2284 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2285 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2286 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2287 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2289 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2291 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2292 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2293 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2300 VbeBuffer
+= VbePixelWidth
;
2303 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2306 // Update physical frame buffer.
2322 gBS
->RestoreTPL (OriginalTPL
);
2329 WriteGraphicsController (
2330 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2336 Routine Description:
2338 Write graphics controller registers
2342 PciIo - Pointer to PciIo protocol instance of the controller
2343 Address - Register address
2344 Data - Data to be written to register
2352 Address
= Address
| (Data
<< 8);
2355 EfiPciIoWidthUint16
,
2356 EFI_PCI_IO_PASS_THROUGH_BAR
,
2357 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2365 EFI_PCI_IO_PROTOCOL
*PciIo
,
2366 UINT8
*HardwareBuffer
,
2367 UINT8
*MemoryBuffer
,
2373 Routine Description:
2375 Read the four bit plane of VGA frame buffer
2379 PciIo - Pointer to PciIo protocol instance of the controller
2380 HardwareBuffer - Hardware VGA frame buffer address
2381 MemoryBuffer - Memory buffer address
2382 WidthInBytes - Number of bytes in a line to read
2383 Height - Height of the area to read
2393 UINTN FrameBufferOffset
;
2398 // Program the Mode Register Write mode 0, Read mode 0
2400 WriteGraphicsController (
2402 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2403 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2406 for (BitPlane
= 0, FrameBufferOffset
= 0;
2407 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2408 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2411 // Program the Read Map Select Register to select the correct bit plane
2413 WriteGraphicsController (
2415 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2419 Source
= HardwareBuffer
;
2420 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2422 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2426 EFI_PCI_IO_PASS_THROUGH_BAR
,
2429 (VOID
*) Destination
2436 VgaConvertToGraphicsOutputColor (
2437 UINT8
*MemoryBuffer
,
2440 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2444 Routine Description:
2446 Internal routine to convert VGA color to Grahpics Output color
2450 MemoryBuffer - Buffer containing VGA color
2451 X - The X coordinate of pixel on screen
2452 Y - The Y coordinate of pixel on screen
2453 BltBuffer - Buffer to contain converted Grahpics Output color
2465 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
2466 Mask
= mVgaBitMaskTable
[X
& 0x07];
2467 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2468 if (*MemoryBuffer
& Mask
) {
2473 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2478 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2482 Routine Description:
2484 Internal routine to convert Grahpics Output color to VGA color
2488 BltBuffer - buffer containing Grahpics Output color
2498 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2499 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2508 BiosVideoGraphicsOutputVgaBlt (
2509 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2510 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2511 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2514 IN UINTN DestinationX
,
2515 IN UINTN DestinationY
,
2522 Routine Description:
2524 Grahpics Output protocol instance to block transfer for VGA device
2528 This - Pointer to Grahpics Output protocol instance
2529 BltBuffer - The data to transfer to screen
2530 BltOperation - The operation to perform
2531 SourceX - The X coordinate of the source for BltOperation
2532 SourceY - The Y coordinate of the source for BltOperation
2533 DestinationX - The X coordinate of the destination for BltOperation
2534 DestinationY - The Y coordinate of the destination for BltOperation
2535 Width - The width of a rectangle in the blt rectangle in pixels
2536 Height - The height of a rectangle in the blt rectangle in pixels
2537 Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
2538 If a Delta of 0 is used, the entire BltBuffer will be operated on.
2539 If a subrectangle of the BltBuffer is used, then Delta represents
2540 the number of bytes in a row of the BltBuffer.
2544 EFI_INVALID_PARAMETER - Invalid parameter passed in
2545 EFI_SUCCESS - Blt operation success
2549 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2550 EFI_TPL OriginalTPL
;
2552 UINTN BytesPerScanLine
;
2553 UINTN BytesPerBitPlane
;
2565 UINT8
*SourceAddress
;
2566 UINT8
*DestinationAddress
;
2567 EFI_PCI_IO_PROTOCOL
*PciIo
;
2570 UINT8
*VgaFrameBuffer
;
2579 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2581 CurrentMode
= This
->Mode
->Mode
;
2582 PciIo
= BiosVideoPrivate
->PciIo
;
2583 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2584 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2585 BytesPerBitPlane
= BytesPerScanLine
* BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
;
2586 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2588 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2589 return EFI_INVALID_PARAMETER
;
2592 if (Width
== 0 || Height
== 0) {
2593 return EFI_INVALID_PARAMETER
;
2596 // We need to fill the Virtual Screen buffer with the blt data.
2597 // The virtual screen is upside down, as the first row is the bootom row of
2600 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2602 // Video to BltBuffer: Source is Video, destination is BltBuffer
2604 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2605 return EFI_INVALID_PARAMETER
;
2608 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2609 return EFI_INVALID_PARAMETER
;
2613 // BltBuffer to Video: Source is BltBuffer, destination is Video
2615 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2616 return EFI_INVALID_PARAMETER
;
2619 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2620 return EFI_INVALID_PARAMETER
;
2624 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2625 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2626 // the number of bytes in each row can be computed.
2629 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2632 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2633 // We would not want a timer based event (Cursor, ...) to come in while we are
2634 // doing this operation.
2636 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2639 // Compute some values we need for VGA
2641 switch (BltOperation
) {
2642 case EfiBltVideoToBltBuffer
:
2644 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2645 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2648 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2652 MemAddress
+ SourceOffset
,
2653 VgaFrameBuffer
+ SourceOffset
,
2659 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2661 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2662 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2663 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2664 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2672 case EfiBltVideoToVideo
:
2674 // Check for an aligned Video to Video operation
2676 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2678 // Program the Mode Register Write mode 1, Read mode 0
2680 WriteGraphicsController (
2682 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2683 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2686 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2687 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2689 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2693 EFI_PCI_IO_PASS_THROUGH_BAR
,
2694 (UINT64
) (DestinationAddress
+ Offset
),
2695 EFI_PCI_IO_PASS_THROUGH_BAR
,
2696 (UINT64
) (SourceAddress
+ Offset
),
2701 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2702 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2705 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2709 MemAddress
+ SourceOffset
,
2710 VgaFrameBuffer
+ SourceOffset
,
2718 case EfiBltVideoFill
:
2719 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2720 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2721 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2722 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2724 LeftMask
&= RightMask
;
2728 if (LeftMask
== 0xff) {
2734 if (RightMask
== 0xff) {
2739 PixelColor
= VgaConvertColor (BltBuffer
);
2742 // Program the Mode Register Write mode 2, Read mode 0
2744 WriteGraphicsController (
2746 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2747 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2751 // Program the Data Rotate/Function Select Register to replace
2753 WriteGraphicsController (
2755 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2756 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2759 if (LeftMask
!= 0) {
2761 // Program the BitMask register with the Left column mask
2763 WriteGraphicsController (
2765 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2769 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2771 // Read data from the bit planes into the latches
2776 EFI_PCI_IO_PASS_THROUGH_BAR
,
2782 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2787 EFI_PCI_IO_PASS_THROUGH_BAR
,
2797 // Program the BitMask register with the middle column mask of 0xff
2799 WriteGraphicsController (
2801 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2805 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2808 EfiPciIoWidthFillUint8
,
2809 EFI_PCI_IO_PASS_THROUGH_BAR
,
2817 if (RightMask
!= 0) {
2819 // Program the BitMask register with the Right column mask
2821 WriteGraphicsController (
2823 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2827 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2829 // Read data from the bit planes into the latches
2834 EFI_PCI_IO_PASS_THROUGH_BAR
,
2840 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2845 EFI_PCI_IO_PASS_THROUGH_BAR
,
2854 case EfiBltBufferToVideo
:
2855 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2856 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2859 // Program the Mode Register Write mode 2, Read mode 0
2861 WriteGraphicsController (
2863 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2864 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2868 // Program the Data Rotate/Function Select Register to replace
2870 WriteGraphicsController (
2872 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2873 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2876 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2877 for (Index1
= 0; Index1
< Width
; Index1
++) {
2878 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2880 AddressFix
= Address
;
2882 for (Bit
= 0; Bit
< 8; Bit
++) {
2884 // Program the BitMask register with the Left column mask
2886 WriteGraphicsController (
2888 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2892 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2894 // Read data from the bit planes into the latches
2899 EFI_PCI_IO_PASS_THROUGH_BAR
,
2908 EFI_PCI_IO_PASS_THROUGH_BAR
,
2911 &BiosVideoPrivate
->LineBuffer
[Index1
]
2915 LeftMask
= (UINT8
) (LeftMask
>> 1);
2916 if (LeftMask
== 0) {
2926 gBS
->RestoreTPL (OriginalTPL
);
2931 // VGA Mini Port Protocol Functions
2935 BiosVideoVgaMiniPortSetMode (
2936 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2941 Routine Description:
2943 VgaMiniPort protocol interface to set mode
2947 This - Pointer to VgaMiniPort protocol instance
2948 ModeNumber - The index of the mode
2952 EFI_UNSUPPORTED - The requested mode is not supported
2953 EFI_SUCCESS - The requested mode is set successfully
2957 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2958 EFI_IA32_REGISTER_SET Regs
;
2961 return EFI_INVALID_PARAMETER
;
2965 // Make sure the ModeNumber is a valid value
2967 if (ModeNumber
>= This
->MaxMode
) {
2968 return EFI_UNSUPPORTED
;
2971 // Get the device structure for this device
2973 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2975 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2977 switch (ModeNumber
) {
2980 // Set the 80x25 Text VGA Mode
2984 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2989 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2995 // Set the 80x50 Text VGA Mode
2999 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
3004 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
3008 return EFI_UNSUPPORTED
;