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
),
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 DEBUG ((EFI_D_INFO
, "Before BiosVideoCheckForVga()\n"));
497 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
498 DEBUG ((EFI_D_INFO
, "Status BiosVideoCheckForVga(): %r\n", Status
));
501 if (EFI_ERROR (Status
)) {
503 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
504 // not produce the Graphics Output protocol. Instead, produce the VGA MiniPort Protocol.
506 BiosVideoPrivate
->ProduceGraphicsOutput
= FALSE
;
509 // INT services are available, so on the 80x25 and 80x50 text mode are supported
511 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
515 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
516 if (RemainingDevicePath
== NULL
) {
517 ZeroMem (&AcpiDeviceNode
, sizeof (ACPI_ADR_DEVICE_PATH
));
518 AcpiDeviceNode
.Header
.Type
= ACPI_DEVICE_PATH
;
519 AcpiDeviceNode
.Header
.SubType
= ACPI_ADR_DP
;
520 AcpiDeviceNode
.ADR
= ACPI_DISPLAY_ADR (1, 0, 0, 1, 0, ACPI_ADR_DISPLAY_TYPE_VGA
, 0, 0);
521 SetDevicePathNodeLength (&AcpiDeviceNode
.Header
, sizeof (ACPI_ADR_DEVICE_PATH
));
523 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (
525 (EFI_DEVICE_PATH_PROTOCOL
*) &AcpiDeviceNode
528 BiosVideoPrivate
->DevicePath
= AppendDevicePathNode (ParentDevicePath
, RemainingDevicePath
);
532 // Creat child handle and install Graphics Output Protocol,EDID Discovered/Active Protocol
534 Status
= gBS
->InstallMultipleProtocolInterfaces (
535 &BiosVideoPrivate
->Handle
,
536 &gEfiDevicePathProtocolGuid
,
537 BiosVideoPrivate
->DevicePath
,
538 &gEfiGraphicsOutputProtocolGuid
,
539 &BiosVideoPrivate
->GraphicsOutput
,
540 &gEfiEdidDiscoveredProtocolGuid
,
541 &BiosVideoPrivate
->EdidDiscovered
,
542 &gEfiEdidActiveProtocolGuid
,
543 &BiosVideoPrivate
->EdidActive
,
547 if (!EFI_ERROR (Status
)) {
549 // Open the Parent Handle for the child
551 Status
= gBS
->OpenProtocol (
553 &gEfiPciIoProtocolGuid
,
554 (VOID
**) &BiosVideoPrivate
->PciIo
,
555 This
->DriverBindingHandle
,
556 BiosVideoPrivate
->Handle
,
557 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
559 if (EFI_ERROR (Status
)) {
565 // Install VGA Mini Port Protocol
567 Status
= gBS
->InstallMultipleProtocolInterfaces (
568 &BiosVideoPrivate
->Handle
,
569 &gEfiVgaMiniPortProtocolGuid
,
570 &BiosVideoPrivate
->VgaMiniPort
,
576 if (EFI_ERROR (Status
)) {
578 // Free private data structure
580 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
587 Deregister an video child handle and free resources
589 @param This Protocol instance pointer.
590 @param Controller Video controller handle
591 @param Handle Video child handle
597 BiosVideoChildHandleUninstall (
598 EFI_DRIVER_BINDING_PROTOCOL
*This
,
599 EFI_HANDLE Controller
,
604 EFI_IA32_REGISTER_SET Regs
;
605 EFI_GRAPHICS_OUTPUT_PROTOCOL
*GraphicsOutput
;
606 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
607 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
608 EFI_PCI_IO_PROTOCOL
*PciIo
;
610 BiosVideoPrivate
= NULL
;
612 Status
= gBS
->OpenProtocol (
614 &gEfiGraphicsOutputProtocolGuid
,
615 (VOID
**) &GraphicsOutput
,
616 This
->DriverBindingHandle
,
618 EFI_OPEN_PROTOCOL_GET_PROTOCOL
620 if (!EFI_ERROR (Status
)) {
621 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (GraphicsOutput
);
624 Status
= gBS
->OpenProtocol (
626 &gEfiVgaMiniPortProtocolGuid
,
627 (VOID
**) &VgaMiniPort
,
628 This
->DriverBindingHandle
,
630 EFI_OPEN_PROTOCOL_GET_PROTOCOL
632 if (!EFI_ERROR (Status
)) {
633 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
636 if (BiosVideoPrivate
== NULL
) {
637 return EFI_UNSUPPORTED
;
641 // Close PCI I/O protocol that opened by child handle
643 Status
= gBS
->CloseProtocol (
645 &gEfiPciIoProtocolGuid
,
646 This
->DriverBindingHandle
,
651 // Uninstall protocols on child handle
653 if (BiosVideoPrivate
->ProduceGraphicsOutput
) {
654 Status
= gBS
->UninstallMultipleProtocolInterfaces (
655 BiosVideoPrivate
->Handle
,
656 &gEfiDevicePathProtocolGuid
,
657 BiosVideoPrivate
->DevicePath
,
658 &gEfiGraphicsOutputProtocolGuid
,
659 &BiosVideoPrivate
->GraphicsOutput
,
660 &gEfiEdidDiscoveredProtocolGuid
,
661 &BiosVideoPrivate
->EdidDiscovered
,
662 &gEfiEdidActiveProtocolGuid
,
663 &BiosVideoPrivate
->EdidActive
,
667 Status
= gBS
->UninstallMultipleProtocolInterfaces (
668 BiosVideoPrivate
->Handle
,
669 &gEfiVgaMiniPortProtocolGuid
,
670 &BiosVideoPrivate
->VgaMiniPort
,
674 if (EFI_ERROR (Status
)) {
677 &gEfiPciIoProtocolGuid
,
679 This
->DriverBindingHandle
,
681 EFI_OPEN_PROTOCOL_BY_CHILD_CONTROLLER
686 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
689 // Set the 80x25 Text VGA Mode
693 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
698 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
701 // Do not disable IO/memory decode since that would prevent legacy ROM from working
705 // Release all allocated resources
707 BiosVideoDeviceReleaseResource (BiosVideoPrivate
);
713 Collect the resource from destroyed bios video device.
715 @param BiosVideoPrivate Video child device private data structure
719 BiosVideoDeviceReleaseResource (
720 BIOS_VIDEO_DEV
*BiosVideoPrivate
723 if (BiosVideoPrivate
== NULL
) {
728 // Release all the resourses occupied by the BIOS_VIDEO_DEV
732 // Free VGA Frame Buffer
734 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
735 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
738 // Free VBE Frame Buffer
740 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
741 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
746 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
747 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
752 if (BiosVideoPrivate
->ModeData
!= NULL
) {
753 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
756 // Free memory allocated below 1MB
758 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
759 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
762 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
763 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
766 // Free graphics output protocol occupied resource
768 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
769 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
770 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
772 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
775 // Free EDID discovered protocol occupied resource
777 if (BiosVideoPrivate
->EdidDiscovered
.Edid
!= NULL
) {
778 gBS
->FreePool (BiosVideoPrivate
->EdidDiscovered
.Edid
);
781 // Free EDID active protocol occupied resource
783 if (BiosVideoPrivate
->EdidActive
.Edid
!= NULL
) {
784 gBS
->FreePool (BiosVideoPrivate
->EdidActive
.Edid
);
787 if (BiosVideoPrivate
->DevicePath
!= NULL
) {
788 gBS
->FreePool (BiosVideoPrivate
->DevicePath
);
791 gBS
->FreePool (BiosVideoPrivate
);
798 Generate a search key for a specified timing data.
801 @param EdidTiming - Pointer to EDID timing
803 @return The 32 bit unique key for search.
809 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
815 // Be sure no conflicts for all standard timing defined by VESA.
817 Key
= (EdidTiming
->HorizontalResolution
* 2) + EdidTiming
->VerticalResolution
;
823 Parse the Established Timing and Standard Timing in EDID data block.
826 @param EdidBuffer - Pointer to EDID data block
827 @param ValidEdidTiming - Valid EDID timing information
829 @return TRUE - The EDID data is valid.
830 FALSE - The EDID data is invalid.
837 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
845 UINT16 HorizontalResolution
;
846 UINT16 VerticalResolution
;
849 VESA_BIOS_EXTENSIONS_EDID_TIMING TempTiming
;
850 VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*EdidDataBlock
;
852 EdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) EdidBuffer
;
855 // Check the checksum of EDID data
858 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
; Index
++) {
859 CheckSum
= (UINT8
)(CheckSum
+ EdidBuffer
[Index
]);
866 gBS
->SetMem (ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
), 0);
868 if ((EdidDataBlock
->EstablishedTimings
[0] != 0) ||
869 (EdidDataBlock
->EstablishedTimings
[1] != 0) ||
870 (EdidDataBlock
->EstablishedTimings
[2] != 0)
873 // Established timing data
875 TimingBits
= EdidDataBlock
->EstablishedTimings
[0] |
876 (EdidDataBlock
->EstablishedTimings
[1] << 8) |
877 ((EdidDataBlock
->EstablishedTimings
[2] & 0x80) << 9) ;
878 for (Index
= 0; Index
< VESA_BIOS_EXTENSIONS_EDID_ESTABLISHED_TIMING_MAX_NUMBER
; Index
++) {
879 if (TimingBits
& 0x1) {
880 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&mEstablishedEdidTiming
[Index
]);
883 TimingBits
= TimingBits
>> 1;
887 // If no Established timing data, read the standard timing data
889 BufferIndex
= &EdidDataBlock
->StandardTimingIdentification
[0];
890 for (Index
= 0; Index
< 8; Index
++) {
891 if ((BufferIndex
[0] != 0x1) && (BufferIndex
[1] != 0x1)){
893 // A valid Standard Timing
895 HorizontalResolution
= (UINT8
) (BufferIndex
[0] * 8 + 248);
896 AspectRatio
= (UINT8
) (BufferIndex
[1] >> 6);
897 switch (AspectRatio
) {
899 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 16 * 10);
902 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 4 * 3);
905 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 5 * 4);
908 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 16 * 9);
911 VerticalResolution
= (UINT8
) (HorizontalResolution
/ 4 * 3);
914 RefreshRate
= (UINT8
) ((BufferIndex
[1] & 0x1f) + 60);
915 TempTiming
.HorizontalResolution
= HorizontalResolution
;
916 TempTiming
.VerticalResolution
= VerticalResolution
;
917 TempTiming
.RefreshRate
= RefreshRate
;
918 ValidEdidTiming
->Key
[ValidNumber
] = CalculateEdidKey (&TempTiming
);
925 ValidEdidTiming
->ValidNumber
= ValidNumber
;
931 Search a specified Timing in all the valid EDID timings.
934 @param ValidEdidTiming - All valid EDID timing information.
935 @param EdidTiming - The Timing to search for.
937 @return TRUE - Found.
944 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
*ValidEdidTiming
,
945 VESA_BIOS_EXTENSIONS_EDID_TIMING
*EdidTiming
951 Key
= CalculateEdidKey (EdidTiming
);
953 for (Index
= 0; Index
< ValidEdidTiming
->ValidNumber
; Index
++) {
954 if (Key
== ValidEdidTiming
->Key
[Index
]) {
962 #define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
966 Judge whether this device is VGA device.
968 @param PciIo Parent PciIo protocol instance pointer
970 @retval TRUE Is vga device
971 @retval FALSE Is no vga device
975 IN EFI_PCI_IO_PROTOCOL
*PciIo
979 BOOLEAN VgaCompatible
;
982 VgaCompatible
= FALSE
;
985 // Read the PCI Configuration Header
987 Status
= PciIo
->Pci
.Read (
991 sizeof (Pci
) / sizeof (UINT32
),
994 if (EFI_ERROR (Status
)) {
995 return VgaCompatible
;
999 // See if this is a VGA compatible controller or not
1001 if ((Pci
.Hdr
.Command
& PCI_DEVICE_ENABLED
) == PCI_DEVICE_ENABLED
) {
1002 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_OLD
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_OLD_VGA
) {
1004 // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device
1006 VgaCompatible
= TRUE
;
1009 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_DISPLAY
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_DISPLAY_VGA
&& Pci
.Hdr
.ClassCode
[0] == 0x00) {
1011 // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller
1013 VgaCompatible
= TRUE
;
1017 return VgaCompatible
;
1022 Check for VBE device
1024 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1026 @retval EFI_SUCCESS VBE device found
1031 BiosVideoCheckForVbe (
1032 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1036 EFI_IA32_REGISTER_SET Regs
;
1037 UINT16
*ModeNumberPtr
;
1040 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1041 BIOS_VIDEO_MODE_DATA
*CurrentModeData
;
1044 VESA_BIOS_EXTENSIONS_EDID_TIMING Timing
;
1045 VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING ValidEdidTiming
;
1046 EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
*GraphicsOutputMode
;
1048 DEBUG ((EFI_D_INFO
, "Enter BiosVideoCheckForVbe()\n"));
1050 // Allocate buffer under 1MB for VBE data structures
1052 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
1053 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) +
1054 sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
1055 sizeof (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
) +
1056 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
1059 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
1061 Status
= gBS
->AllocatePages (
1063 EfiBootServicesData
,
1064 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
1065 &BiosVideoPrivate
->PagesBelow1MB
1067 if (EFI_ERROR (Status
)) {
1071 ZeroMem (&ValidEdidTiming
, sizeof (VESA_BIOS_EXTENSIONS_VALID_EDID_TIMING
));
1074 // Fill in the Graphics Output Protocol
1076 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1077 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1078 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVbeBlt
;
1079 BiosVideoPrivate
->GraphicsOutput
.Mode
= NULL
;
1082 // Fill in the VBE related data structures
1084 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
1085 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
1086 BiosVideoPrivate
->VbeEdidDataBlock
= (VESA_BIOS_EXTENSIONS_EDID_DATA_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
1087 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeEdidDataBlock
+ 1);
1088 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
1089 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
1092 // Test to see if the Video Adapter is compliant with VBE 3.0
1094 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1095 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
1096 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
1097 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
1098 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1099 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
);
1101 DEBUG ((EFI_D_INFO
, "Before VESA!\n"));
1102 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1103 DEBUG ((EFI_D_INFO
, "Call VESA! Return Status=0x%X\n", Regs
.X
.AX
));
1104 DEBUG ((EFI_D_INFO
, "Call VESA! VESA Signature =0x%X\n", BiosVideoPrivate
->VbeInformationBlock
->VESASignature
));
1105 DEBUG ((EFI_D_INFO
, "Call VESA! VESA Version =0x%X\n", BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
));
1107 Status
= EFI_DEVICE_ERROR
;
1110 // See if the VESA call succeeded
1112 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1113 DEBUG ((EFI_D_INFO
, "Fail to call VESA! Status=0x%X\n", Regs
.X
.AX
));
1117 // Check for 'VESA' signature
1119 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
1120 DEBUG ((EFI_D_INFO
, "Fail to check VESA signature!\n"));
1124 // Check to see if this is VBE 2.0 or higher
1126 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
1127 DEBUG ((EFI_D_INFO
, "VBE version is little than 2.0!\n"));
1132 // Read EDID information
1134 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1135 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_EDID
;
1139 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1140 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeEdidDataBlock
);
1142 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1145 // See if the VESA call succeeded
1148 if (Regs
.X
.AX
== VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1150 // Parse EDID data structure to retrieve modes supported by monitor
1152 if (ParseEdidData ((UINT8
*) BiosVideoPrivate
->VbeEdidDataBlock
, &ValidEdidTiming
) == TRUE
) {
1155 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1156 Status
= gBS
->AllocatePool (
1157 EfiBootServicesData
,
1158 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1159 (VOID
**) &BiosVideoPrivate
->EdidDiscovered
.Edid
1161 if (EFI_ERROR (Status
)) {
1165 BiosVideoPrivate
->EdidDiscovered
.Edid
,
1166 BiosVideoPrivate
->VbeEdidDataBlock
,
1167 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1170 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
;
1171 Status
= gBS
->AllocatePool (
1172 EfiBootServicesData
,
1173 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
,
1174 (VOID
**)&BiosVideoPrivate
->EdidActive
.Edid
1176 if (EFI_ERROR (Status
)) {
1180 BiosVideoPrivate
->EdidActive
.Edid
,
1181 BiosVideoPrivate
->VbeEdidDataBlock
,
1182 VESA_BIOS_EXTENSIONS_EDID_BLOCK_SIZE
1185 BiosVideoPrivate
->EdidDiscovered
.SizeOfEdid
= 0;
1186 BiosVideoPrivate
->EdidDiscovered
.Edid
= NULL
;
1188 BiosVideoPrivate
->EdidActive
.SizeOfEdid
= 0;
1189 BiosVideoPrivate
->EdidActive
.Edid
= NULL
;
1194 // Walk through the mode list to see if there is at least one mode the is compatible with the EDID mode
1196 ModeNumberPtr
= (UINT16
*)
1198 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
1199 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
1205 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
1207 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
1209 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
1213 // Get the information about the mode
1215 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1216 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
1217 Regs
.X
.CX
= *ModeNumberPtr
;
1218 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
1219 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1220 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeModeInformationBlock
);
1222 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1225 // See if the call succeeded. If it didn't, then try the next mode.
1227 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1231 // See if the mode supports color. If it doesn't then try the next mode.
1233 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
1237 // See if the mode supports graphics. If it doesn't then try the next mode.
1239 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
1243 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
1245 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
1249 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
1250 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
1251 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
1253 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
1257 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
1261 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
1265 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
1267 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
1271 if (EdidFound
&& (ValidEdidTiming
.ValidNumber
> 0)) {
1273 // EDID exist, check whether this mode match with any mode in EDID
1275 Timing
.HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1276 Timing
.VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1277 if (SearchEdidTiming (&ValidEdidTiming
, &Timing
) == FALSE
) {
1283 // Select a reasonable mode to be set for current display mode
1287 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
1288 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
1292 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
1293 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
1296 PreferMode
= ModeNumber
;
1298 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
1299 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
1303 if ((!EdidFound
) && (!ModeFound
)) {
1305 // When no EDID exist, only select three possible resolutions, i.e. 1024x768, 800x600, 640x480
1311 // Add mode to the list of available modes
1314 Status
= gBS
->AllocatePool (
1315 EfiBootServicesData
,
1316 ModeNumber
* sizeof (BIOS_VIDEO_MODE_DATA
),
1317 (VOID
**) &ModeBuffer
1319 if (EFI_ERROR (Status
)) {
1323 if (ModeNumber
> 1) {
1326 BiosVideoPrivate
->ModeData
,
1327 (ModeNumber
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1331 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1332 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1335 CurrentModeData
= &ModeBuffer
[ModeNumber
- 1];
1336 CurrentModeData
->VbeModeNumber
= *ModeNumberPtr
;
1337 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
1338 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
1339 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
1340 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
1341 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
1342 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
1343 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
1344 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
1345 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdFieldPosition
;
1346 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRsvdMaskSize
) - 1);
1348 CurrentModeData
->BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1349 CurrentModeData
->Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1350 CurrentModeData
->Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1351 CurrentModeData
->Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1352 CurrentModeData
->Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1353 CurrentModeData
->Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1354 CurrentModeData
->Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1355 CurrentModeData
->Reserved
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RsvdFieldPosition
;
1356 CurrentModeData
->Reserved
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RsvdMaskSize
) - 1);
1358 CurrentModeData
->PixelFormat
= PixelBitMask
;
1359 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
== 32) &&
1360 (CurrentModeData
->Red
.Mask
== 0xff) && (CurrentModeData
->Green
.Mask
== 0xff) && (CurrentModeData
->Blue
.Mask
== 0xff)) {
1361 if ((CurrentModeData
->Red
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Blue
.Position
== 16)) {
1362 CurrentModeData
->PixelFormat
= PixelRedGreenBlueReserved8BitPerColor
;
1363 } else if ((CurrentModeData
->Blue
.Position
== 0) && (CurrentModeData
->Green
.Position
== 8) && (CurrentModeData
->Red
.Position
== 16)) {
1364 CurrentModeData
->PixelFormat
= PixelBlueGreenRedReserved8BitPerColor
;
1367 CurrentModeData
->PixelBitMask
.RedMask
= ((UINT32
) CurrentModeData
->Red
.Mask
) << CurrentModeData
->Red
.Position
;
1368 CurrentModeData
->PixelBitMask
.GreenMask
= ((UINT32
) CurrentModeData
->Green
.Mask
) << CurrentModeData
->Green
.Position
;
1369 CurrentModeData
->PixelBitMask
.BlueMask
= ((UINT32
) CurrentModeData
->Blue
.Mask
) << CurrentModeData
->Blue
.Position
;
1370 CurrentModeData
->PixelBitMask
.ReservedMask
= ((UINT32
) CurrentModeData
->Reserved
.Mask
) << CurrentModeData
->Reserved
.Position
;
1372 CurrentModeData
->LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1373 CurrentModeData
->FrameBufferSize
= BiosVideoPrivate
->VbeInformationBlock
->TotalMemory
* 64 * 1024;
1374 CurrentModeData
->HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1375 CurrentModeData
->VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1377 CurrentModeData
->BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1379 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1382 // Check to see if we found any modes that are compatible with GRAPHICS OUTPUT
1384 if (ModeNumber
== 0) {
1385 Status
= EFI_DEVICE_ERROR
;
1390 // Allocate buffer for Graphics Output Protocol mode information
1392 Status
= gBS
->AllocatePool (
1393 EfiBootServicesData
,
1394 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1395 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1397 if (EFI_ERROR (Status
)) {
1400 GraphicsOutputMode
= BiosVideoPrivate
->GraphicsOutput
.Mode
;
1401 Status
= gBS
->AllocatePool (
1402 EfiBootServicesData
,
1403 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1404 (VOID
**) &GraphicsOutputMode
->Info
1406 if (EFI_ERROR (Status
)) {
1410 GraphicsOutputMode
->MaxMode
= (UINT32
) ModeNumber
;
1412 // Current mode is unknow till now, set it to an invalid mode.
1414 GraphicsOutputMode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1417 // Find the best mode to initialize
1419 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, (UINT32
) PreferMode
);
1420 if (EFI_ERROR (Status
)) {
1421 for (PreferMode
= 0; PreferMode
< ModeNumber
; PreferMode
++) {
1422 Status
= BiosVideoGraphicsOutputSetMode (
1423 &BiosVideoPrivate
->GraphicsOutput
,
1426 if (!EFI_ERROR (Status
)) {
1430 if (PreferMode
== ModeNumber
) {
1432 // None mode is set successfully.
1440 // If there was an error, then free the mode structure
1442 if (EFI_ERROR (Status
)) {
1443 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1444 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1446 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1447 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1448 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1450 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1458 Check for VGA device
1460 @param BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1462 @retval EFI_SUCCESS Standard VGA device found
1466 BiosVideoCheckForVga (
1467 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1471 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1474 // Fill in the Graphics Output Protocol
1476 BiosVideoPrivate
->GraphicsOutput
.QueryMode
= BiosVideoGraphicsOutputQueryMode
;
1477 BiosVideoPrivate
->GraphicsOutput
.SetMode
= BiosVideoGraphicsOutputSetMode
;
1478 BiosVideoPrivate
->GraphicsOutput
.Blt
= BiosVideoGraphicsOutputVgaBlt
;
1481 // Allocate buffer for Graphics Output Protocol mode information
1483 Status
= gBS
->AllocatePool (
1484 EfiBootServicesData
,
1485 sizeof (EFI_GRAPHICS_OUTPUT_PROTOCOL_MODE
),
1486 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
1488 if (EFI_ERROR (Status
)) {
1491 Status
= gBS
->AllocatePool (
1492 EfiBootServicesData
,
1493 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1494 (VOID
**) &BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
1496 if (EFI_ERROR (Status
)) {
1501 // Add mode to the list of available modes
1503 BiosVideoPrivate
->GraphicsOutput
.Mode
->MaxMode
= 1;
1505 Status
= gBS
->AllocatePool (
1506 EfiBootServicesData
,
1507 sizeof (BIOS_VIDEO_MODE_DATA
),
1508 (VOID
**) &ModeBuffer
1510 if (EFI_ERROR (Status
)) {
1514 ModeBuffer
->VbeModeNumber
= 0x0012;
1515 ModeBuffer
->BytesPerScanLine
= 640;
1516 ModeBuffer
->LinearFrameBuffer
= (VOID
*) (UINTN
) (0xa0000);
1517 ModeBuffer
->FrameBufferSize
= 0;
1518 ModeBuffer
->HorizontalResolution
= 640;
1519 ModeBuffer
->VerticalResolution
= 480;
1520 ModeBuffer
->BitsPerPixel
= 8;
1521 ModeBuffer
->PixelFormat
= PixelBltOnly
;
1523 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1526 // Test to see if the Video Adapter support the 640x480 16 color mode
1528 BiosVideoPrivate
->GraphicsOutput
.Mode
->Mode
= GRAPHICS_OUTPUT_INVALIDE_MODE_NUMBER
;
1529 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVga: before BiosVideoGraphicsOutputSetMode"));
1530 Status
= BiosVideoGraphicsOutputSetMode (&BiosVideoPrivate
->GraphicsOutput
, 0);
1531 DEBUG ((EFI_D_INFO
, "BiosVideoCheckForVga: after BiosVideoGraphicsOutputSetMode, %r", Status
));
1535 // If there was an error, then free the mode structure
1537 if (EFI_ERROR (Status
)) {
1538 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1539 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1541 if (BiosVideoPrivate
->GraphicsOutput
.Mode
!= NULL
) {
1542 if (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
!= NULL
) {
1543 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
->Info
);
1545 gBS
->FreePool (BiosVideoPrivate
->GraphicsOutput
.Mode
);
1551 // Graphics Output Protocol Member Functions for VESA BIOS Extensions
1555 Graphics Output protocol interface to get video mode
1558 @param This - Protocol instance pointer.
1559 @param ModeNumber - The mode number to return information on.
1560 @param SizeOfInfo - A pointer to the size, in bytes, of the Info buffer.
1561 @param Info - Caller allocated buffer that returns information about ModeNumber.
1563 @return EFI_SUCCESS - Mode information returned.
1564 EFI_DEVICE_ERROR - A hardware error occurred trying to retrieve the video mode.
1565 EFI_NOT_STARTED - Video display is not initialized. Call SetMode ()
1566 EFI_INVALID_PARAMETER - One of the input args was NULL.
1571 BiosVideoGraphicsOutputQueryMode (
1572 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1573 IN UINT32 ModeNumber
,
1574 OUT UINTN
*SizeOfInfo
,
1575 OUT EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
**Info
1578 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1580 BIOS_VIDEO_MODE_DATA
*ModeData
;
1582 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1584 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1585 return EFI_NOT_STARTED
;
1588 if (This
== NULL
|| Info
== NULL
|| SizeOfInfo
== NULL
|| ModeNumber
>= This
->Mode
->MaxMode
) {
1589 return EFI_INVALID_PARAMETER
;
1592 Status
= gBS
->AllocatePool (
1593 EfiBootServicesData
,
1594 sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
),
1597 if (EFI_ERROR (Status
)) {
1601 *SizeOfInfo
= sizeof (EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1603 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1604 (*Info
)->Version
= 0;
1605 (*Info
)->HorizontalResolution
= ModeData
->HorizontalResolution
;
1606 (*Info
)->VerticalResolution
= ModeData
->VerticalResolution
;
1607 (*Info
)->PixelFormat
= ModeData
->PixelFormat
;
1608 (*Info
)->PixelInformation
= ModeData
->PixelBitMask
;
1610 (*Info
)->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1617 Graphics Output protocol interface to set video mode
1620 @param This - Protocol instance pointer.
1621 @param ModeNumber - The mode number to be set.
1623 @return EFI_SUCCESS - Graphics mode was changed.
1624 EFI_DEVICE_ERROR - The device had an error and could not complete the request.
1625 EFI_UNSUPPORTED - ModeNumber is not supported by this device.
1630 BiosVideoGraphicsOutputSetMode (
1631 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
* This
,
1632 IN UINT32 ModeNumber
1636 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1637 EFI_IA32_REGISTER_SET Regs
;
1638 BIOS_VIDEO_MODE_DATA
*ModeData
;
1640 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1643 return EFI_INVALID_PARAMETER
;
1646 if (ModeNumber
>= This
->Mode
->MaxMode
) {
1647 return EFI_UNSUPPORTED
;
1650 if (ModeNumber
== This
->Mode
->Mode
) {
1654 ModeData
= &BiosVideoPrivate
->ModeData
[ModeNumber
];
1656 if (BiosVideoPrivate
->LineBuffer
) {
1657 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
1660 if (BiosVideoPrivate
->VgaFrameBuffer
) {
1661 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1664 if (BiosVideoPrivate
->VbeFrameBuffer
) {
1665 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1668 BiosVideoPrivate
->LineBuffer
= NULL
;
1669 Status
= gBS
->AllocatePool (
1670 EfiBootServicesData
,
1671 ModeData
->BytesPerScanLine
,
1672 (VOID
**) &BiosVideoPrivate
->LineBuffer
1674 if (EFI_ERROR (Status
)) {
1678 // Clear all registers
1680 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1682 if (ModeData
->VbeModeNumber
< 0x100) {
1684 // Allocate a working buffer for BLT operations to the VGA frame buffer
1686 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
1687 Status
= gBS
->AllocatePool (
1688 EfiBootServicesData
,
1690 (VOID
**) &BiosVideoPrivate
->VgaFrameBuffer
1692 if (EFI_ERROR (Status
)) {
1698 //Regs.X.AX = ModeData->VbeModeNumber;
1701 DEBUG ((EFI_D_INFO
, "Set VGA Mode, VbeModeNumber AX=0x%X!\n", Regs
.X
.AX
));
1702 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1706 // Allocate a working buffer for BLT operations to the VBE frame buffer
1708 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
1709 Status
= gBS
->AllocatePool (
1710 EfiBootServicesData
,
1711 ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
,
1712 (VOID
**) &BiosVideoPrivate
->VbeFrameBuffer
1714 if (EFI_ERROR (Status
)) {
1720 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1721 Regs
.X
.BX
= (UINT16
) (ModeData
->VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1722 gBS
->SetMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
), 0);
1723 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1724 Regs
.X
.DI
= EFI_OFFSET ((UINTN
) BiosVideoPrivate
->VbeCrtcInformationBlock
);
1726 DEBUG ((EFI_D_INFO
, "Set VBE Mode!\n"));
1727 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
1730 // Check to see if the call succeeded
1732 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1733 return EFI_DEVICE_ERROR
;
1736 // Initialize the state of the VbeFrameBuffer
1738 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1739 BiosVideoPrivate
->PciIo
,
1740 EfiPciIoWidthUint32
,
1741 EFI_PCI_IO_PASS_THROUGH_BAR
,
1742 (UINT64
) (UINTN
) ModeData
->LinearFrameBuffer
,
1743 (ModeData
->BytesPerScanLine
* ModeData
->VerticalResolution
) >> 2,
1744 BiosVideoPrivate
->VbeFrameBuffer
1746 if (EFI_ERROR (Status
)) {
1751 This
->Mode
->Mode
= ModeNumber
;
1752 This
->Mode
->Info
->Version
= 0;
1753 This
->Mode
->Info
->HorizontalResolution
= ModeData
->HorizontalResolution
;
1754 This
->Mode
->Info
->VerticalResolution
= ModeData
->VerticalResolution
;
1755 This
->Mode
->Info
->PixelFormat
= ModeData
->PixelFormat
;
1756 This
->Mode
->Info
->PixelInformation
= ModeData
->PixelBitMask
;
1757 This
->Mode
->Info
->PixelsPerScanLine
= (ModeData
->BytesPerScanLine
* 8) / ModeData
->BitsPerPixel
;
1758 This
->Mode
->SizeOfInfo
= sizeof(EFI_GRAPHICS_OUTPUT_MODE_INFORMATION
);
1761 // Frame BufferSize remain unchanged
1763 This
->Mode
->FrameBufferBase
= (EFI_PHYSICAL_ADDRESS
)(UINTN
)ModeData
->LinearFrameBuffer
;
1764 This
->Mode
->FrameBufferSize
= ModeData
->FrameBufferSize
;
1766 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
1773 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1776 @param PciIo - The pointer of EFI_PCI_IO_PROTOCOL
1777 @param VbeBuffer - The data to transfer to screen
1778 @param MemAddress - Physical frame buffer base address
1779 @param DestinationX - The X coordinate of the destination for BltOperation
1780 @param DestinationY - The Y coordinate of the destination for BltOperation
1781 @param TotalBytes - The total bytes of copy
1782 @param VbePixelWidth - Bytes per pixel
1783 @param BytesPerScanLine - Bytes per scan line
1790 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1791 IN UINT8
*VbeBuffer
,
1792 IN VOID
*MemAddress
,
1793 IN UINTN DestinationX
,
1794 IN UINTN DestinationY
,
1795 IN UINTN TotalBytes
,
1796 IN UINT32 VbePixelWidth
,
1797 IN UINTN BytesPerScanLine
1800 UINTN FrameBufferAddr
;
1802 UINTN RemainingBytes
;
1803 UINTN UnalignedBytes
;
1806 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1809 // If TotalBytes is less than 4 bytes, only start byte copy.
1811 if (TotalBytes
< 4) {
1812 Status
= PciIo
->Mem
.Write (
1815 EFI_PCI_IO_PASS_THROUGH_BAR
,
1816 (UINT64
) FrameBufferAddr
,
1820 ASSERT_EFI_ERROR (Status
);
1825 // If VbeBuffer is not 4-byte aligned, start byte copy.
1827 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1829 if (UnalignedBytes
!= 0) {
1830 Status
= PciIo
->Mem
.Write (
1833 EFI_PCI_IO_PASS_THROUGH_BAR
,
1834 (UINT64
) FrameBufferAddr
,
1838 ASSERT_EFI_ERROR (Status
);
1839 FrameBufferAddr
+= UnalignedBytes
;
1840 VbeBuffer
+= UnalignedBytes
;
1844 // Calculate 4-byte block count and remaining bytes.
1846 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1847 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1850 // Copy 4-byte block and remaining bytes to physical frame buffer.
1852 if (CopyBlockNum
!= 0) {
1853 Status
= PciIo
->Mem
.Write (
1855 EfiPciIoWidthUint32
,
1856 EFI_PCI_IO_PASS_THROUGH_BAR
,
1857 (UINT64
) FrameBufferAddr
,
1861 ASSERT_EFI_ERROR (Status
);
1864 if (RemainingBytes
!= 0) {
1865 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1866 VbeBuffer
+= (CopyBlockNum
<< 2);
1867 Status
= PciIo
->Mem
.Write (
1870 EFI_PCI_IO_PASS_THROUGH_BAR
,
1871 (UINT64
) FrameBufferAddr
,
1875 ASSERT_EFI_ERROR (Status
);
1880 // BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
1884 Graphics Output protocol instance to block transfer for VBE device
1887 @param This - Pointer to Graphics Output protocol instance
1888 @param BltBuffer - The data to transfer to screen
1889 @param BltOperation - The operation to perform
1890 @param SourceX - The X coordinate of the source for BltOperation
1891 @param SourceY - The Y coordinate of the source for BltOperation
1892 @param DestinationX - The X coordinate of the destination for BltOperation
1893 @param DestinationY - The Y coordinate of the destination for BltOperation
1894 @param Width - The width of a rectangle in the blt rectangle in pixels
1895 @param Height - The height of a rectangle in the blt rectangle in pixels
1896 @param Delta - Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
1897 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1898 If a subrectangle of the BltBuffer is used, then Delta represents
1899 the number of bytes in a row of the BltBuffer.
1901 @return EFI_INVALID_PARAMETER - Invalid parameter passed in
1902 EFI_SUCCESS - Blt operation success
1907 BiosVideoGraphicsOutputVbeBlt (
1908 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
1909 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
1910 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
1913 IN UINTN DestinationX
,
1914 IN UINTN DestinationY
,
1920 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1921 BIOS_VIDEO_MODE_DATA
*Mode
;
1922 EFI_PCI_IO_PROTOCOL
*PciIo
;
1923 EFI_TPL OriginalTPL
;
1927 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*Blt
;
1929 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*VbeFrameBuffer
;
1930 UINTN BytesPerScanLine
;
1935 UINT32 VbePixelWidth
;
1939 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
1940 Mode
= &BiosVideoPrivate
->ModeData
[This
->Mode
->Mode
];
1941 PciIo
= BiosVideoPrivate
->PciIo
;
1943 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
1944 MemAddress
= Mode
->LinearFrameBuffer
;
1945 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1946 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1947 BltUint8
= (UINT8
*) BltBuffer
;
1948 TotalBytes
= Width
* VbePixelWidth
;
1950 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
1951 return EFI_INVALID_PARAMETER
;
1954 if (Width
== 0 || Height
== 0) {
1955 return EFI_INVALID_PARAMETER
;
1958 // We need to fill the Virtual Screen buffer with the blt data.
1959 // The virtual screen is upside down, as the first row is the bootom row of
1962 if (BltOperation
== EfiBltVideoToBltBuffer
) {
1964 // Video to BltBuffer: Source is Video, destination is BltBuffer
1966 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1967 return EFI_INVALID_PARAMETER
;
1970 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1971 return EFI_INVALID_PARAMETER
;
1975 // BltBuffer to Video: Source is BltBuffer, destination is Video
1977 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1978 return EFI_INVALID_PARAMETER
;
1981 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1982 return EFI_INVALID_PARAMETER
;
1986 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1987 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1988 // the number of bytes in each row can be computed.
1991 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
1994 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1995 // We would not want a timer based event (Cursor, ...) to come in while we are
1996 // doing this operation.
1998 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2000 switch (BltOperation
) {
2001 case EfiBltVideoToBltBuffer
:
2002 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
2003 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2005 // Shuffle the packed bytes in the hardware buffer to match EFI_GRAPHICS_OUTPUT_BLT_PIXEL
2007 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
2008 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2009 Pixel
= *(UINT32
*) (VbeBuffer
);
2010 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
2011 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
2012 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
2015 VbeBuffer
+= VbePixelWidth
;
2021 case EfiBltVideoToVideo
:
2022 for (Index
= 0; Index
< Height
; Index
++) {
2023 if (DestinationY
<= SourceY
) {
2024 SrcY
= SourceY
+ Index
;
2025 DstY
= DestinationY
+ Index
;
2027 SrcY
= SourceY
+ Height
- Index
- 1;
2028 DstY
= DestinationY
+ Height
- Index
- 1;
2031 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
2032 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
2041 // Update physical frame buffer.
2056 case EfiBltVideoFill
:
2057 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2058 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) BltUint8
;
2060 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2062 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2064 (Blt
->Green
& Mode
->Green
.Mask
) <<
2065 Mode
->Green
.Position
2067 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2069 for (Index
= 0; Index
< Width
; Index
++) {
2075 VbeBuffer
+= VbePixelWidth
;
2078 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
2079 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
2081 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
2086 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
2088 // Update physical frame buffer.
2103 case EfiBltBufferToVideo
:
2104 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
2105 Blt
= (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
));
2106 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2107 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
2109 // Shuffle the RGB fields in EFI_GRAPHICS_OUTPUT_BLT_PIXEL to match the hardware buffer
2111 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
2112 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
2113 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
2120 VbeBuffer
+= VbePixelWidth
;
2123 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
2126 // Update physical frame buffer.
2144 gBS
->RestoreTPL (OriginalTPL
);
2151 Write graphics controller registers
2154 @param PciIo - Pointer to PciIo protocol instance of the controller
2155 @param Address - Register address
2156 @param Data - Data to be written to register
2163 WriteGraphicsController (
2164 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
2169 Address
= Address
| (Data
<< 8);
2172 EfiPciIoWidthUint16
,
2173 EFI_PCI_IO_PASS_THROUGH_BAR
,
2174 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
2182 Read the four bit plane of VGA frame buffer
2185 @param PciIo - Pointer to PciIo protocol instance of the controller
2186 @param HardwareBuffer - Hardware VGA frame buffer address
2187 @param MemoryBuffer - Memory buffer address
2188 @param WidthInBytes - Number of bytes in a line to read
2189 @param Height - Height of the area to read
2196 EFI_PCI_IO_PROTOCOL
*PciIo
,
2197 UINT8
*HardwareBuffer
,
2198 UINT8
*MemoryBuffer
,
2205 UINTN FrameBufferOffset
;
2210 // Program the Mode Register Write mode 0, Read mode 0
2212 WriteGraphicsController (
2214 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2215 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
2218 for (BitPlane
= 0, FrameBufferOffset
= 0;
2219 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
2220 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
2223 // Program the Read Map Select Register to select the correct bit plane
2225 WriteGraphicsController (
2227 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
2231 Source
= HardwareBuffer
;
2232 Destination
= MemoryBuffer
+ FrameBufferOffset
;
2234 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
2238 (UINT8
) EFI_PCI_IO_PASS_THROUGH_BAR
,
2239 (UINT64
)(UINTN
) Source
,
2241 (VOID
*) Destination
2249 Internal routine to convert VGA color to Grahpics Output color
2252 @param MemoryBuffer - Buffer containing VGA color
2253 @param X - The X coordinate of pixel on screen
2254 @param Y - The Y coordinate of pixel on screen
2255 @param BltBuffer - Buffer to contain converted Grahpics Output color
2261 VgaConvertToGraphicsOutputColor (
2262 UINT8
*MemoryBuffer
,
2265 EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2272 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
2273 Mask
= mVgaBitMaskTable
[X
& 0x07];
2274 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
2275 if (*MemoryBuffer
& Mask
) {
2280 *BltBuffer
= mVgaColorToGraphicsOutputColor
[Color
];
2285 Internal routine to convert Grahpics Output color to VGA color
2288 @param BltBuffer - buffer containing Grahpics Output color
2290 @return Converted VGA color
2295 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
2300 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
2301 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
2309 Grahpics Output protocol instance to block transfer for VGA device
2311 @param This Pointer to Grahpics Output protocol instance
2312 @param BltBuffer The data to transfer to screen
2313 @param BltOperation The operation to perform
2314 @param SourceX The X coordinate of the source for BltOperation
2315 @param SourceY The Y coordinate of the source for BltOperation
2316 @param DestinationX The X coordinate of the destination for BltOperation
2317 @param DestinationY The Y coordinate of the destination for BltOperation
2318 @param Width The width of a rectangle in the blt rectangle in pixels
2319 @param Height The height of a rectangle in the blt rectangle in pixels
2320 @param Delta Not used for EfiBltVideoFill and EfiBltVideoToVideo operation.
2321 If a Delta of 0 is used, the entire BltBuffer will be operated on.
2322 If a subrectangle of the BltBuffer is used, then Delta represents
2323 the number of bytes in a row of the BltBuffer.
2325 @retval EFI_INVALID_PARAMETER Invalid parameter passed in
2326 @retval EFI_SUCCESS Blt operation success
2331 BiosVideoGraphicsOutputVgaBlt (
2332 IN EFI_GRAPHICS_OUTPUT_PROTOCOL
*This
,
2333 IN EFI_GRAPHICS_OUTPUT_BLT_PIXEL
*BltBuffer
, OPTIONAL
2334 IN EFI_GRAPHICS_OUTPUT_BLT_OPERATION BltOperation
,
2337 IN UINTN DestinationX
,
2338 IN UINTN DestinationY
,
2344 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2345 EFI_TPL OriginalTPL
;
2347 UINTN BytesPerScanLine
;
2348 //UINTN BytesPerBitPlane;
2360 UINT8
*SourceAddress
;
2361 UINT8
*DestinationAddress
;
2362 EFI_PCI_IO_PROTOCOL
*PciIo
;
2365 UINT8
*VgaFrameBuffer
;
2374 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_GRAPHICS_OUTPUT_THIS (This
);
2376 CurrentMode
= This
->Mode
->Mode
;
2377 PciIo
= BiosVideoPrivate
->PciIo
;
2378 MemAddress
= BiosVideoPrivate
->ModeData
[CurrentMode
].LinearFrameBuffer
;
2379 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[CurrentMode
].BytesPerScanLine
>> 3;
2380 //BytesPerBitPlane = BytesPerScanLine * BiosVideoPrivate->ModeData[CurrentMode].VerticalResolution;
2381 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2383 if (This
== NULL
|| ((UINTN
) BltOperation
) >= EfiGraphicsOutputBltOperationMax
) {
2384 return EFI_INVALID_PARAMETER
;
2387 if (Width
== 0 || Height
== 0) {
2388 return EFI_INVALID_PARAMETER
;
2391 // We need to fill the Virtual Screen buffer with the blt data.
2392 // The virtual screen is upside down, as the first row is the bootom row of
2395 if (BltOperation
== EfiBltVideoToBltBuffer
) {
2397 // Video to BltBuffer: Source is Video, destination is BltBuffer
2399 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2400 return EFI_INVALID_PARAMETER
;
2403 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2404 return EFI_INVALID_PARAMETER
;
2408 // BltBuffer to Video: Source is BltBuffer, destination is Video
2410 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[CurrentMode
].VerticalResolution
) {
2411 return EFI_INVALID_PARAMETER
;
2414 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[CurrentMode
].HorizontalResolution
) {
2415 return EFI_INVALID_PARAMETER
;
2419 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2420 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2421 // the number of bytes in each row can be computed.
2424 Delta
= Width
* sizeof (EFI_GRAPHICS_OUTPUT_BLT_PIXEL
);
2427 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2428 // We would not want a timer based event (Cursor, ...) to come in while we are
2429 // doing this operation.
2431 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2434 // Compute some values we need for VGA
2436 switch (BltOperation
) {
2437 case EfiBltVideoToBltBuffer
:
2439 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2440 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2443 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2447 MemAddress
+ SourceOffset
,
2448 VgaFrameBuffer
+ SourceOffset
,
2454 // Convert VGA Bit Planes to a Graphics Output 32-bit color value
2456 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2457 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2458 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2459 VgaConvertToGraphicsOutputColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2467 case EfiBltVideoToVideo
:
2469 // Check for an aligned Video to Video operation
2471 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2473 // Program the Mode Register Write mode 1, Read mode 0
2475 WriteGraphicsController (
2477 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2478 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2481 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2482 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2484 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2488 EFI_PCI_IO_PASS_THROUGH_BAR
,
2489 (UINT64
) ((UINTN
)DestinationAddress
+ Offset
),
2490 EFI_PCI_IO_PASS_THROUGH_BAR
,
2491 (UINT64
) ((UINTN
)SourceAddress
+ Offset
),
2496 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2497 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2500 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2504 MemAddress
+ SourceOffset
,
2505 VgaFrameBuffer
+ SourceOffset
,
2513 case EfiBltVideoFill
:
2514 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2515 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2516 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2517 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2519 LeftMask
= (UINT8
) (LeftMask
& RightMask
);
2523 if (LeftMask
== 0xff) {
2529 if (RightMask
== 0xff) {
2534 PixelColor
= VgaConvertColor (BltBuffer
);
2537 // Program the Mode Register Write mode 2, Read mode 0
2539 WriteGraphicsController (
2541 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2542 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2546 // Program the Data Rotate/Function Select Register to replace
2548 WriteGraphicsController (
2550 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2551 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2554 if (LeftMask
!= 0) {
2556 // Program the BitMask register with the Left column mask
2558 WriteGraphicsController (
2560 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2564 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2566 // Read data from the bit planes into the latches
2571 EFI_PCI_IO_PASS_THROUGH_BAR
,
2577 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2582 EFI_PCI_IO_PASS_THROUGH_BAR
,
2592 // Program the BitMask register with the middle column mask of 0xff
2594 WriteGraphicsController (
2596 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2600 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2603 EfiPciIoWidthFillUint8
,
2604 EFI_PCI_IO_PASS_THROUGH_BAR
,
2612 if (RightMask
!= 0) {
2614 // Program the BitMask register with the Right column mask
2616 WriteGraphicsController (
2618 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2622 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2624 // Read data from the bit planes into the latches
2629 EFI_PCI_IO_PASS_THROUGH_BAR
,
2635 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2640 EFI_PCI_IO_PASS_THROUGH_BAR
,
2649 case EfiBltBufferToVideo
:
2650 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2651 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2654 // Program the Mode Register Write mode 2, Read mode 0
2656 WriteGraphicsController (
2658 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2659 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2663 // Program the Data Rotate/Function Select Register to replace
2665 WriteGraphicsController (
2667 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2668 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2671 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2672 for (Index1
= 0; Index1
< Width
; Index1
++) {
2673 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2675 AddressFix
= Address
;
2677 for (Bit
= 0; Bit
< 8; Bit
++) {
2679 // Program the BitMask register with the Left column mask
2681 WriteGraphicsController (
2683 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2687 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2689 // Read data from the bit planes into the latches
2694 EFI_PCI_IO_PASS_THROUGH_BAR
,
2695 (UINT64
)(UINTN
) Address1
,
2703 EFI_PCI_IO_PASS_THROUGH_BAR
,
2704 (UINT64
)(UINTN
) Address1
,
2706 &BiosVideoPrivate
->LineBuffer
[Index1
]
2710 LeftMask
= (UINT8
) (LeftMask
>> 1);
2711 if (LeftMask
== 0) {
2723 gBS
->RestoreTPL (OriginalTPL
);
2728 // VGA Mini Port Protocol Functions
2731 VgaMiniPort protocol interface to set mode
2733 @param This Pointer to VgaMiniPort protocol instance
2734 @param ModeNumber The index of the mode
2736 @retval EFI_UNSUPPORTED The requested mode is not supported
2737 @retval EFI_SUCCESS The requested mode is set successfully
2742 BiosVideoVgaMiniPortSetMode (
2743 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2747 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2748 EFI_IA32_REGISTER_SET Regs
;
2751 return EFI_INVALID_PARAMETER
;
2755 // Make sure the ModeNumber is a valid value
2757 if (ModeNumber
>= This
->MaxMode
) {
2758 return EFI_UNSUPPORTED
;
2761 // Get the device structure for this device
2763 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2765 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2767 switch (ModeNumber
) {
2770 // Set the 80x25 Text VGA Mode
2774 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2779 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2785 // Set the 80x50 Text VGA Mode
2789 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2794 LegacyBiosInt86 (BiosVideoPrivate
, 0x10, &Regs
);
2798 return EFI_UNSUPPORTED
;