3 BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom.
5 Copyright (c) 2006 - 2009, Intel Corporation
6 All rights reserved. This program and the accompanying materials
7 are licensed and made available under the terms and conditions of the BSD License
8 which accompanies this distribution. The full text of the license may be found at
9 http://opensource.org/licenses/bsd-license.php
11 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
12 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
16 #include "BiosVideo.h"
19 // EFI Driver Binding Protocol Instance
21 EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding
= {
22 BiosVideoDriverBindingSupported
,
23 BiosVideoDriverBindingStart
,
24 BiosVideoDriverBindingStop
,
31 // Global lookup tables for VGA graphics modes
33 UINT8 mVgaLeftMaskTable
[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
35 UINT8 mVgaRightMaskTable
[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
37 UINT8 mVgaBitMaskTable
[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
39 EFI_LEGACY_8259_PROTOCOL
*mLegacy8259
= NULL
;
40 THUNK_CONTEXT mThunkContext
;
42 EFI_GRAPHICS_OUTPUT_BLT_PIXEL mVgaColorToGraphicsOutputColor
[] = {
44 // {B, G, R, reserved}
46 {0x00, 0x00, 0x00, 0x00}, // BLACK
47 {0x98, 0x00, 0x00, 0x00}, // LIGHTBLUE
48 {0x00, 0x98, 0x00, 0x00}, // LIGHGREEN
49 {0x98, 0x98, 0x00, 0x00}, // LIGHCYAN
50 {0x00, 0x00, 0x98, 0x00}, // LIGHRED
51 {0x98, 0x00, 0x98, 0x00}, // MAGENTA
52 {0x00, 0x98, 0x98, 0x00}, // BROWN
53 {0x98, 0x98, 0x98, 0x00}, // LIGHTGRAY
54 {0x10, 0x10, 0x10, 0x00},
55 {0xff, 0x10, 0x10, 0x00}, // BLUE
56 {0x10, 0xff, 0x10, 0x00}, // LIME
57 {0xff, 0xff, 0x10, 0x00}, // CYAN
58 {0x10, 0x10, 0xff, 0x00}, // RED
59 {0xf0, 0x10, 0xff, 0x00}, // FUCHSIA
60 {0x10, 0xff, 0xff, 0x00}, // YELLOW
61 {0xff, 0xff, 0xff, 0x00} // WHITE
65 // Standard timing defined by VESA EDID
67 VESA_BIOS_EXTENSIONS_EDID_TIMING mEstablishedEdidTiming
[] = {
69 // Established Timing I
80 // Established Timing II
91 // Established Timing III
97 Install child hanlde for a detect BiosVideo device and install related protocol
98 into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.
100 @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL
101 @param ParentHandle Parent's controller handle
102 @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer
103 @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer
104 @param ParentDevicePath Parent's BIOS Video controller device path
105 @param RemainingDevicePath Remaining device path node instance for children.
107 @return whether success to create children handle for a VGA device and install
108 related protocol into new children handle.
112 BiosVideoChildHandleInstall (
113 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
114 IN EFI_HANDLE ParentHandle
,
115 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
116 IN EFI_LEGACY_8259_PROTOCOL
*ParentLegacy8259
,
117 IN THUNK_CONTEXT
*ThunkContext
,
118 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
119 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
124 Deregister an video child handle and free resources
126 @param This Protocol instance pointer.
127 @param Controller Video controller handle
128 @param Handle Video child handle
135 BiosVideoChildHandleUninstall (
136 EFI_DRIVER_BINDING_PROTOCOL
*This
,
137 EFI_HANDLE Controller
,
143 Collect the resource from destroyed bios video device.
145 @param BiosVideoPrivate Video child device private data structure
149 BiosVideoDeviceReleaseResource (
150 BIOS_VIDEO_DEV
*BiosVideoPrivate
157 @param ImageHandle Handle of driver image.
158 @param SystemTable Pointer to system table.
164 BiosVideoDriverEntryPoint (
165 IN EFI_HANDLE ImageHandle
,
166 IN EFI_SYSTEM_TABLE
*SystemTable
171 Status
= EfiLibInstallDriverBindingComponentName2 (
174 &gBiosVideoDriverBinding
,
176 &gBiosVideoComponentName
,
177 &gBiosVideoComponentName2
184 Test to see if Bios Video could be supported on the Controller.
186 @param This Pointer to driver binding protocol
187 @param Controller Controller handle to connect
188 @param RemainingDevicePath A pointer to the remaining portion of a device path
190 @retval EFI_SUCCESS This driver supports this device.
191 @retval other This driver does not support this device.
196 BiosVideoDriverBindingSupported (
197 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
198 IN EFI_HANDLE Controller
,
199 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
203 EFI_LEGACY_8259_PROTOCOL
*LegacyBios
;
204 EFI_PCI_IO_PROTOCOL
*PciIo
;
207 // See if the Legacy 8259 Protocol is available
209 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &LegacyBios
);
210 if (EFI_ERROR (Status
)) {
215 // Open the IO Abstraction(s) needed to perform the supported test
217 Status
= gBS
->OpenProtocol (
219 &gEfiPciIoProtocolGuid
,
221 This
->DriverBindingHandle
,
223 EFI_OPEN_PROTOCOL_BY_DRIVER
225 if (EFI_ERROR (Status
)) {
229 if (!BiosVideoIsVga (PciIo
)) {
230 Status
= EFI_UNSUPPORTED
;
235 &gEfiPciIoProtocolGuid
,
236 This
->DriverBindingHandle
,
244 Install Graphics Output Protocol onto VGA device handles
246 @param This Pointer to driver binding protocol
247 @param Controller Controller handle to connect
248 @param RemainingDevicePath A pointer to the remaining portion of a device path
255 BiosVideoDriverBindingStart (
256 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
257 IN EFI_HANDLE Controller
,
258 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
262 EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
;
263 EFI_PCI_IO_PROTOCOL
*PciIo
;
267 // Prepare for status code
269 Status
= gBS
->HandleProtocol (
271 &gEfiDevicePathProtocolGuid
,
272 (VOID
**) &ParentDevicePath
274 if (EFI_ERROR (Status
)) {
279 // Open the IO Abstraction(s) needed
281 Status
= gBS
->OpenProtocol (
283 &gEfiPciIoProtocolGuid
,
285 This
->DriverBindingHandle
,
287 EFI_OPEN_PROTOCOL_BY_DRIVER
289 if (EFI_ERROR (Status
)) {
294 // Establish legacy environment for thunk call for all children handle.
296 if (mLegacy8259
== NULL
) {
297 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &mLegacy8259
);
298 if (EFI_ERROR (Status
)) {
302 InitializeBiosIntCaller(&mThunkContext
);
303 InitializeInterruptRedirection(mLegacy8259
);
307 // Create child handle and install GraphicsOutputProtocol on it
309 Status
= BiosVideoChildHandleInstall (
320 if (EFI_ERROR (Status
)) {
323 // Release PCI I/O Protocols on the controller handle.
327 &gEfiPciIoProtocolGuid
,
328 This
->DriverBindingHandle
,
338 Stop this driver on Controller
340 @param This Protocol instance pointer.
341 @param Controller Handle of device to stop driver on
342 @param NumberOfChildren Number of Handles in ChildHandleBuffer. If number of
343 children is zero stop the entire bus driver.
344 @param ChildHandleBuffer List of Child Handles to Stop.
346 @retval EFI_SUCCESS This driver is removed Controller.
347 @retval other This driver was not removed from this device.
352 BiosVideoDriverBindingStop (
353 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
354 IN EFI_HANDLE Controller
,
355 IN UINTN NumberOfChildren
,
356 IN EFI_HANDLE
*ChildHandleBuffer
360 BOOLEAN AllChildrenStopped
;
363 if (NumberOfChildren
== 0) {
365 // Close PCI I/O protocol on the controller handle
369 &gEfiPciIoProtocolGuid
,
370 This
->DriverBindingHandle
,
377 AllChildrenStopped
= TRUE
;
378 for (Index
= 0; Index
< NumberOfChildren
; Index
++) {
379 Status
= BiosVideoChildHandleUninstall (This
, Controller
, ChildHandleBuffer
[Index
]);
381 if (EFI_ERROR (Status
)) {
382 AllChildrenStopped
= FALSE
;
386 if (!AllChildrenStopped
) {
387 return EFI_DEVICE_ERROR
;
394 Install child hanlde for a detect BiosVideo device and install related protocol
395 into this handle, such as EFI_GRAPHIC_OUTPUT_PROTOCOL.
397 @param This Instance pointer of EFI_DRIVER_BINDING_PROTOCOL
398 @param ParentHandle Parent's controller handle
399 @param ParentPciIo Parent's EFI_PCI_IO_PROTOCOL instance pointer
400 @param ParentLegacy8259 Parent's EFI_LEGACY_8259_PROTOCOL instance pointer
401 @param ParentDevicePath Parent's BIOS Video controller device path
402 @param RemainingDevicePath Remaining device path node instance for children.
404 @return whether success to create children handle for a VGA device and install
405 related protocol into new children handle.
409 BiosVideoChildHandleInstall (
410 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
411 IN EFI_HANDLE ParentHandle
,
412 IN EFI_PCI_IO_PROTOCOL
*ParentPciIo
,
413 IN EFI_LEGACY_8259_PROTOCOL
*ParentLegacy8259
,
414 IN THUNK_CONTEXT
*ParentThunkContext
,
415 IN EFI_DEVICE_PATH_PROTOCOL
*ParentDevicePath
,
416 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
420 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
421 ACPI_ADR_DEVICE_PATH AcpiDeviceNode
;
424 // Allocate the private device structure for video device
426 Status
= gBS
->AllocatePool (
428 sizeof (BIOS_VIDEO_DEV
),
429 (VOID
**) &BiosVideoPrivate
431 if (EFI_ERROR (Status
)) {
435 ZeroMem (BiosVideoPrivate
, sizeof (BIOS_VIDEO_DEV
));
437 if (!BiosVideoIsVga (ParentPciIo
)) {
438 Status
= EFI_UNSUPPORTED
;
442 BiosVideoPrivate
->VgaCompatible
= TRUE
;
445 // Initialize the child private structure
447 BiosVideoPrivate
->Signature
= BIOS_VIDEO_DEV_SIGNATURE
;
448 BiosVideoPrivate
->Handle
= NULL
;
451 // Fill in Graphics Output specific mode structures
453 BiosVideoPrivate
->HardwareNeedsStarting
= TRUE
;
454 BiosVideoPrivate
->ModeData
= NULL
;
455 BiosVideoPrivate
->LineBuffer
= NULL
;
456 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
457 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
460 // Fill in the VGA Mini Port Protocol fields
462 BiosVideoPrivate
->VgaMiniPort
.SetMode
= BiosVideoVgaMiniPortSetMode
;
463 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryOffset
= 0xb8000;
464 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterOffset
= 0x3d4;
465 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterOffset
= 0x3d5;
466 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
467 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
468 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
471 // Assume that Graphics Output Protocol will be produced until proven otherwise
473 BiosVideoPrivate
->ProduceGraphicsOutput
= TRUE
;
476 // Child handle need to consume the Legacy Bios protocol
478 BiosVideoPrivate
->Legacy8259
= ParentLegacy8259
;
479 BiosVideoPrivate
->ThunkContext
= ParentThunkContext
;
482 // When check for VBE, PCI I/O protocol is needed, so use parent's protocol interface temporally
484 BiosVideoPrivate
->PciIo
= ParentPciIo
;
487 // Check for VESA BIOS Extensions for modes that are compatible with Graphics Output
489 Status
= BiosVideoCheckForVbe (BiosVideoPrivate
);
490 if (EFI_ERROR (Status
)) {
492 // The VESA BIOS Extensions are not compatible with Graphics Output, so check for support
493 // for the standard 640x480 16 color VGA mode
495 if (BiosVideoPrivate
->VgaCompatible
) {
496 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
499 if (EFI_ERROR (Status
)) {
501 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
502 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
504 BiosVideoPrivate
->ProduceGraphicsOutput
= FALSE
;
507 // INT services are available, so on the 80x25 and 80x50 text mode are supported
509 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
513 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
514 if (RemainingDevicePath
== NULL
) {
515 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
516 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
517 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
518 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
519 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
521 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (
523 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
526 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
530 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
532 Status
= gBS
->InstallMultipleProtocolInterfaces (
533 &BiosVideoPrivate
->Handle
,
534 &gEfiDevicePathProtocolGuid
,
535 BiosVideoPrivate
->DevicePath
,
536 &gEfiGraphicsOutputProtocolGuid
,
537 &BiosVideoPrivate
->GraphicsOutput
,
538 &gEfiEdidDiscoveredProtocolGuid
,
539 &BiosVideoPrivate
->EdidDiscovered
,
540 &gEfiEdidActiveProtocolGuid
,
541 &BiosVideoPrivate
->EdidActive
,
545 if (!EFI_ERROR (Status
)) {
547 // Open the Parent Handle for the child
549 Status
= gBS
->OpenProtocol (
551 &gEfiPciIoProtocolGuid
,
552 (VOID
**) &BiosVideoPrivate
->PciIo
,
553 This
->DriverBindingHandle
,
554 BiosVideoPrivate
->Handle
,
555 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
557 if (EFI_ERROR (Status
)) {
563 // Install VGA Mini Port Protocol
565 Status
= gBS
->InstallMultipleProtocolInterfaces (
566 &BiosVideoPrivate
->Handle
,
567 &gEfiVgaMiniPortProtocolGuid
,
568 &BiosVideoPrivate
->VgaMiniPort
,
574 if (EFI_ERROR (Status
)) {
576 // Free private data structure
578 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
585 Deregister an video child handle and free resources
587 @param This Protocol instance pointer.
588 @param Controller Video controller handle
589 @param Handle Video child handle
595 BiosVideoChildHandleUninstall (
596 EFI_DRIVER_BINDING_PROTOCOL
*This
,
597 EFI_HANDLE Controller
,
602 IA32_REGISTER_SET Regs
;
603 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
604 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
605 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
606 EFI_PCI_IO_PROTOCOL
*PciIo
;
608 BiosVideoPrivate
= NULL
;
610 Status
= gBS
->OpenProtocol (
612 &gEfiGraphicsOutputProtocolGuid
,
613 (VOID
**) &GraphicsOutput
,
614 This
->DriverBindingHandle
,
616 EFI_OPEN_PROTOCOL_GET_PROTOCOL
618 if (!EFI_ERROR (Status
)) {
619 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
622 Status
= gBS
->OpenProtocol (
624 &gEfiVgaMiniPortProtocolGuid
,
625 (VOID
**) &VgaMiniPort
,
626 This
->DriverBindingHandle
,
628 EFI_OPEN_PROTOCOL_GET_PROTOCOL
630 if (!EFI_ERROR (Status
)) {
631 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
634 if (BiosVideoPrivate
== NULL
) {
635 return EFI_UNSUPPORTED
;
639 // Close PCI I/O protocol that opened by child handle
641 Status
= gBS
->CloseProtocol (
643 &gEfiPciIoProtocolGuid
,
644 This
->DriverBindingHandle
,
649 // Uninstall protocols on child handle
651 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
652 Status
= gBS
->UninstallMultipleProtocolInterfaces (
653 BiosVideoPrivate
->Handle
,
654 &gEfiDevicePathProtocolGuid
,
655 BiosVideoPrivate
->DevicePath
,
656 &gEfiGraphicsOutputProtocolGuid
,
657 &BiosVideoPrivate
->GraphicsOutput
,
658 &gEfiEdidDiscoveredProtocolGuid
,
659 &BiosVideoPrivate
->EdidDiscovered
,
660 &gEfiEdidActiveProtocolGuid
,
661 &BiosVideoPrivate
->EdidActive
,
665 Status
= gBS
->UninstallMultipleProtocolInterfaces (
666 BiosVideoPrivate
->Handle
,
667 &gEfiVgaMiniPortProtocolGuid
,
668 &BiosVideoPrivate
->VgaMiniPort
,
672 if (EFI_ERROR (Status
)) {
675 &gEfiPciIoProtocolGuid
,
677 This
->DriverBindingHandle
,
679 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
684 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
687 // Set the 80x25 Text VGA Mode
691 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
696 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
699 // Do not disable IO/memory decode since that would prevent legacy ROM from working
703 // Release all allocated resources
705 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
711 Collect the resource from destroyed bios video device.
713 @param BiosVideoPrivate Video child device private data structure
717 BiosVideoDeviceReleaseResource (
718 BIOS_VIDEO_DEV
*BiosVideoPrivate
721 if (BiosVideoPrivate
== NULL
) {
726 // Release all the resourses occupied by the BIOS_VIDEO_DEV
730 // Free VGA Frame Buffer
732 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
733 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
736 // Free VBE Frame Buffer
738 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
739 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
744 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
745 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
750 if (BiosVideoPrivate
->ModeData
!= NULL
) {
751 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
754 // Free memory allocated below 1MB
756 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
757 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
760 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
761 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
764 // Free graphics output protocol occupied resource
766 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
767 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
768 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
770 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
773 // Free EDID discovered protocol occupied resource
775 if (BiosVideoPrivate
->EdidDiscovered
.Edid
!= NULL
) {
776 gBS
->FreePool (BiosVideoPrivate
->EdidDiscovered
.Edid
);
779 // Free EDID active protocol occupied resource
781 if (BiosVideoPrivate
->EdidActive
.Edid
!= NULL
) {
782 gBS
->FreePool (BiosVideoPrivate
->EdidActive
.Edid
);
785 if (BiosVideoPrivate
->DevicePath
!= NULL
) {
786 gBS
->FreePool (BiosVideoPrivate
->DevicePath
);
789 gBS
->FreePool (BiosVideoPrivate
);
796 Generate a search key for a specified timing data.
799 @param EdidTiming - Pointer to EDID timing
801 @return The 32 bit unique key for search.
807 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
813 // Be sure no conflicts for all standard timing defined by VESA.
815 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
821 Parse the Established Timing and Standard Timing in EDID data block.
824 @param EdidBuffer - Pointer to EDID data block
825 @param ValidEdidTiming - Valid EDID timing information
827 @return TRUE - The EDID data is valid.
828 FALSE - The EDID data is invalid.
835 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
843 UINT16 HorizontalResolution
;
844 UINT16 VerticalResolution
;
847 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming
;
848 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*EdidDataBlock
;
850 EdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) EdidBuffer
;
853 // Check the checksum of EDID data
856 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
; Index
++) {
857 CheckSum
= (UINT8
)(CheckSum
+ EdidBuffer
[Index
]);
864 gBS
->SetMem (ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
), 0);
866 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
867 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
868 (EdidDataBlock
->EstablishedTimings
[2] != 0)
871 // Established timing data
873 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
874 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
875 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
876 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
877 if (TimingBits
& 0x1) {
878 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mEstablishedEdidTiming
[Index
]);
881 TimingBits
= TimingBits
>> 1;
885 // If no Established timing data, read the standard timing data
887 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
888 for (Index
= 0; Index
< 8; Index
++) {
889 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
891 // A valid Standard Timing
893 HorizontalResolution
= (UINT8
) (BufferIndex
[0] * 8 + 248);
894 AspectRatio
= (UINT8
) (BufferIndex
[1] >> 6);
895 switch (AspectRatio
) {
897 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 16 * 10);
900 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 4 * 3);
903 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 5 * 4);
906 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 16 * 9);
909 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 4 * 3);
912 RefreshRate
= (UINT8
) ((BufferIndex
[1] & 0x1f) + 60);
913 TempTiming
.HorizontalResolution
= HorizontalResolution
;
914 TempTiming
.VerticalResolution
= VerticalResolution
;
915 TempTiming
.RefreshRate
= RefreshRate
;
916 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
923 ValidEdidTiming
->ValidNumber
= ValidNumber
;
929 Search a specified Timing in all the valid EDID timings.
932 @param ValidEdidTiming - All valid EDID timing information.
933 @param EdidTiming - The Timing to search for.
935 @return TRUE - Found.
942 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
,
943 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
949 Key
= CalculateEdidKey (EdidTiming
);
951 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
952 if (Key
== ValidEdidTiming
->Key
[Index
]) {
960 #define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
964 Judge whether this device is VGA device.
966 @param PciIo Parent PciIo protocol instance pointer
968 @retval TRUE Is vga device
969 @retval FALSE Is no vga device
973 IN EFI_PCI_IO_PROTOCOL
*PciIo
977 BOOLEAN VgaCompatible
;
980 VgaCompatible
= FALSE
;
983 // Read the PCI Configuration Header
985 Status
= PciIo
->Pci
.Read (
989 sizeof (Pci
) / sizeof (UINT32
),
992 if (EFI_ERROR (Status
)) {
993 return VgaCompatible
;
997 // See if this is a VGA compatible controller or not
999 if ((Pci
.Hdr
.Command
& PCI_DEVICE_ENABLED
) == PCI_DEVICE_ENABLED
) {
1000 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_OLD
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_OLD_VGA
) {
1002 // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device
1004 VgaCompatible
= TRUE
;
1007 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_DISPLAY
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_DISPLAY_VGA
&& Pci
.Hdr
.ClassCode
[0] == 0x00) {
1009 // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller
1011 VgaCompatible
= TRUE
;
1015 return VgaCompatible
;
1020 Check for VBE device
1022 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1024 @retval EFI_SUCCESS VBE device found
1029 BiosVideoCheckForVbe (
1030 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1034 IA32_REGISTER_SET Regs
;
1035 UINT16
*ModeNumberPtr
;
1038 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1039 BIOS_VIDEO_MODE_DATA
*CurrentModeData
;
1042 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing
;
1043 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming
;
1044 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*GraphicsOutputMode
;
1047 // Allocate buffer under 1MB for VBE data structures
1049 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
1050 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) +
1051 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
1052 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
) +
1053 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
1056 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
1058 Status
= gBS
->AllocatePages (
1060 EfiBootServicesData
,
1061 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
1062 &BiosVideoPrivate
->PagesBelow1MB
1064 if (EFI_ERROR (Status
)) {
1068 ZeroMem (&ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
));
1071 // Fill in the Graphics Output Protocol
1073 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1074 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1075 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVbeBlt
;
1076 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1079 // Fill in the VBE related data structures
1081 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
1082 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
1083 BiosVideoPrivate
->VbeEdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
1084 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeEdidDataBlock
+ 1);
1085 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
1086 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
1089 // Test to see if the Video Adapter is compliant with VBE 3.0
1091 // INT 10 - VESA SuperVGA BIOS (VBE) - GET SuperVGA INFORMATION
1094 // ES:DI -> buffer for SuperVGA information (see #00077)
1095 // Return: AL = 4Fh if function supported
1098 // ES:DI buffer filled
1101 // 02h function not supported by current hardware configuration
1102 // 03h function invalid in current video mode
1103 // Desc: determine whether VESA BIOS extensions are present and the capabilities
1104 // supported by the display adapter
1106 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1107 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1108 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1109 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1110 Regs
.E
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1111 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1113 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1115 Status
= EFI_DEVICE_ERROR
;
1118 // See if the VESA call succeeded
1120 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1124 // Check for 'VESA' signature
1126 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1130 // Check to see if this is VBE 2.0 or higher
1132 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1137 // Read EDID information
1139 // INT 10 - VESA VBE/DC (Display Data Channel) - READ EDID
1145 // ES:DI -> 128-byte buffer for EDID record (see #00127)
1146 // Return: AL = 4Fh if function supported
1149 // ES:DI buffer filled
1150 // 01h failed (e.g. non-DDC monitor)
1152 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1153 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1157 Regs
.E
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1158 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1160 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1163 // See if the VESA call succeeded
1166 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1168 // Parse EDID data structure to retrieve modes supported by monitor
1170 if (ParseEdidData ((UINT8
*) BiosVideoPrivate
->VbeEdidDataBlock
, &ValidEdidTiming
) == TRUE
) {
1173 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1174 Status
= gBS
->AllocatePool (
1175 EfiBootServicesData
,
1176 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1177 (VOID
**) &BiosVideoPrivate
->EdidDiscovered
.Edid
1179 if (EFI_ERROR (Status
)) {
1183 BiosVideoPrivate
->EdidDiscovered
.Edid
,
1184 BiosVideoPrivate
->VbeEdidDataBlock
,
1185 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1188 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1189 Status
= gBS
->AllocatePool (
1190 EfiBootServicesData
,
1191 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1192 (VOID
**)&BiosVideoPrivate
->EdidActive
.Edid
1194 if (EFI_ERROR (Status
)) {
1198 BiosVideoPrivate
->EdidActive
.Edid
,
1199 BiosVideoPrivate
->VbeEdidDataBlock
,
1200 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1203 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
1204 BiosVideoPrivate
->EdidDiscovered
.Edid
= NULL
;
1206 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1207 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1212 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1214 ModeNumberPtr
= (UINT16
*)
1216 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1217 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1223 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
1225 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1227 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1231 // Get the information about the mode
1233 // INT 10 - VESA SuperVGA BIOS - GET SuperVGA MODE INFORMATION
1236 // CX = SuperVGA video mode (see #04082 for bitfields)
1237 // ES:DI -> 256-byte buffer for mode information (see #00079)
1238 // Return: AL = 4Fh if function supported
1241 // ES:DI buffer filled
1243 // Desc: determine the attributes of the specified video mode
1245 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1246 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1247 Regs
.X
.CX
= *ModeNumberPtr
;
1248 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1249 Regs
.E
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1250 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1252 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1255 // See if the call succeeded. If it didn't, then try the next mode.
1257 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1261 // See if the mode supports color. If it doesn't then try the next mode.
1263 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1267 // See if the mode supports graphics. If it doesn't then try the next mode.
1269 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1273 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1275 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1279 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1280 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1281 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1283 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1287 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1291 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1295 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1297 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1301 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1303 // EDID exist, check whether this mode match with any mode in EDID
1305 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1306 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1307 if (SearchEdidTiming (&ValidEdidTiming
, &Timing
) == FALSE
) {
1313 // Select a reasonable mode to be set for current display mode
1317 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1318 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1322 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1323 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1326 PreferMode
= ModeNumber
;
1328 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1329 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1333 if ((!EdidFound
) && (!ModeFound
)) {
1335 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1341 // Add mode to the list of available modes
1344 Status
= gBS
->AllocatePool (
1345 EfiBootServicesData
,
1346 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
),
1347 (VOID
**) &ModeBuffer
1349 if (EFI_ERROR (Status
)) {
1353 if (ModeNumber
> 1) {
1356 BiosVideoPrivate
->ModeData
,
1357 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1361 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1362 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1365 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1366 CurrentModeData
->VbeModeNumber
= *ModeNumberPtr
;
1367 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1368 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1369 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1370 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1371 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1372 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1373 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1374 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1375 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1376 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1378 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1379 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1380 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1381 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1382 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1383 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1384 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1385 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1386 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1388 CurrentModeData
->PixelFormat
= PixelBitMask
;
1389 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1390 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1391 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1392 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1393 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1394 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1397 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1398 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1399 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1400 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1402 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1403 CurrentModeData
->FrameBufferSize
= BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024;
1404 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1405 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1407 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1409 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1412 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1414 if (ModeNumber
== 0) {
1415 Status
= EFI_DEVICE_ERROR
;
1420 // Allocate buffer for Graphics Output Protocol mode information
1422 Status
= gBS
->AllocatePool (
1423 EfiBootServicesData
,
1424 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1425 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1427 if (EFI_ERROR (Status
)) {
1430 GraphicsOutputMode
= BiosVideoPrivate
->GraphicsOutput
.Mode
;
1431 Status
= gBS
->AllocatePool (
1432 EfiBootServicesData
,
1433 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1434 (VOID
**) &GraphicsOutputMode
->Info
1436 if (EFI_ERROR (Status
)) {
1440 GraphicsOutputMode
->MaxMode
= (UINT32
) ModeNumber
;
1442 // Current mode is unknow till now, set it to an invalid mode.
1444 GraphicsOutputMode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1447 // Find the best mode to initialize
1449 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1450 if (EFI_ERROR (Status
)) {
1451 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1452 Status
= BiosVideoGraphicsOutputSetMode (
1453 &BiosVideoPrivate
->GraphicsOutput
,
1456 if (!EFI_ERROR (Status
)) {
1460 if (PreferMode
== ModeNumber
) {
1462 // None mode is set successfully.
1470 // If there was an error, then free the mode structure
1472 if (EFI_ERROR (Status
)) {
1473 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1474 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1476 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1477 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1478 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1480 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1488 Check for VGA device
1490 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1492 @retval EFI_SUCCESS Standard VGA device found
1496 BiosVideoCheckForVga (
1497 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1501 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1504 // Fill in the Graphics Output Protocol
1506 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1507 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1508 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1511 // Allocate buffer for Graphics Output Protocol mode information
1513 Status
= gBS
->AllocatePool (
1514 EfiBootServicesData
,
1515 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1516 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1518 if (EFI_ERROR (Status
)) {
1521 Status
= gBS
->AllocatePool (
1522 EfiBootServicesData
,
1523 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1524 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
1526 if (EFI_ERROR (Status
)) {
1531 // Add mode to the list of available modes
1533 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1535 Status
= gBS
->AllocatePool (
1536 EfiBootServicesData
,
1537 sizeof (BIOS_VIDEO_MODE_DATA
),
1538 (VOID
**) &ModeBuffer
1540 if (EFI_ERROR (Status
)) {
1544 ModeBuffer
->VbeModeNumber
= 0x0012;
1545 ModeBuffer
->BytesPerScanLine
= 640;
1546 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1547 ModeBuffer
->FrameBufferSize
= 0;
1548 ModeBuffer
->HorizontalResolution
= 640;
1549 ModeBuffer
->VerticalResolution
= 480;
1550 ModeBuffer
->BitsPerPixel
= 8;
1551 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1553 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1556 // Test to see if the Video Adapter support the 640x480 16 color mode
1558 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1559 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1563 // If there was an error, then free the mode structure
1565 if (EFI_ERROR (Status
)) {
1566 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1567 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1569 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1570 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1571 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1573 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1579 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1583 Graphics Output protocol interface to get video mode
1586 @param This - Protocol instance pointer.
1587 @param ModeNumber - The mode number to return information on.
1588 @param SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
1589 @param Info - Caller allocated buffer that returns information about ModeNumber.
1591 @return EFI_SUCCESS - Mode information returned.
1592 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
1593 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
1594 EFI_INVALID_PARAMETER - One of the input args was NULL.
1599 BiosVideoGraphicsOutputQueryMode (
1600 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1601 IN UINT32 ModeNumber
,
1602 OUT UINTN
*SizeOfInfo
,
1603 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1606 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1608 BIOS_VIDEO_MODE_DATA
*ModeData
;
1610 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1612 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1613 return EFI_NOT_STARTED
;
1616 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1617 return EFI_INVALID_PARAMETER
;
1620 Status
= gBS
->AllocatePool (
1621 EfiBootServicesData
,
1622 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1625 if (EFI_ERROR (Status
)) {
1629 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1631 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1632 (*Info
)->Version
= 0;
1633 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1634 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1635 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1636 (*Info
)->PixelInformation
= ModeData
->PixelBitMask
;
1638 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1645 Graphics Output protocol interface to set video mode
1648 @param This - Protocol instance pointer.
1649 @param ModeNumber - The mode number to be set.
1651 @return EFI_SUCCESS - Graphics mode was changed.
1652 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
1653 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
1658 BiosVideoGraphicsOutputSetMode (
1659 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1660 IN UINT32 ModeNumber
1664 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1665 IA32_REGISTER_SET Regs
;
1666 BIOS_VIDEO_MODE_DATA
*ModeData
;
1668 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1671 return EFI_INVALID_PARAMETER
;
1674 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1675 return EFI_UNSUPPORTED
;
1678 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1680 if (BiosVideoPrivate
->LineBuffer
) {
1681 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
1684 if (BiosVideoPrivate
->VgaFrameBuffer
) {
1685 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1688 if (BiosVideoPrivate
->VbeFrameBuffer
) {
1689 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1692 BiosVideoPrivate
->LineBuffer
= NULL
;
1693 Status
= gBS
->AllocatePool (
1694 EfiBootServicesData
,
1695 ModeData
->BytesPerScanLine
,
1696 (VOID
**) &BiosVideoPrivate
->LineBuffer
1698 if (EFI_ERROR (Status
)) {
1702 // Clear all registers
1704 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1706 if (ModeData
->VbeModeNumber
< 0x100) {
1708 // Allocate a working buffer for BLT operations to the VGA frame buffer
1710 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
1711 Status
= gBS
->AllocatePool (
1712 EfiBootServicesData
,
1714 (VOID
**) &BiosVideoPrivate
->VgaFrameBuffer
1716 if (EFI_ERROR (Status
)) {
1722 Regs
.X
.AX
= ModeData
->VbeModeNumber
;
1723 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1727 // Allocate a working buffer for BLT operations to the VBE frame buffer
1729 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
1730 Status
= gBS
->AllocatePool (
1731 EfiBootServicesData
,
1732 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
,
1733 (VOID
**) &BiosVideoPrivate
->VbeFrameBuffer
1735 if (EFI_ERROR (Status
)) {
1741 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1742 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1743 gBS
->SetMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
), 0);
1744 Regs
.E
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1745 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1747 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1750 // Check to see if the call succeeded
1752 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1753 return EFI_DEVICE_ERROR
;
1756 // Initialize the state of the VbeFrameBuffer
1758 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1759 BiosVideoPrivate
->PciIo
,
1760 EfiPciIoWidthUint32
,
1761 EFI_PCI_IO_PASS_THROUGH_BAR
,
1762 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
1763 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
1764 BiosVideoPrivate
->VbeFrameBuffer
1766 if (EFI_ERROR (Status
)) {
1771 This
->Mode
->Mode
= ModeNumber
;
1772 This
->Mode
->Info
->Version
= 0;
1773 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
1774 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
1775 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
1776 This
->Mode
->Info
->PixelInformation
= ModeData
->PixelBitMask
;
1777 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1778 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1781 // Frame BufferSize remain unchanged
1783 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ModeData
->LinearFrameBuffer
;
1784 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
1786 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
1793 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1796 @param PciIo - The pointer of EFI_PCI_IO_PROTOCOL
1797 @param VbeBuffer - The data to transfer to screen
1798 @param MemAddress - Physical frame buffer base address
1799 @param DestinationX - The X coordinate of the destination for BltOperation
1800 @param DestinationY - The Y coordinate of the destination for BltOperation
1801 @param TotalBytes - The total bytes of copy
1802 @param VbePixelWidth - Bytes per pixel
1803 @param BytesPerScanLine - Bytes per scan line
1810 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1811 IN UINT8
*VbeBuffer
,
1812 IN VOID
*MemAddress
,
1813 IN UINTN DestinationX
,
1814 IN UINTN DestinationY
,
1815 IN UINTN TotalBytes
,
1816 IN UINT32 VbePixelWidth
,
1817 IN UINTN BytesPerScanLine
1820 UINTN FrameBufferAddr
;
1822 UINTN RemainingBytes
;
1823 UINTN UnalignedBytes
;
1826 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1829 // If TotalBytes is less than 4 bytes, only start byte copy.
1831 if (TotalBytes
< 4) {
1832 Status
= PciIo
->Mem
.Write (
1835 EFI_PCI_IO_PASS_THROUGH_BAR
,
1836 (UINT64
) FrameBufferAddr
,
1840 ASSERT_EFI_ERROR (Status
);
1845 // If VbeBuffer is not 4-byte aligned, start byte copy.
1847 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1849 if (UnalignedBytes
!= 0) {
1850 Status
= PciIo
->Mem
.Write (
1853 EFI_PCI_IO_PASS_THROUGH_BAR
,
1854 (UINT64
) FrameBufferAddr
,
1858 ASSERT_EFI_ERROR (Status
);
1859 FrameBufferAddr
+= UnalignedBytes
;
1860 VbeBuffer
+= UnalignedBytes
;
1864 // Calculate 4-byte block count and remaining bytes.
1866 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1867 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1870 // Copy 4-byte block and remaining bytes to physical frame buffer.
1872 if (CopyBlockNum
!= 0) {
1873 Status
= PciIo
->Mem
.Write (
1875 EfiPciIoWidthUint32
,
1876 EFI_PCI_IO_PASS_THROUGH_BAR
,
1877 (UINT64
) FrameBufferAddr
,
1881 ASSERT_EFI_ERROR (Status
);
1884 if (RemainingBytes
!= 0) {
1885 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1886 VbeBuffer
+= (CopyBlockNum
<< 2);
1887 Status
= PciIo
->Mem
.Write (
1890 EFI_PCI_IO_PASS_THROUGH_BAR
,
1891 (UINT64
) FrameBufferAddr
,
1895 ASSERT_EFI_ERROR (Status
);
1900 // BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
1904 Graphics Output protocol instance to block transfer for VBE device
1907 @param This - Pointer to Graphics Output protocol instance
1908 @param BltBuffer - The data to transfer to screen
1909 @param BltOperation - The operation to perform
1910 @param SourceX - The X coordinate of the source for BltOperation
1911 @param SourceY - The Y coordinate of the source for BltOperation
1912 @param DestinationX - The X coordinate of the destination for BltOperation
1913 @param DestinationY - The Y coordinate of the destination for BltOperation
1914 @param Width - The width of a rectangle in the blt rectangle in pixels
1915 @param Height - The height of a rectangle in the blt rectangle in pixels
1916 @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
1917 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1918 If a subrectangle of the BltBuffer is used, then Delta represents
1919 the number of bytes in a row of the BltBuffer.
1921 @return EFI_INVALID_PARAMETER - Invalid parameter passed in
1922 EFI_SUCCESS - Blt operation success
1927 BiosVideoGraphicsOutputVbeBlt (
1928 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1929 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1930 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1933 IN UINTN DestinationX
,
1934 IN UINTN DestinationY
,
1940 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1941 BIOS_VIDEO_MODE_DATA
*Mode
;
1942 EFI_PCI_IO_PROTOCOL
*PciIo
;
1943 EFI_TPL OriginalTPL
;
1947 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1949 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1950 UINTN BytesPerScanLine
;
1955 UINT32 VbePixelWidth
;
1959 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1960 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
1961 PciIo
= BiosVideoPrivate
->PciIo
;
1963 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
1964 MemAddress
= Mode
->LinearFrameBuffer
;
1965 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1966 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1967 BltUint8
= (UINT8
*) BltBuffer
;
1968 TotalBytes
= Width
* VbePixelWidth
;
1970 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1971 return EFI_INVALID_PARAMETER
;
1974 if (Width
== 0 || Height
== 0) {
1975 return EFI_INVALID_PARAMETER
;
1978 // We need to fill the Virtual Screen buffer with the blt data.
1979 // The virtual screen is upside down, as the first row is the bootom row of
1982 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1984 // Video to BltBuffer: Source is Video, destination is BltBuffer
1986 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1987 return EFI_INVALID_PARAMETER
;
1990 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1991 return EFI_INVALID_PARAMETER
;
1995 // BltBuffer to Video: Source is BltBuffer, destination is Video
1997 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1998 return EFI_INVALID_PARAMETER
;
2001 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
2002 return EFI_INVALID_PARAMETER
;
2006 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2007 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2008 // the number of bytes in each row can be computed.
2011 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2014 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2015 // We would not want a timer based event (Cursor, ...) to come in while we are
2016 // doing this operation.
2018 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2020 switch (BltOperation
) {
2021 case EfiBltVideoToBltBuffer
:
2022 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
2023 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2025 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
2027 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
2028 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2029 Pixel
= *(UINT32
*) (VbeBuffer
);
2030 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
2031 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
2032 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
2035 VbeBuffer
+= VbePixelWidth
;
2041 case EfiBltVideoToVideo
:
2042 for (Index
= 0; Index
< Height
; Index
++) {
2043 if (DestinationY
<= SourceY
) {
2044 SrcY
= SourceY
+ Index
;
2045 DstY
= DestinationY
+ Index
;
2047 SrcY
= SourceY
+ Height
- Index
- 1;
2048 DstY
= DestinationY
+ Height
- Index
- 1;
2051 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2052 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2061 // Update physical frame buffer.
2076 case EfiBltVideoFill
:
2077 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2078 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2080 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2082 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2084 (Blt
->Green
& Mode
->Green
.Mask
) <<
2085 Mode
->Green
.Position
2087 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2089 for (Index
= 0; Index
< Width
; Index
++) {
2095 VbeBuffer
+= VbePixelWidth
;
2098 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2099 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2101 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2106 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2108 // Update physical frame buffer.
2123 case EfiBltBufferToVideo
:
2124 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2125 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2126 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2127 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2129 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2131 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2132 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2133 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2140 VbeBuffer
+= VbePixelWidth
;
2143 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2146 // Update physical frame buffer.
2164 gBS
->RestoreTPL (OriginalTPL
);
2171 Write graphics controller registers
2174 @param PciIo - Pointer to PciIo protocol instance of the controller
2175 @param Address - Register address
2176 @param Data - Data to be written to register
2183 WriteGraphicsController (
2184 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2189 Address
= Address
| (Data
<< 8);
2192 EfiPciIoWidthUint16
,
2193 EFI_PCI_IO_PASS_THROUGH_BAR
,
2194 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2202 Read the four bit plane of VGA frame buffer
2205 @param PciIo - Pointer to PciIo protocol instance of the controller
2206 @param HardwareBuffer - Hardware VGA frame buffer address
2207 @param MemoryBuffer - Memory buffer address
2208 @param WidthInBytes - Number of bytes in a line to read
2209 @param Height - Height of the area to read
2216 EFI_PCI_IO_PROTOCOL
*PciIo
,
2217 UINT8
*HardwareBuffer
,
2218 UINT8
*MemoryBuffer
,
2225 UINTN FrameBufferOffset
;
2230 // Program the Mode Register Write mode 0, Read mode 0
2232 WriteGraphicsController (
2234 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2235 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2238 for (BitPlane
= 0, FrameBufferOffset
= 0;
2239 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2240 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2243 // Program the Read Map Select Register to select the correct bit plane
2245 WriteGraphicsController (
2247 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2251 Source
= HardwareBuffer
;
2252 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2254 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2258 (UINT8
) EFI_PCI_IO_PASS_THROUGH_BAR
,
2259 (UINT64
)(UINTN
) Source
,
2261 (VOID
*) Destination
2269 Internal routine to convert VGA color to Grahpics Output color
2272 @param MemoryBuffer - Buffer containing VGA color
2273 @param X - The X coordinate of pixel on screen
2274 @param Y - The Y coordinate of pixel on screen
2275 @param BltBuffer - Buffer to contain converted Grahpics Output color
2281 VgaConvertToGraphicsOutputColor (
2282 UINT8
*MemoryBuffer
,
2285 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2292 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
2293 Mask
= mVgaBitMaskTable
[X
& 0x07];
2294 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2295 if (*MemoryBuffer
& Mask
) {
2300 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2305 Internal routine to convert Grahpics Output color to VGA color
2308 @param BltBuffer - buffer containing Grahpics Output color
2310 @return Converted VGA color
2315 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2320 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2321 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2329 Grahpics Output protocol instance to block transfer for VGA device
2331 @param This Pointer to Grahpics Output protocol instance
2332 @param BltBuffer The data to transfer to screen
2333 @param BltOperation The operation to perform
2334 @param SourceX The X coordinate of the source for BltOperation
2335 @param SourceY The Y coordinate of the source for BltOperation
2336 @param DestinationX The X coordinate of the destination for BltOperation
2337 @param DestinationY The Y coordinate of the destination for BltOperation
2338 @param Width The width of a rectangle in the blt rectangle in pixels
2339 @param Height The height of a rectangle in the blt rectangle in pixels
2340 @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
2341 If a Delta of 0 is used, the entire BltBuffer will be operated on.
2342 If a subrectangle of the BltBuffer is used, then Delta represents
2343 the number of bytes in a row of the BltBuffer.
2345 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2346 @retval EFI_SUCCESS Blt operation success
2351 BiosVideoGraphicsOutputVgaBlt (
2352 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2353 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2354 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2357 IN UINTN DestinationX
,
2358 IN UINTN DestinationY
,
2364 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2365 EFI_TPL OriginalTPL
;
2367 UINTN BytesPerScanLine
;
2368 //UINTN BytesPerBitPlane;
2380 UINT8
*SourceAddress
;
2381 UINT8
*DestinationAddress
;
2382 EFI_PCI_IO_PROTOCOL
*PciIo
;
2385 UINT8
*VgaFrameBuffer
;
2394 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2396 CurrentMode
= This
->Mode
->Mode
;
2397 PciIo
= BiosVideoPrivate
->PciIo
;
2398 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2399 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2400 //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;
2401 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2403 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2404 return EFI_INVALID_PARAMETER
;
2407 if (Width
== 0 || Height
== 0) {
2408 return EFI_INVALID_PARAMETER
;
2411 // We need to fill the Virtual Screen buffer with the blt data.
2412 // The virtual screen is upside down, as the first row is the bootom row of
2415 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2417 // Video to BltBuffer: Source is Video, destination is BltBuffer
2419 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2420 return EFI_INVALID_PARAMETER
;
2423 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2424 return EFI_INVALID_PARAMETER
;
2428 // BltBuffer to Video: Source is BltBuffer, destination is Video
2430 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2431 return EFI_INVALID_PARAMETER
;
2434 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2435 return EFI_INVALID_PARAMETER
;
2439 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2440 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2441 // the number of bytes in each row can be computed.
2444 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2447 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2448 // We would not want a timer based event (Cursor, ...) to come in while we are
2449 // doing this operation.
2451 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2454 // Compute some values we need for VGA
2456 switch (BltOperation
) {
2457 case EfiBltVideoToBltBuffer
:
2459 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2460 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2463 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2467 MemAddress
+ SourceOffset
,
2468 VgaFrameBuffer
+ SourceOffset
,
2474 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2476 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2477 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2478 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2479 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2487 case EfiBltVideoToVideo
:
2489 // Check for an aligned Video to Video operation
2491 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2493 // Program the Mode Register Write mode 1, Read mode 0
2495 WriteGraphicsController (
2497 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2498 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2501 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2502 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2504 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2508 EFI_PCI_IO_PASS_THROUGH_BAR
,
2509 (UINT64
) ((UINTN
)DestinationAddress
+ Offset
),
2510 EFI_PCI_IO_PASS_THROUGH_BAR
,
2511 (UINT64
) ((UINTN
)SourceAddress
+ Offset
),
2516 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2517 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2520 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2524 MemAddress
+ SourceOffset
,
2525 VgaFrameBuffer
+ SourceOffset
,
2533 case EfiBltVideoFill
:
2534 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2535 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2536 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2537 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2539 LeftMask
= (UINT8
) (LeftMask
& RightMask
);
2543 if (LeftMask
== 0xff) {
2549 if (RightMask
== 0xff) {
2554 PixelColor
= VgaConvertColor (BltBuffer
);
2557 // Program the Mode Register Write mode 2, Read mode 0
2559 WriteGraphicsController (
2561 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2562 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2566 // Program the Data Rotate/Function Select Register to replace
2568 WriteGraphicsController (
2570 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2571 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2574 if (LeftMask
!= 0) {
2576 // Program the BitMask register with the Left column mask
2578 WriteGraphicsController (
2580 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2584 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2586 // Read data from the bit planes into the latches
2591 EFI_PCI_IO_PASS_THROUGH_BAR
,
2597 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2602 EFI_PCI_IO_PASS_THROUGH_BAR
,
2612 // Program the BitMask register with the middle column mask of 0xff
2614 WriteGraphicsController (
2616 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2620 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2623 EfiPciIoWidthFillUint8
,
2624 EFI_PCI_IO_PASS_THROUGH_BAR
,
2632 if (RightMask
!= 0) {
2634 // Program the BitMask register with the Right column mask
2636 WriteGraphicsController (
2638 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2642 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2644 // Read data from the bit planes into the latches
2649 EFI_PCI_IO_PASS_THROUGH_BAR
,
2655 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2660 EFI_PCI_IO_PASS_THROUGH_BAR
,
2669 case EfiBltBufferToVideo
:
2670 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2671 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2674 // Program the Mode Register Write mode 2, Read mode 0
2676 WriteGraphicsController (
2678 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2679 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2683 // Program the Data Rotate/Function Select Register to replace
2685 WriteGraphicsController (
2687 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2688 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2691 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2692 for (Index1
= 0; Index1
< Width
; Index1
++) {
2693 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2695 AddressFix
= Address
;
2697 for (Bit
= 0; Bit
< 8; Bit
++) {
2699 // Program the BitMask register with the Left column mask
2701 WriteGraphicsController (
2703 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2707 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2709 // Read data from the bit planes into the latches
2714 EFI_PCI_IO_PASS_THROUGH_BAR
,
2715 (UINT64
)(UINTN
) Address1
,
2723 EFI_PCI_IO_PASS_THROUGH_BAR
,
2724 (UINT64
)(UINTN
) Address1
,
2726 &BiosVideoPrivate
->LineBuffer
[Index1
]
2730 LeftMask
= (UINT8
) (LeftMask
>> 1);
2731 if (LeftMask
== 0) {
2743 gBS
->RestoreTPL (OriginalTPL
);
2748 // VGA Mini Port Protocol Functions
2751 VgaMiniPort protocol interface to set mode
2753 @param This Pointer to VgaMiniPort protocol instance
2754 @param ModeNumber The index of the mode
2756 @retval EFI_UNSUPPORTED The requested mode is not supported
2757 @retval EFI_SUCCESS The requested mode is set successfully
2762 BiosVideoVgaMiniPortSetMode (
2763 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2767 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2768 IA32_REGISTER_SET Regs
;
2771 return EFI_INVALID_PARAMETER
;
2775 // Make sure the ModeNumber is a valid value
2777 if (ModeNumber
>= This
->MaxMode
) {
2778 return EFI_UNSUPPORTED
;
2781 // Get the device structure for this device
2783 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2785 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2787 switch (ModeNumber
) {
2790 // Set the 80x25 Text VGA Mode
2794 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2799 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2805 // Set the 80x50 Text VGA Mode
2809 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2814 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2818 return EFI_UNSUPPORTED
;