3 BiosVideo driver produce EFI_GRAPHIC_OUTPUT_PROTOCOL via LegacyBios Video rom.
5 Copyright (c) 2006 - 2008, 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
),
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 EFI_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
= 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
= BufferIndex
[0] * 8 + 248;
894 AspectRatio
= BufferIndex
[1] >> 6;
895 switch (AspectRatio
) {
897 VerticalResolution
= HorizontalResolution
/ 16 * 10;
900 VerticalResolution
= HorizontalResolution
/ 4 * 3;
903 VerticalResolution
= HorizontalResolution
/ 5 * 4;
906 VerticalResolution
= HorizontalResolution
/ 16 * 9;
909 VerticalResolution
= HorizontalResolution
/ 4 * 3;
912 RefreshRate
= (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 EFI_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 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1092 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1093 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1094 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1095 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1096 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1098 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1100 Status
= EFI_DEVICE_ERROR
;
1103 // See if the VESA call succeeded
1105 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1109 // Check for 'VESA' signature
1111 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1115 // Check to see if this is VBE 2.0 or higher
1117 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1122 // Read EDID information
1124 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1125 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1129 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1130 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1132 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1135 // See if the VESA call succeeded
1138 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1140 // Parse EDID data structure to retrieve modes supported by monitor
1142 if (ParseEdidData ((UINT8
*) BiosVideoPrivate
->VbeEdidDataBlock
, &ValidEdidTiming
) == TRUE
) {
1145 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1146 Status
= gBS
->AllocatePool (
1147 EfiBootServicesData
,
1148 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1149 &BiosVideoPrivate
->EdidDiscovered
.Edid
1151 if (EFI_ERROR (Status
)) {
1155 BiosVideoPrivate
->EdidDiscovered
.Edid
,
1156 BiosVideoPrivate
->VbeEdidDataBlock
,
1157 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1160 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1161 Status
= gBS
->AllocatePool (
1162 EfiBootServicesData
,
1163 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1164 &BiosVideoPrivate
->EdidActive
.Edid
1166 if (EFI_ERROR (Status
)) {
1170 BiosVideoPrivate
->EdidActive
.Edid
,
1171 BiosVideoPrivate
->VbeEdidDataBlock
,
1172 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1175 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
1176 BiosVideoPrivate
->EdidDiscovered
.Edid
= NULL
;
1178 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1179 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1184 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1186 ModeNumberPtr
= (UINT16
*)
1188 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1189 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1195 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
1197 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1199 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1203 // Get the information about the mode
1205 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1206 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1207 Regs
.X
.CX
= *ModeNumberPtr
;
1208 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1209 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1210 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1212 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1215 // See if the call succeeded. If it didn't, then try the next mode.
1217 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1221 // See if the mode supports color. If it doesn't then try the next mode.
1223 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1227 // See if the mode supports graphics. If it doesn't then try the next mode.
1229 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1233 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1235 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1239 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1240 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1241 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1243 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1247 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1251 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1255 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1257 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1261 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1263 // EDID exist, check whether this mode match with any mode in EDID
1265 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1266 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1267 if (SearchEdidTiming (&ValidEdidTiming
, &Timing
) == FALSE
) {
1273 // Select a reasonable mode to be set for current display mode
1277 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1278 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1282 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1283 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1286 PreferMode
= ModeNumber
;
1288 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1289 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1293 if ((!EdidFound
) && (!ModeFound
)) {
1295 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1301 // Add mode to the list of available modes
1304 Status
= gBS
->AllocatePool (
1305 EfiBootServicesData
,
1306 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
),
1307 (VOID
**) &ModeBuffer
1309 if (EFI_ERROR (Status
)) {
1313 if (ModeNumber
> 1) {
1316 BiosVideoPrivate
->ModeData
,
1317 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1321 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1322 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1325 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1326 CurrentModeData
->VbeModeNumber
= *ModeNumberPtr
;
1327 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1328 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1329 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1330 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1331 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1332 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1333 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1334 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1335 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1336 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1338 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1339 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1340 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1341 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1342 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1343 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1344 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1345 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1346 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1348 CurrentModeData
->PixelFormat
= PixelBitMask
;
1349 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1350 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1351 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1352 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1353 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1354 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1357 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1358 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1359 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1360 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1362 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1363 CurrentModeData
->FrameBufferSize
= BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024;
1364 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1365 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1367 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1369 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1372 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1374 if (ModeNumber
== 0) {
1375 Status
= EFI_DEVICE_ERROR
;
1380 // Allocate buffer for Graphics Output Protocol mode information
1382 Status
= gBS
->AllocatePool (
1383 EfiBootServicesData
,
1384 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1385 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1387 if (EFI_ERROR (Status
)) {
1390 GraphicsOutputMode
= BiosVideoPrivate
->GraphicsOutput
.Mode
;
1391 Status
= gBS
->AllocatePool (
1392 EfiBootServicesData
,
1393 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1394 (VOID
**) &GraphicsOutputMode
->Info
1396 if (EFI_ERROR (Status
)) {
1400 GraphicsOutputMode
->MaxMode
= (UINT32
) ModeNumber
;
1402 // Current mode is unknow till now, set it to an invalid mode.
1404 GraphicsOutputMode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1407 // Find the best mode to initialize
1409 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1410 if (EFI_ERROR (Status
)) {
1411 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1412 Status
= BiosVideoGraphicsOutputSetMode (
1413 &BiosVideoPrivate
->GraphicsOutput
,
1416 if (!EFI_ERROR (Status
)) {
1420 if (PreferMode
== ModeNumber
) {
1422 // None mode is set successfully.
1430 // If there was an error, then free the mode structure
1432 if (EFI_ERROR (Status
)) {
1433 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1434 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1436 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1437 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1438 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1440 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1448 Check for VGA device
1450 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1452 @retval EFI_SUCCESS Standard VGA device found
1456 BiosVideoCheckForVga (
1457 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1461 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1464 // Fill in the Graphics Output Protocol
1466 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1467 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1468 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1471 // Allocate buffer for Graphics Output Protocol mode information
1473 Status
= gBS
->AllocatePool (
1474 EfiBootServicesData
,
1475 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1476 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1478 if (EFI_ERROR (Status
)) {
1481 Status
= gBS
->AllocatePool (
1482 EfiBootServicesData
,
1483 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1484 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
1486 if (EFI_ERROR (Status
)) {
1491 // Add mode to the list of available modes
1493 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1495 Status
= gBS
->AllocatePool (
1496 EfiBootServicesData
,
1497 sizeof (BIOS_VIDEO_MODE_DATA
),
1498 (VOID
**) &ModeBuffer
1500 if (EFI_ERROR (Status
)) {
1504 ModeBuffer
->VbeModeNumber
= 0x0012;
1505 ModeBuffer
->BytesPerScanLine
= 640;
1506 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1507 ModeBuffer
->FrameBufferSize
= 0;
1508 ModeBuffer
->HorizontalResolution
= 640;
1509 ModeBuffer
->VerticalResolution
= 480;
1510 ModeBuffer
->BitsPerPixel
= 8;
1511 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1513 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1516 // Test to see if the Video Adapter support the 640x480 16 color mode
1518 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1519 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1523 // If there was an error, then free the mode structure
1525 if (EFI_ERROR (Status
)) {
1526 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1527 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1529 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1530 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1531 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1533 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1539 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1543 Graphics Output protocol interface to get video mode
1546 @param This - Protocol instance pointer.
1547 @param ModeNumber - The mode number to return information on.
1548 @param SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
1549 @param Info - Caller allocated buffer that returns information about ModeNumber.
1551 @return EFI_SUCCESS - Mode information returned.
1552 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
1553 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
1554 EFI_INVALID_PARAMETER - One of the input args was NULL.
1559 BiosVideoGraphicsOutputQueryMode (
1560 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1561 IN UINT32 ModeNumber
,
1562 OUT UINTN
*SizeOfInfo
,
1563 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1566 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1568 BIOS_VIDEO_MODE_DATA
*ModeData
;
1570 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1572 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1573 return EFI_NOT_STARTED
;
1576 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1577 return EFI_INVALID_PARAMETER
;
1580 Status
= gBS
->AllocatePool (
1581 EfiBootServicesData
,
1582 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1585 if (EFI_ERROR (Status
)) {
1589 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1591 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1592 (*Info
)->Version
= 0;
1593 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1594 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1595 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1596 (*Info
)->PixelInformation
= ModeData
->PixelBitMask
;
1598 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1605 Graphics Output protocol interface to set video mode
1608 @param This - Protocol instance pointer.
1609 @param ModeNumber - The mode number to be set.
1611 @return EFI_SUCCESS - Graphics mode was changed.
1612 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
1613 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
1618 BiosVideoGraphicsOutputSetMode (
1619 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1620 IN UINT32 ModeNumber
1624 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1625 EFI_IA32_REGISTER_SET Regs
;
1626 BIOS_VIDEO_MODE_DATA
*ModeData
;
1628 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1631 return EFI_INVALID_PARAMETER
;
1634 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1635 return EFI_UNSUPPORTED
;
1638 if (ModeNumber
== This
->Mode
->Mode
) {
1642 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1644 if (BiosVideoPrivate
->LineBuffer
) {
1645 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
1648 if (BiosVideoPrivate
->VgaFrameBuffer
) {
1649 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1652 if (BiosVideoPrivate
->VbeFrameBuffer
) {
1653 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1656 BiosVideoPrivate
->LineBuffer
= NULL
;
1657 Status
= gBS
->AllocatePool (
1658 EfiBootServicesData
,
1659 ModeData
->BytesPerScanLine
,
1660 &BiosVideoPrivate
->LineBuffer
1662 if (EFI_ERROR (Status
)) {
1666 // Clear all registers
1668 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1670 if (ModeData
->VbeModeNumber
< 0x100) {
1672 // Allocate a working buffer for BLT operations to the VGA frame buffer
1674 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
1675 Status
= gBS
->AllocatePool (
1676 EfiBootServicesData
,
1678 &BiosVideoPrivate
->VgaFrameBuffer
1680 if (EFI_ERROR (Status
)) {
1686 Regs
.X
.AX
= ModeData
->VbeModeNumber
;
1687 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1691 // Allocate a working buffer for BLT operations to the VBE frame buffer
1693 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
1694 Status
= gBS
->AllocatePool (
1695 EfiBootServicesData
,
1696 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
,
1697 &BiosVideoPrivate
->VbeFrameBuffer
1699 if (EFI_ERROR (Status
)) {
1705 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1706 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1707 gBS
->SetMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
), 0);
1708 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1709 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1710 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1713 // Check to see if the call succeeded
1715 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1716 return EFI_DEVICE_ERROR
;
1719 // Initialize the state of the VbeFrameBuffer
1721 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1722 BiosVideoPrivate
->PciIo
,
1723 EfiPciIoWidthUint32
,
1724 EFI_PCI_IO_PASS_THROUGH_BAR
,
1725 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
1726 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
1727 BiosVideoPrivate
->VbeFrameBuffer
1729 if (EFI_ERROR (Status
)) {
1734 This
->Mode
->Mode
= ModeNumber
;
1735 This
->Mode
->Info
->Version
= 0;
1736 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
1737 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
1738 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
1739 This
->Mode
->Info
->PixelInformation
= ModeData
->PixelBitMask
;
1740 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1741 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1744 // Frame BufferSize remain unchanged
1746 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
) ModeData
->LinearFrameBuffer
;
1747 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
1749 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
1756 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1759 @param PciIo - The pointer of EFI_PCI_IO_PROTOCOL
1760 @param VbeBuffer - The data to transfer to screen
1761 @param MemAddress - Physical frame buffer base address
1762 @param DestinationX - The X coordinate of the destination for BltOperation
1763 @param DestinationY - The Y coordinate of the destination for BltOperation
1764 @param TotalBytes - The total bytes of copy
1765 @param VbePixelWidth - Bytes per pixel
1766 @param BytesPerScanLine - Bytes per scan line
1773 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1774 IN UINT8
*VbeBuffer
,
1775 IN VOID
*MemAddress
,
1776 IN UINTN DestinationX
,
1777 IN UINTN DestinationY
,
1778 IN UINTN TotalBytes
,
1779 IN UINT32 VbePixelWidth
,
1780 IN UINTN BytesPerScanLine
1783 UINTN FrameBufferAddr
;
1785 UINTN RemainingBytes
;
1786 UINTN UnalignedBytes
;
1789 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1792 // If TotalBytes is less than 4 bytes, only start byte copy.
1794 if (TotalBytes
< 4) {
1795 Status
= PciIo
->Mem
.Write (
1798 EFI_PCI_IO_PASS_THROUGH_BAR
,
1799 (UINT64
) FrameBufferAddr
,
1803 ASSERT_EFI_ERROR (Status
);
1808 // If VbeBuffer is not 4-byte aligned, start byte copy.
1810 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1812 if (UnalignedBytes
!= 0) {
1813 Status
= PciIo
->Mem
.Write (
1816 EFI_PCI_IO_PASS_THROUGH_BAR
,
1817 (UINT64
) FrameBufferAddr
,
1821 ASSERT_EFI_ERROR (Status
);
1822 FrameBufferAddr
+= UnalignedBytes
;
1823 VbeBuffer
+= UnalignedBytes
;
1827 // Calculate 4-byte block count and remaining bytes.
1829 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1830 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1833 // Copy 4-byte block and remaining bytes to physical frame buffer.
1835 if (CopyBlockNum
!= 0) {
1836 Status
= PciIo
->Mem
.Write (
1838 EfiPciIoWidthUint32
,
1839 EFI_PCI_IO_PASS_THROUGH_BAR
,
1840 (UINT64
) FrameBufferAddr
,
1844 ASSERT_EFI_ERROR (Status
);
1847 if (RemainingBytes
!= 0) {
1848 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1849 VbeBuffer
+= (CopyBlockNum
<< 2);
1850 Status
= PciIo
->Mem
.Write (
1853 EFI_PCI_IO_PASS_THROUGH_BAR
,
1854 (UINT64
) FrameBufferAddr
,
1858 ASSERT_EFI_ERROR (Status
);
1863 // BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
1867 Graphics Output protocol instance to block transfer for VBE device
1870 @param This - Pointer to Graphics Output protocol instance
1871 @param BltBuffer - The data to transfer to screen
1872 @param BltOperation - The operation to perform
1873 @param SourceX - The X coordinate of the source for BltOperation
1874 @param SourceY - The Y coordinate of the source for BltOperation
1875 @param DestinationX - The X coordinate of the destination for BltOperation
1876 @param DestinationY - The Y coordinate of the destination for BltOperation
1877 @param Width - The width of a rectangle in the blt rectangle in pixels
1878 @param Height - The height of a rectangle in the blt rectangle in pixels
1879 @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
1880 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1881 If a subrectangle of the BltBuffer is used, then Delta represents
1882 the number of bytes in a row of the BltBuffer.
1884 @return EFI_INVALID_PARAMETER - Invalid parameter passed in
1885 EFI_SUCCESS - Blt operation success
1890 BiosVideoGraphicsOutputVbeBlt (
1891 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1892 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1893 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1896 IN UINTN DestinationX
,
1897 IN UINTN DestinationY
,
1903 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1904 BIOS_VIDEO_MODE_DATA
*Mode
;
1905 EFI_PCI_IO_PROTOCOL
*PciIo
;
1906 EFI_TPL OriginalTPL
;
1910 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1912 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1913 UINTN BytesPerScanLine
;
1918 UINT32 VbePixelWidth
;
1922 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1923 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
1924 PciIo
= BiosVideoPrivate
->PciIo
;
1926 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
1927 MemAddress
= Mode
->LinearFrameBuffer
;
1928 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1929 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1930 BltUint8
= (UINT8
*) BltBuffer
;
1931 TotalBytes
= Width
* VbePixelWidth
;
1933 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1934 return EFI_INVALID_PARAMETER
;
1937 if (Width
== 0 || Height
== 0) {
1938 return EFI_INVALID_PARAMETER
;
1941 // We need to fill the Virtual Screen buffer with the blt data.
1942 // The virtual screen is upside down, as the first row is the bootom row of
1945 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1947 // Video to BltBuffer: Source is Video, destination is BltBuffer
1949 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1950 return EFI_INVALID_PARAMETER
;
1953 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1954 return EFI_INVALID_PARAMETER
;
1958 // BltBuffer to Video: Source is BltBuffer, destination is Video
1960 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1961 return EFI_INVALID_PARAMETER
;
1964 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1965 return EFI_INVALID_PARAMETER
;
1969 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1970 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1971 // the number of bytes in each row can be computed.
1974 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1977 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1978 // We would not want a timer based event (Cursor, ...) to come in while we are
1979 // doing this operation.
1981 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1983 switch (BltOperation
) {
1984 case EfiBltVideoToBltBuffer
:
1985 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1986 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
1988 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
1990 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1991 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1992 Pixel
= *(UINT32
*) (VbeBuffer
);
1993 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1994 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1995 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1998 VbeBuffer
+= VbePixelWidth
;
2004 case EfiBltVideoToVideo
:
2005 for (Index
= 0; Index
< Height
; Index
++) {
2006 if (DestinationY
<= SourceY
) {
2007 SrcY
= SourceY
+ Index
;
2008 DstY
= DestinationY
+ Index
;
2010 SrcY
= SourceY
+ Height
- Index
- 1;
2011 DstY
= DestinationY
+ Height
- Index
- 1;
2014 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2015 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2024 // Update physical frame buffer.
2039 case EfiBltVideoFill
:
2040 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2041 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2043 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2045 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2047 (Blt
->Green
& Mode
->Green
.Mask
) <<
2048 Mode
->Green
.Position
2050 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2052 for (Index
= 0; Index
< Width
; Index
++) {
2058 VbeBuffer
+= VbePixelWidth
;
2061 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2062 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2064 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2069 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2071 // Update physical frame buffer.
2086 case EfiBltBufferToVideo
:
2087 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2088 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2089 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2090 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2092 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2094 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2095 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2096 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2103 VbeBuffer
+= VbePixelWidth
;
2106 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2109 // Update physical frame buffer.
2125 gBS
->RestoreTPL (OriginalTPL
);
2132 Write graphics controller registers
2135 @param PciIo - Pointer to PciIo protocol instance of the controller
2136 @param Address - Register address
2137 @param Data - Data to be written to register
2144 WriteGraphicsController (
2145 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2150 Address
= Address
| (Data
<< 8);
2153 EfiPciIoWidthUint16
,
2154 EFI_PCI_IO_PASS_THROUGH_BAR
,
2155 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2163 Read the four bit plane of VGA frame buffer
2166 @param PciIo - Pointer to PciIo protocol instance of the controller
2167 @param HardwareBuffer - Hardware VGA frame buffer address
2168 @param MemoryBuffer - Memory buffer address
2169 @param WidthInBytes - Number of bytes in a line to read
2170 @param Height - Height of the area to read
2177 EFI_PCI_IO_PROTOCOL
*PciIo
,
2178 UINT8
*HardwareBuffer
,
2179 UINT8
*MemoryBuffer
,
2186 UINTN FrameBufferOffset
;
2191 // Program the Mode Register Write mode 0, Read mode 0
2193 WriteGraphicsController (
2195 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2196 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2199 for (BitPlane
= 0, FrameBufferOffset
= 0;
2200 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2201 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2204 // Program the Read Map Select Register to select the correct bit plane
2206 WriteGraphicsController (
2208 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2212 Source
= HardwareBuffer
;
2213 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2215 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2219 EFI_PCI_IO_PASS_THROUGH_BAR
,
2222 (VOID
*) Destination
2230 Internal routine to convert VGA color to Grahpics Output color
2233 @param MemoryBuffer - Buffer containing VGA color
2234 @param X - The X coordinate of pixel on screen
2235 @param Y - The Y coordinate of pixel on screen
2236 @param BltBuffer - Buffer to contain converted Grahpics Output color
2242 VgaConvertToGraphicsOutputColor (
2243 UINT8
*MemoryBuffer
,
2246 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2253 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
2254 Mask
= mVgaBitMaskTable
[X
& 0x07];
2255 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2256 if (*MemoryBuffer
& Mask
) {
2261 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2266 Internal routine to convert Grahpics Output color to VGA color
2269 @param BltBuffer - buffer containing Grahpics Output color
2271 @return Converted VGA color
2276 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2281 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2282 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2290 Grahpics Output protocol instance to block transfer for VGA device
2292 @param This Pointer to Grahpics Output protocol instance
2293 @param BltBuffer The data to transfer to screen
2294 @param BltOperation The operation to perform
2295 @param SourceX The X coordinate of the source for BltOperation
2296 @param SourceY The Y coordinate of the source for BltOperation
2297 @param DestinationX The X coordinate of the destination for BltOperation
2298 @param DestinationY The Y coordinate of the destination for BltOperation
2299 @param Width The width of a rectangle in the blt rectangle in pixels
2300 @param Height The height of a rectangle in the blt rectangle in pixels
2301 @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
2302 If a Delta of 0 is used, the entire BltBuffer will be operated on.
2303 If a subrectangle of the BltBuffer is used, then Delta represents
2304 the number of bytes in a row of the BltBuffer.
2306 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2307 @retval EFI_SUCCESS Blt operation success
2312 BiosVideoGraphicsOutputVgaBlt (
2313 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2314 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2315 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2318 IN UINTN DestinationX
,
2319 IN UINTN DestinationY
,
2325 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2326 EFI_TPL OriginalTPL
;
2328 UINTN BytesPerScanLine
;
2329 UINTN BytesPerBitPlane
;
2341 UINT8
*SourceAddress
;
2342 UINT8
*DestinationAddress
;
2343 EFI_PCI_IO_PROTOCOL
*PciIo
;
2346 UINT8
*VgaFrameBuffer
;
2355 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2357 CurrentMode
= This
->Mode
->Mode
;
2358 PciIo
= BiosVideoPrivate
->PciIo
;
2359 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2360 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2361 BytesPerBitPlane
= BytesPerScanLine
* BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
;
2362 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2364 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2365 return EFI_INVALID_PARAMETER
;
2368 if (Width
== 0 || Height
== 0) {
2369 return EFI_INVALID_PARAMETER
;
2372 // We need to fill the Virtual Screen buffer with the blt data.
2373 // The virtual screen is upside down, as the first row is the bootom row of
2376 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2378 // Video to BltBuffer: Source is Video, destination is BltBuffer
2380 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2381 return EFI_INVALID_PARAMETER
;
2384 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2385 return EFI_INVALID_PARAMETER
;
2389 // BltBuffer to Video: Source is BltBuffer, destination is Video
2391 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2392 return EFI_INVALID_PARAMETER
;
2395 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2396 return EFI_INVALID_PARAMETER
;
2400 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2401 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2402 // the number of bytes in each row can be computed.
2405 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2408 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2409 // We would not want a timer based event (Cursor, ...) to come in while we are
2410 // doing this operation.
2412 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2415 // Compute some values we need for VGA
2417 switch (BltOperation
) {
2418 case EfiBltVideoToBltBuffer
:
2420 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2421 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2424 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2428 MemAddress
+ SourceOffset
,
2429 VgaFrameBuffer
+ SourceOffset
,
2435 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2437 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2438 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2439 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2440 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2448 case EfiBltVideoToVideo
:
2450 // Check for an aligned Video to Video operation
2452 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2454 // Program the Mode Register Write mode 1, Read mode 0
2456 WriteGraphicsController (
2458 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2459 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2462 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2463 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2465 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2469 EFI_PCI_IO_PASS_THROUGH_BAR
,
2470 (UINT64
) (DestinationAddress
+ Offset
),
2471 EFI_PCI_IO_PASS_THROUGH_BAR
,
2472 (UINT64
) (SourceAddress
+ Offset
),
2477 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2478 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2481 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2485 MemAddress
+ SourceOffset
,
2486 VgaFrameBuffer
+ SourceOffset
,
2494 case EfiBltVideoFill
:
2495 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2496 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2497 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2498 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2500 LeftMask
&= RightMask
;
2504 if (LeftMask
== 0xff) {
2510 if (RightMask
== 0xff) {
2515 PixelColor
= VgaConvertColor (BltBuffer
);
2518 // Program the Mode Register Write mode 2, Read mode 0
2520 WriteGraphicsController (
2522 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2523 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2527 // Program the Data Rotate/Function Select Register to replace
2529 WriteGraphicsController (
2531 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2532 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2535 if (LeftMask
!= 0) {
2537 // Program the BitMask register with the Left column mask
2539 WriteGraphicsController (
2541 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2545 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2547 // Read data from the bit planes into the latches
2552 EFI_PCI_IO_PASS_THROUGH_BAR
,
2558 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2563 EFI_PCI_IO_PASS_THROUGH_BAR
,
2573 // Program the BitMask register with the middle column mask of 0xff
2575 WriteGraphicsController (
2577 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2581 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2584 EfiPciIoWidthFillUint8
,
2585 EFI_PCI_IO_PASS_THROUGH_BAR
,
2593 if (RightMask
!= 0) {
2595 // Program the BitMask register with the Right column mask
2597 WriteGraphicsController (
2599 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2603 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2605 // Read data from the bit planes into the latches
2610 EFI_PCI_IO_PASS_THROUGH_BAR
,
2616 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2621 EFI_PCI_IO_PASS_THROUGH_BAR
,
2630 case EfiBltBufferToVideo
:
2631 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2632 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2635 // Program the Mode Register Write mode 2, Read mode 0
2637 WriteGraphicsController (
2639 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2640 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2644 // Program the Data Rotate/Function Select Register to replace
2646 WriteGraphicsController (
2648 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2649 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2652 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2653 for (Index1
= 0; Index1
< Width
; Index1
++) {
2654 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2656 AddressFix
= Address
;
2658 for (Bit
= 0; Bit
< 8; Bit
++) {
2660 // Program the BitMask register with the Left column mask
2662 WriteGraphicsController (
2664 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2668 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2670 // Read data from the bit planes into the latches
2675 EFI_PCI_IO_PASS_THROUGH_BAR
,
2684 EFI_PCI_IO_PASS_THROUGH_BAR
,
2687 &BiosVideoPrivate
->LineBuffer
[Index1
]
2691 LeftMask
= (UINT8
) (LeftMask
>> 1);
2692 if (LeftMask
== 0) {
2702 gBS
->RestoreTPL (OriginalTPL
);
2707 // VGA Mini Port Protocol Functions
2710 VgaMiniPort protocol interface to set mode
2712 @param This Pointer to VgaMiniPort protocol instance
2713 @param ModeNumber The index of the mode
2715 @retval EFI_UNSUPPORTED The requested mode is not supported
2716 @retval EFI_SUCCESS The requested mode is set successfully
2721 BiosVideoVgaMiniPortSetMode (
2722 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2726 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2727 EFI_IA32_REGISTER_SET Regs
;
2730 return EFI_INVALID_PARAMETER
;
2734 // Make sure the ModeNumber is a valid value
2736 if (ModeNumber
>= This
->MaxMode
) {
2737 return EFI_UNSUPPORTED
;
2740 // Get the device structure for this device
2742 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2744 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2746 switch (ModeNumber
) {
2749 // Set the 80x25 Text VGA Mode
2753 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2758 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2764 // Set the 80x50 Text VGA Mode
2768 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2773 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2777 return EFI_UNSUPPORTED
;