3 Copyright (c) 2006 - 2008, Intel Corporation
4 All rights reserved. This program and the accompanying materials
5 are licensed and made available under the terms and conditions of the BSD License
6 which accompanies this distribution. The full text of the license may be found at
7 http://opensource.org/licenses/bsd-license.php
9 THE PROGRAM IS DISTRIBUTED UNDER THE BSD LICENSE ON AN "AS IS" BASIS,
10 WITHOUT WARRANTIES OR REPRESENTATIONS OF ANY KIND, EITHER EXPRESS OR IMPLIED.
18 ConsoleOut Routines that speak VGA.
24 #include "BiosVideo.h"
28 // EFI Driver Binding Protocol Instance
30 EFI_DRIVER_BINDING_PROTOCOL gBiosVideoDriverBinding
= {
31 BiosVideoDriverBindingSupported
,
32 BiosVideoDriverBindingStart
,
33 BiosVideoDriverBindingStop
,
40 // Global lookup tables for VGA graphics modes
42 UINT8 mVgaLeftMaskTable
[] = { 0xff, 0x7f, 0x3f, 0x1f, 0x0f, 0x07, 0x03, 0x01 };
44 UINT8 mVgaRightMaskTable
[] = { 0x80, 0xc0, 0xe0, 0xf0, 0xf8, 0xfc, 0xfe, 0xff };
46 UINT8 mVgaBitMaskTable
[] = { 0x80, 0x40, 0x20, 0x10, 0x08, 0x04, 0x02, 0x01 };
48 THUNK_CONTEXT mThunkContext
;
50 EFI_LEGACY_8259_PROTOCOL
*mLegacy8259
= NULL
;
52 #define EFI_CPU_EFLAGS_IF 0x200
54 EFI_UGA_PIXEL mVgaColorToUgaColor
[] = {
154 InitializeBiosIntCaller (
159 InitializeInterruptRedirection (
167 IN EFI_IA32_REGISTER_SET
*Regs
172 BiosVideoDriverEntryPoint (
173 IN EFI_HANDLE ImageHandle
,
174 IN EFI_SYSTEM_TABLE
*SystemTable
184 ImageHandle - Handle of driver image.
185 SystemTable - Pointer to system table.
195 Status
= EfiLibInstallDriverBindingComponentName2 (
198 &gBiosVideoDriverBinding
,
200 &gBiosVideoComponentName
,
201 &gBiosVideoComponentName2
209 BiosVideoExitBootServices (
217 Callback function for exit boot service event
221 Event - EFI_EVENT structure
222 Context - Event context
231 BIOS_VIDEO_DEV *BiosVideoPrivate;
232 EFI_IA32_REGISTER_SET Regs;
237 BiosVideoPrivate = (BIOS_VIDEO_DEV *) Context;
240 // Set the 80x25 Text VGA Mode
244 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
249 BiosVideoPrivate->LegacyBios->Int86 (BiosVideoPrivate->LegacyBios, 0x10, &Regs);
255 BiosVideoDriverBindingSupported (
256 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
257 IN EFI_HANDLE Controller
,
258 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
268 This - Pointer to driver binding protocol
269 Controller - Controller handle to connect
270 RemainingDevicePath - A pointer to the remaining portion of a device path
275 EFI_STATUS - EFI_SUCCESS:This controller can be managed by this driver,
276 Otherwise, this controller cannot be managed by this driver
281 EFI_LEGACY_8259_PROTOCOL
*Legacy8259
;
282 EFI_PCI_IO_PROTOCOL
*PciIo
;
284 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingSupported\n"));
287 // See if the Legacy BIOS Protocol is available
289 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &Legacy8259
);
290 if (EFI_ERROR (Status
)) {
294 // Open the IO Abstraction(s) needed to perform the supported test
296 Status
= gBS
->OpenProtocol (
298 &gEfiPciIoProtocolGuid
,
300 This
->DriverBindingHandle
,
302 EFI_OPEN_PROTOCOL_BY_DRIVER
304 if (EFI_ERROR (Status
)) {
305 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingSupported: Fail to open PciIo protocol!\n"));
309 if (!BiosVideoIsVga (PciIo
)) {
310 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingSupported: Is not VGA!\n"));
311 Status
= EFI_UNSUPPORTED
;
316 &gEfiPciIoProtocolGuid
,
317 This
->DriverBindingHandle
,
326 BiosVideoDriverBindingStart (
327 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
328 IN EFI_HANDLE Controller
,
329 IN EFI_DEVICE_PATH_PROTOCOL
*RemainingDevicePath
335 Install UGA Draw Protocol onto VGA device handles
339 This - Pointer to driver binding protocol
340 Controller - Controller handle to connect
341 RemainingDevicePath - A pointer to the remaining portion of a device path
350 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
352 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart\n"));
354 // Initialize local variables
356 BiosVideoPrivate
= NULL
;
359 // Allocate the private device structure
361 Status
= gBS
->AllocatePool (
363 sizeof (BIOS_VIDEO_DEV
),
364 (VOID
**)&BiosVideoPrivate
366 if (EFI_ERROR (Status
)) {
370 ZeroMem (BiosVideoPrivate
, sizeof (BIOS_VIDEO_DEV
));
373 // See if the Legacy BIOS Protocol is available
375 Status
= gBS
->LocateProtocol (&gEfiLegacy8259ProtocolGuid
, NULL
, (VOID
**) &mLegacy8259
);
376 if (EFI_ERROR (Status
)) {
381 // Prepare for status code
383 Status
= gBS
->HandleProtocol (
385 &gEfiDevicePathProtocolGuid
,
386 (VOID
**)&BiosVideoPrivate
->DevicePath
388 if (EFI_ERROR (Status
)) {
392 // Open the IO Abstraction(s) needed
394 Status
= gBS
->OpenProtocol (
396 &gEfiPciIoProtocolGuid
,
397 (VOID
**) &(BiosVideoPrivate
->PciIo
),
398 This
->DriverBindingHandle
,
400 EFI_OPEN_PROTOCOL_BY_DRIVER
402 if (EFI_ERROR (Status
)) {
406 DEBUG ((EFI_D_INFO
, "InitializeBiosIntCaller\n"));
407 InitializeBiosIntCaller();
408 InitializeInterruptRedirection();
409 DEBUG ((EFI_D_INFO
, "InitializeBiosIntCaller Finished!\n"));
411 if (!BiosVideoIsVga (BiosVideoPrivate
->PciIo
)) {
412 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart: not VGA\n"));
413 Status
= EFI_UNSUPPORTED
;
417 BiosVideoPrivate
->VgaCompatible
= TRUE
;
419 // Initialize the private device structure
421 BiosVideoPrivate
->Signature
= BIOS_VIDEO_DEV_SIGNATURE
;
422 BiosVideoPrivate
->Handle
= Controller
;
425 Status = gBS->CreateEvent (
426 EFI_EVENT_SIGNAL_EXIT_BOOT_SERVICES,
428 BiosVideoExitBootServices,
430 &BiosVideoPrivate->ExitBootServicesEvent
432 if (EFI_ERROR (Status)) {
438 // Fill in UGA Draw specific mode structures
440 BiosVideoPrivate
->HardwareNeedsStarting
= TRUE
;
441 BiosVideoPrivate
->CurrentMode
= 0;
442 BiosVideoPrivate
->MaxMode
= 0;
443 BiosVideoPrivate
->ModeData
= NULL
;
444 BiosVideoPrivate
->LineBuffer
= NULL
;
445 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
446 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
449 // Fill in the VGA Mini Port Protocol fields
451 BiosVideoPrivate
->VgaMiniPort
.SetMode
= BiosVideoVgaMiniPortSetMode
;
452 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryOffset
= 0xb8000;
453 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterOffset
= 0x3d4;
454 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterOffset
= 0x3d5;
455 BiosVideoPrivate
->VgaMiniPort
.VgaMemoryBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
456 BiosVideoPrivate
->VgaMiniPort
.CrtcAddressRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
457 BiosVideoPrivate
->VgaMiniPort
.CrtcDataRegisterBar
= EFI_PCI_IO_PASS_THROUGH_BAR
;
460 // Assume that UGA Draw will be produced until proven otherwise
462 BiosVideoPrivate
->ProduceUgaDraw
= TRUE
;
465 // Check for VESA BIOS Extensions for modes that are compatible with UGA Draw
468 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart: Before check VBE!\n"));
469 Status
= BiosVideoCheckForVbe (BiosVideoPrivate
);
470 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart: check VBE status=%r!\n", Status
));
472 if (EFI_ERROR (Status
)) {
473 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart: Fail to check VBE!\n"));
475 // The VESA BIOS Extensions are not compatible with UGA Draw, so check for support
476 // for the standard 640x480 16 color VGA mode
478 if (BiosVideoPrivate
->VgaCompatible
) {
479 Status
= BiosVideoCheckForVga (BiosVideoPrivate
);
482 if (EFI_ERROR (Status
)) {
484 // Neither VBE nor the standard 640x480 16 color VGA mode are supported, so do
485 // not produce the UGA Draw protocol. Instead, produce the VGA MiniPort Protocol.
487 BiosVideoPrivate
->ProduceUgaDraw
= FALSE
;
490 // INT services are available, so on the 80x25 and 80x50 text mode are supported
492 BiosVideoPrivate
->VgaMiniPort
.MaxMode
= 2;
496 if (BiosVideoPrivate
->ProduceUgaDraw
) {
497 DEBUG ((EFI_D_INFO
, "BiosVideoDriverBindingStart: Produce Uga Draw!\n"));
499 // Install UGA Draw Protocol
501 Status
= gBS
->InstallMultipleProtocolInterfaces (
503 &gEfiUgaDrawProtocolGuid
,
504 &BiosVideoPrivate
->UgaDraw
,
509 // Install VGA Mini Port Protocol
511 Status
= gBS
->InstallMultipleProtocolInterfaces (
513 &gEfiVgaMiniPortProtocolGuid
,
514 &BiosVideoPrivate
->VgaMiniPort
,
520 if (EFI_ERROR (Status
)) {
521 if (BiosVideoPrivate
!= NULL
) {
525 if (BiosVideoPrivate
->ModeData
!= NULL
) {
526 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
529 // Free memory allocated below 1MB
531 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
532 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
535 if (BiosVideoPrivate
->PciIo
!= NULL
) {
537 // Release PCI I/O and UGA Draw Protocols on the controller handle.
541 &gEfiPciIoProtocolGuid
,
542 This
->DriverBindingHandle
,
547 // Close the ExitBootServices event
549 if (BiosVideoPrivate
->ExitBootServicesEvent
!= NULL
) {
550 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
553 // Free private data structure
555 gBS
->FreePool (BiosVideoPrivate
);
564 BiosVideoDriverBindingStop (
565 IN EFI_DRIVER_BINDING_PROTOCOL
*This
,
566 IN EFI_HANDLE Controller
,
567 IN UINTN NumberOfChildren
,
568 IN EFI_HANDLE
*ChildHandleBuffer
578 This - Pointer to driver binding protocol
579 Controller - Controller handle to connect
580 NumberOfChilren - Number of children handle created by this driver
581 ChildHandleBuffer - Buffer containing child handle created
585 EFI_SUCCESS - Driver disconnected successfully from controller
586 EFI_UNSUPPORTED - Cannot find BIOS_VIDEO_DEV structure
591 EFI_UGA_DRAW_PROTOCOL
*Uga
;
592 EFI_VGA_MINI_PORT_PROTOCOL
*VgaMiniPort
;
593 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
594 EFI_IA32_REGISTER_SET Regs
;
596 BiosVideoPrivate
= NULL
;
598 Status
= gBS
->OpenProtocol (
600 &gEfiUgaDrawProtocolGuid
,
602 This
->DriverBindingHandle
,
604 EFI_OPEN_PROTOCOL_GET_PROTOCOL
606 if (!EFI_ERROR (Status
)) {
607 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (Uga
);
610 Status
= gBS
->OpenProtocol (
612 &gEfiVgaMiniPortProtocolGuid
,
613 (VOID
**) &VgaMiniPort
,
614 This
->DriverBindingHandle
,
616 EFI_OPEN_PROTOCOL_GET_PROTOCOL
618 if (!EFI_ERROR (Status
)) {
619 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (VgaMiniPort
);
622 if (BiosVideoPrivate
== NULL
) {
623 return EFI_UNSUPPORTED
;
626 if (BiosVideoPrivate
->ProduceUgaDraw
) {
627 Status
= gBS
->UninstallMultipleProtocolInterfaces (
629 &gEfiUgaDrawProtocolGuid
,
630 &BiosVideoPrivate
->UgaDraw
,
634 Status
= gBS
->UninstallMultipleProtocolInterfaces (
636 &gEfiVgaMiniPortProtocolGuid
,
637 &BiosVideoPrivate
->VgaMiniPort
,
642 if (EFI_ERROR (Status
)) {
646 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
649 // Set the 80x25 Text VGA Mode
653 LegacyBiosInt86 (0x10, &Regs
);
658 LegacyBiosInt86 (0x10, &Regs
);
661 // Do not disable IO/memory decode since that would prevent legacy ROM from working
664 // Free VGA Frame Buffer
666 if (BiosVideoPrivate
->VgaFrameBuffer
!= NULL
) {
667 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
670 // Free VBE Frame Buffer
672 if (BiosVideoPrivate
->VbeFrameBuffer
!= NULL
) {
673 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
678 if (BiosVideoPrivate
->LineBuffer
!= NULL
) {
679 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
684 if (BiosVideoPrivate
->ModeData
!= NULL
) {
685 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
688 // Free memory allocated below 1MB
690 if (BiosVideoPrivate
->PagesBelow1MB
!= 0) {
691 gBS
->FreePages (BiosVideoPrivate
->PagesBelow1MB
, BiosVideoPrivate
->NumberOfPagesBelow1MB
);
694 if (BiosVideoPrivate
->VbeSaveRestorePages
!= 0) {
695 gBS
->FreePages (BiosVideoPrivate
->VbeSaveRestoreBuffer
, BiosVideoPrivate
->VbeSaveRestorePages
);
698 // Release PCI I/O and UGA Draw Protocols on the controller handle.
702 &gEfiPciIoProtocolGuid
,
703 This
->DriverBindingHandle
,
708 // Close the ExitBootServices event
710 gBS
->CloseEvent (BiosVideoPrivate
->ExitBootServicesEvent
);
713 // Free private data structure
715 gBS
->FreePool (BiosVideoPrivate
);
720 #define PCI_DEVICE_ENABLED (EFI_PCI_COMMAND_IO_SPACE | EFI_PCI_COMMAND_MEMORY_SPACE)
725 IN EFI_PCI_IO_PROTOCOL
*PciIo
729 BOOLEAN VgaCompatible
;
732 VgaCompatible
= FALSE
;
735 // Read the PCI Configuration Header
737 Status
= PciIo
->Pci
.Read (
741 sizeof (Pci
) / sizeof (UINT32
),
744 if (EFI_ERROR (Status
)) {
745 return VgaCompatible
;
749 // See if this is a VGA compatible controller or not
751 if ((Pci
.Hdr
.Command
& PCI_DEVICE_ENABLED
) == PCI_DEVICE_ENABLED
) {
752 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_OLD
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_OLD_VGA
) {
754 // Base Class 0x00 Sub-Class 0x01 - Backward compatible VGA device
756 VgaCompatible
= TRUE
;
759 if (Pci
.Hdr
.ClassCode
[2] == PCI_CLASS_DISPLAY
&& Pci
.Hdr
.ClassCode
[1] == PCI_CLASS_DISPLAY_VGA
&& Pci
.Hdr
.ClassCode
[0] == 0x00) {
761 // Base Class 3 Sub-Class 0 Programming interface 0 - VGA compatible Display controller
763 VgaCompatible
= TRUE
;
767 return VgaCompatible
;
772 BiosVideoCheckForVbe (
773 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
783 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
787 EFI_SUCCESS - VBE device found
792 EFI_IA32_REGISTER_SET Regs
;
793 UINT16
*ModeNumberPtr
;
795 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
799 // Allocate buffer under 1MB for VBE data structures
801 BiosVideoPrivate
->NumberOfPagesBelow1MB
= EFI_SIZE_TO_PAGES (
802 sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
) + sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
) +
803 sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
)
806 BiosVideoPrivate
->PagesBelow1MB
= 0x00100000 - 1;
808 Status
= gBS
->AllocatePages (
811 BiosVideoPrivate
->NumberOfPagesBelow1MB
,
812 &BiosVideoPrivate
->PagesBelow1MB
814 if (EFI_ERROR (Status
)) {
818 // Fill in the UGA Draw Protocol
820 BiosVideoPrivate
->UgaDraw
.GetMode
= BiosVideoUgaDrawGetMode
;
821 BiosVideoPrivate
->UgaDraw
.SetMode
= BiosVideoUgaDrawSetMode
;
822 BiosVideoPrivate
->UgaDraw
.Blt
= BiosVideoUgaDrawVbeBlt
;
825 // Fill in the VBE related data structures
827 BiosVideoPrivate
->VbeInformationBlock
= (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
*) (UINTN
) (BiosVideoPrivate
->PagesBelow1MB
);
828 BiosVideoPrivate
->VbeModeInformationBlock
= (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeInformationBlock
+ 1);
829 BiosVideoPrivate
->VbeCrtcInformationBlock
= (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
*) (BiosVideoPrivate
->VbeModeInformationBlock
+ 1);
830 BiosVideoPrivate
->VbeSaveRestorePages
= 0;
831 BiosVideoPrivate
->VbeSaveRestoreBuffer
= 0;
834 // Test to see if the Video Adapter is compliant with VBE 3.0
836 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
837 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_CONTROLLER_INFORMATION
;
838 gBS
->SetMem (BiosVideoPrivate
->VbeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_INFORMATION_BLOCK
), 0);
839 BiosVideoPrivate
->VbeInformationBlock
->VESASignature
= VESA_BIOS_EXTENSIONS_VBE2_SIGNATURE
;
840 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
)BiosVideoPrivate
->VbeInformationBlock
);
841 Regs
.X
.DI
= EFI_OFFSET ((UINTN
)BiosVideoPrivate
->VbeInformationBlock
);
843 LegacyBiosInt86 (0x10, &Regs
);
845 Status
= EFI_DEVICE_ERROR
;
848 // See if the VESA call succeeded
850 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
854 // Check for 'VESA' signature
856 if (BiosVideoPrivate
->VbeInformationBlock
->VESASignature
!= VESA_BIOS_EXTENSIONS_VESA_SIGNATURE
) {
860 // Check to see if this is VBE 2.0 or higher
862 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
< VESA_BIOS_EXTENSIONS_VERSION_2_0
) {
866 // Walk through the mode list to see if there is at least one mode the is compatible with the UGA_DRAW protocol
868 ModeNumberPtr
= (UINT16
*)
870 (((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0xffff0000) >> 12) |
871 ((UINTN
) BiosVideoPrivate
->VbeInformationBlock
->VideoModePtr
& 0x0000ffff)
873 for (; *ModeNumberPtr
!= VESA_BIOS_EXTENSIONS_END_OF_MODE_LIST
; ModeNumberPtr
++) {
875 // Make sure this is a mode number defined by the VESA VBE specification. If it isn'tm then skip this mode number.
877 if ((*ModeNumberPtr
& VESA_BIOS_EXTENSIONS_MODE_NUMBER_VESA
) == 0) {
881 // Get the information about the mode
883 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
884 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_RETURN_MODE_INFORMATION
;
885 Regs
.X
.CX
= *ModeNumberPtr
;
886 gBS
->SetMem (BiosVideoPrivate
->VbeModeInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_MODE_INFORMATION_BLOCK
), 0);
887 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
);
888 Regs
.X
.DI
= EFI_OFFSET ((UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
);
890 LegacyBiosInt86 (0x10, &Regs
);
893 // See if the call succeeded. If it didn't, then try the next mode.
895 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
899 // See if the mode supports color. If it doesn't then try the next mode.
901 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_COLOR
) == 0) {
905 // See if the mode supports graphics. If it doesn't then try the next mode.
907 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_GRAPHICS
) == 0) {
911 // See if the mode supports a linear frame buffer. If it doesn't then try the next mode.
913 if ((BiosVideoPrivate
->VbeModeInformationBlock
->ModeAttributes
& VESA_BIOS_EXTENSIONS_MODE_ATTRIBUTE_LINEAR_FRAME_BUFFER
) == 0) {
917 // See if the mode supports 32 bit color. If it doesn't then try the next mode.
918 // 32 bit mode can be implemented by 24 Bits Per Pixels. Also make sure the
919 // number of bits per pixel is a multiple of 8 or more than 32 bits per pixel
921 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
< 24) {
925 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
> 32) {
929 if ((BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
% 8) != 0) {
933 // See if the physical base pointer for the linear mode is valid. If it isn't then try the next mode.
935 if (BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
== 0) {
939 // See if the resolution is 1024x768, 800x600, or 640x480
942 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 1024 &&
943 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 768
948 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 800 &&
949 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 600
954 if (BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
== 640 &&
955 BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
== 480
964 // Add mode to the list of available modes
966 BiosVideoPrivate
->MaxMode
++;
967 Status
= gBS
->AllocatePool (
969 BiosVideoPrivate
->MaxMode
* sizeof (BIOS_VIDEO_MODE_DATA
),
970 (VOID
**) &ModeBuffer
972 if (EFI_ERROR (Status
)) {
976 if (BiosVideoPrivate
->MaxMode
> 1) {
979 BiosVideoPrivate
->ModeData
,
980 (BiosVideoPrivate
->MaxMode
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
984 if (BiosVideoPrivate
->ModeData
!= NULL
) {
985 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
988 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].VbeModeNumber
= *ModeNumberPtr
;
989 if (BiosVideoPrivate
->VbeInformationBlock
->VESAVersion
>= VESA_BIOS_EXTENSIONS_VERSION_3_0
) {
990 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBytesPerScanLine
;
991 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinRedFieldPosition
;
992 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinRedMaskSize
) - 1);
993 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueFieldPosition
;
994 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinBlueMaskSize
) - 1);
995 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenFieldPosition
;
996 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->LinGreenMaskSize
) - 1);
999 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].BytesPerScanLine
= BiosVideoPrivate
->VbeModeInformationBlock
->BytesPerScanLine
;
1000 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Red
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->RedFieldPosition
;
1001 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Red
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->RedMaskSize
) - 1);
1002 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Blue
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->BlueFieldPosition
;
1003 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Blue
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->BlueMaskSize
) - 1);
1004 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Green
.Position
= BiosVideoPrivate
->VbeModeInformationBlock
->GreenFieldPosition
;
1005 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].Green
.Mask
= (UINT8
) ((1 << BiosVideoPrivate
->VbeModeInformationBlock
->GreenMaskSize
) - 1);
1009 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].LinearFrameBuffer
= (VOID
*) (UINTN
)BiosVideoPrivate
->VbeModeInformationBlock
->PhysBasePtr
;
1010 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].HorizontalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->XResolution
;
1011 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].VerticalResolution
= BiosVideoPrivate
->VbeModeInformationBlock
->YResolution
;
1013 if (BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
>= 24) {
1014 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].ColorDepth
= 32;
1016 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].ColorDepth
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1019 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].BitsPerPixel
= BiosVideoPrivate
->VbeModeInformationBlock
->BitsPerPixel
;
1021 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].RefreshRate
= 60;
1023 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1026 // Check to see if we found any modes that are compatible with UGA DRAW
1028 if (BiosVideoPrivate
->MaxMode
== 0) {
1029 Status
= EFI_DEVICE_ERROR
;
1033 // Find the best mode to initialize
1035 Status
= BiosVideoUgaDrawSetMode (&BiosVideoPrivate
->UgaDraw
, 1024, 768, 32, 60);
1036 //Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 800, 600, 32, 60);
1037 if (EFI_ERROR (Status
)) {
1038 Status
= BiosVideoUgaDrawSetMode (&BiosVideoPrivate
->UgaDraw
, 800, 600, 32, 60);
1039 //Status = BiosVideoUgaDrawSetMode (&BiosVideoPrivate->UgaDraw, 1024, 768, 32, 60);
1040 if (EFI_ERROR (Status
)) {
1041 Status
= BiosVideoUgaDrawSetMode (&BiosVideoPrivate
->UgaDraw
, 640, 480, 32, 60);
1042 for (Index
= 0; EFI_ERROR (Status
) && Index
< BiosVideoPrivate
->MaxMode
; Index
++) {
1043 Status
= BiosVideoUgaDrawSetMode (
1044 &BiosVideoPrivate
->UgaDraw
,
1045 BiosVideoPrivate
->ModeData
[Index
].HorizontalResolution
,
1046 BiosVideoPrivate
->ModeData
[Index
].VerticalResolution
,
1047 BiosVideoPrivate
->ModeData
[Index
].ColorDepth
,
1048 BiosVideoPrivate
->ModeData
[Index
].RefreshRate
1056 // If there was an error, then free the mode structure
1058 if (EFI_ERROR (Status
)) {
1059 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1060 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1061 BiosVideoPrivate
->ModeData
= NULL
;
1062 BiosVideoPrivate
->MaxMode
= 0;
1070 BiosVideoCheckForVga (
1071 IN OUT BIOS_VIDEO_DEV
*BiosVideoPrivate
1075 Routine Description:
1077 Check for VGA device
1081 BiosVideoPrivate - Pointer to BIOS_VIDEO_DEV structure
1085 EFI_SUCCESS - Standard VGA device found
1090 BIOS_VIDEO_MODE_DATA
*ModeBuffer
;
1093 // Fill in the UGA Draw Protocol
1095 BiosVideoPrivate
->UgaDraw
.GetMode
= BiosVideoUgaDrawGetMode
;
1096 BiosVideoPrivate
->UgaDraw
.SetMode
= BiosVideoUgaDrawSetMode
;
1097 BiosVideoPrivate
->UgaDraw
.Blt
= BiosVideoUgaDrawVgaBlt
;
1100 // Add mode to the list of available modes
1102 BiosVideoPrivate
->MaxMode
++;
1103 Status
= gBS
->AllocatePool (
1104 EfiBootServicesData
,
1105 BiosVideoPrivate
->MaxMode
* sizeof (BIOS_VIDEO_MODE_DATA
),
1106 (VOID
**) &ModeBuffer
1108 if (EFI_ERROR (Status
)) {
1112 if (BiosVideoPrivate
->MaxMode
> 1) {
1115 BiosVideoPrivate
->ModeData
,
1116 (BiosVideoPrivate
->MaxMode
- 1) * sizeof (BIOS_VIDEO_MODE_DATA
)
1120 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1121 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1124 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].VbeModeNumber
= 0x0012;
1125 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].BytesPerScanLine
= 640;
1126 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].LinearFrameBuffer
= (VOID
*) (UINTN
)(0xa0000);
1127 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].HorizontalResolution
= 640;
1128 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].VerticalResolution
= 480;
1129 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].ColorDepth
= 32;
1130 ModeBuffer
[BiosVideoPrivate
->MaxMode
- 1].RefreshRate
= 60;
1132 BiosVideoPrivate
->ModeData
= ModeBuffer
;
1135 // Test to see if the Video Adapter support the 640x480 16 color mode
1137 Status
= BiosVideoUgaDrawSetMode (&BiosVideoPrivate
->UgaDraw
, 640, 480, 32, 60);
1140 // If there was an error, then free the mode structure
1142 if (EFI_ERROR (Status
)) {
1143 BiosVideoPrivate
->MaxMode
= 0;
1144 if (BiosVideoPrivate
->ModeData
!= NULL
) {
1145 gBS
->FreePool (BiosVideoPrivate
->ModeData
);
1152 // UGA Protocol Member Functions for VESA BIOS Extensions
1156 BiosVideoUgaDrawGetMode (
1157 IN EFI_UGA_DRAW_PROTOCOL
*This
,
1158 OUT UINT32
*HorizontalResolution
,
1159 OUT UINT32
*VerticalResolution
,
1160 OUT UINT32
*ColorDepth
,
1161 OUT UINT32
*RefreshRate
1165 Routine Description:
1167 UGA protocol interface to get video mode
1171 This - Pointer to UGA draw protocol instance
1172 HorizontalResolution - Horizontal Resolution, in pixels
1173 VerticalResolution - Vertical Resolution, in pixels
1174 ColorDepth - Bit number used to represent color value of a pixel
1175 RefreshRate - Refresh rate, in Hertz
1179 EFI_DEVICE_ERROR - Hardware need starting
1180 EFI_INVALID_PARAMETER - Invalid parameter passed in
1181 EFI_SUCCESS - Video mode query successfully
1185 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1187 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This
);
1189 if (BiosVideoPrivate
->HardwareNeedsStarting
) {
1190 return EFI_DEVICE_ERROR
;
1193 if (HorizontalResolution
== NULL
|| VerticalResolution
== NULL
|| ColorDepth
== NULL
|| RefreshRate
== NULL
) {
1194 return EFI_INVALID_PARAMETER
;
1197 *HorizontalResolution
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].HorizontalResolution
;
1198 *VerticalResolution
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
;
1199 *ColorDepth
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].ColorDepth
;
1200 *RefreshRate
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].RefreshRate
;
1207 BiosVideoUgaDrawSetMode (
1208 IN EFI_UGA_DRAW_PROTOCOL
*This
,
1209 IN UINT32 HorizontalResolution
,
1210 IN UINT32 VerticalResolution
,
1211 IN UINT32 ColorDepth
,
1212 IN UINT32 RefreshRate
1216 Routine Description:
1218 UGA draw protocol interface to set video mode
1222 This - Pointer to UGA draw protocol instance
1223 HorizontalResolution - Horizontal Resolution, in pixels
1224 VerticalResolution - Vertical Resolution, in pixels
1225 ColorDepth - Bit number used to represent color value of a pixel
1226 RefreshRate - Refresh rate, in Hertz
1230 EFI_DEVICE_ERROR - Device error
1231 EFI_SUCCESS - Video mode set successfully
1232 EFI_UNSUPPORTED - Cannot support this video mode
1237 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1239 EFI_IA32_REGISTER_SET Regs
;
1241 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This
);
1243 for (Index
= 0; Index
< BiosVideoPrivate
->MaxMode
; Index
++) {
1245 if (HorizontalResolution
!= BiosVideoPrivate
->ModeData
[Index
].HorizontalResolution
) {
1249 if (VerticalResolution
!= BiosVideoPrivate
->ModeData
[Index
].VerticalResolution
) {
1253 if (ColorDepth
!= BiosVideoPrivate
->ModeData
[Index
].ColorDepth
) {
1257 if (RefreshRate
!= BiosVideoPrivate
->ModeData
[Index
].RefreshRate
) {
1261 if (BiosVideoPrivate
->LineBuffer
) {
1262 gBS
->FreePool (BiosVideoPrivate
->LineBuffer
);
1265 if (BiosVideoPrivate
->VgaFrameBuffer
) {
1266 gBS
->FreePool (BiosVideoPrivate
->VgaFrameBuffer
);
1269 if (BiosVideoPrivate
->VbeFrameBuffer
) {
1270 gBS
->FreePool (BiosVideoPrivate
->VbeFrameBuffer
);
1273 BiosVideoPrivate
->LineBuffer
= NULL
;
1274 Status
= gBS
->AllocatePool (
1275 EfiBootServicesData
,
1276 BiosVideoPrivate
->ModeData
[Index
].BytesPerScanLine
,
1277 (VOID
**)&BiosVideoPrivate
->LineBuffer
1279 if (EFI_ERROR (Status
)) {
1283 // Clear all registers
1285 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
1287 if (BiosVideoPrivate
->ModeData
[Index
].VbeModeNumber
< 0x100) {
1289 // Allocate a working buffer for BLT operations to the VGA frame buffer
1291 BiosVideoPrivate
->VgaFrameBuffer
= NULL
;
1292 Status
= gBS
->AllocatePool (
1293 EfiBootServicesData
,
1295 (VOID
**)&BiosVideoPrivate
->VgaFrameBuffer
1297 if (EFI_ERROR (Status
)) {
1303 Regs
.X
.AX
= BiosVideoPrivate
->ModeData
[Index
].VbeModeNumber
;
1304 LegacyBiosInt86 (0x10, &Regs
);
1308 // Allocate a working buffer for BLT operations to the VBE frame buffer
1310 BiosVideoPrivate
->VbeFrameBuffer
= NULL
;
1311 Status
= gBS
->AllocatePool (
1312 EfiBootServicesData
,
1313 BiosVideoPrivate
->ModeData
[Index
].BytesPerScanLine
* BiosVideoPrivate
->ModeData
[Index
].VerticalResolution
,
1314 (VOID
**)&BiosVideoPrivate
->VbeFrameBuffer
1316 if (EFI_ERROR (Status
)) {
1322 Regs
.X
.AX
= VESA_BIOS_EXTENSIONS_SET_MODE
;
1323 Regs
.X
.BX
= (UINT16
) (BiosVideoPrivate
->ModeData
[Index
].VbeModeNumber
| VESA_BIOS_EXTENSIONS_MODE_NUMBER_LINEAR_FRAME_BUFFER
);
1324 gBS
->SetMem (BiosVideoPrivate
->VbeCrtcInformationBlock
, sizeof (VESA_BIOS_EXTENSIONS_CRTC_INFORMATION_BLOCK
), 0);
1325 Regs
.X
.ES
= EFI_SEGMENT ((UINTN
)BiosVideoPrivate
->VbeCrtcInformationBlock
);
1326 Regs
.X
.DI
= EFI_OFFSET ((UINTN
)BiosVideoPrivate
->VbeCrtcInformationBlock
);
1327 LegacyBiosInt86 (0x10, &Regs
);
1330 // Check to see if the call succeeded
1332 if (Regs
.X
.AX
!= VESA_BIOS_EXTENSIONS_STATUS_SUCCESS
) {
1333 return EFI_DEVICE_ERROR
;
1336 // Initialize the state of the VbeFrameBuffer
1338 Status
= BiosVideoPrivate
->PciIo
->Mem
.Read (
1339 BiosVideoPrivate
->PciIo
,
1340 EfiPciIoWidthUint32
,
1341 EFI_PCI_IO_PASS_THROUGH_BAR
,
1342 (UINT64
) (UINTN
) BiosVideoPrivate
->ModeData
[Index
].LinearFrameBuffer
,
1343 (BiosVideoPrivate
->ModeData
[Index
].BytesPerScanLine
* BiosVideoPrivate
->ModeData
[Index
].VerticalResolution
) >> 2,
1344 BiosVideoPrivate
->VbeFrameBuffer
1346 if (EFI_ERROR (Status
)) {
1351 BiosVideoPrivate
->CurrentMode
= Index
;
1353 BiosVideoPrivate
->HardwareNeedsStarting
= FALSE
;
1358 return EFI_UNSUPPORTED
;
1363 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1364 IN UINT8
*VbeBuffer
,
1365 IN VOID
*MemAddress
,
1366 IN UINTN DestinationX
,
1367 IN UINTN DestinationY
,
1368 IN UINTN TotalBytes
,
1369 IN UINT32 VbePixelWidth
,
1370 IN UINTN BytesPerScanLine
1374 Routine Description:
1376 Update physical frame buffer, copy 4 bytes block, then copy remaining bytes.
1380 PciIo - The pointer of EFI_PCI_IO_PROTOCOL
1381 VbeBuffer - The data to transfer to screen
1382 MemAddress - Physical frame buffer base address
1383 DestinationX - The X coordinate of the destination for BltOperation
1384 DestinationY - The Y coordinate of the destination for BltOperation
1385 TotalBytes - The total bytes of copy
1386 VbePixelWidth - Bytes per pixel
1387 BytesPerScanLine - Bytes per scan line
1395 UINTN FrameBufferAddr
;
1397 UINTN RemainingBytes
;
1398 UINTN UnalignedBytes
;
1401 FrameBufferAddr
= (UINTN
) MemAddress
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
;
1404 // If TotalBytes is less than 4 bytes, only start byte copy.
1406 if (TotalBytes
< 4) {
1407 Status
= PciIo
->Mem
.Write (
1410 EFI_PCI_IO_PASS_THROUGH_BAR
,
1411 (UINT64
) FrameBufferAddr
,
1415 ASSERT_EFI_ERROR (Status
);
1420 // If VbeBuffer is not 4-byte aligned, start byte copy.
1422 UnalignedBytes
= (4 - ((UINTN
) VbeBuffer
& 0x3)) & 0x3;
1424 if (UnalignedBytes
!= 0) {
1425 Status
= PciIo
->Mem
.Write (
1428 EFI_PCI_IO_PASS_THROUGH_BAR
,
1429 (UINT64
) FrameBufferAddr
,
1433 ASSERT_EFI_ERROR (Status
);
1434 FrameBufferAddr
+= UnalignedBytes
;
1435 VbeBuffer
+= UnalignedBytes
;
1439 // Calculate 4-byte block count and remaining bytes.
1441 CopyBlockNum
= (TotalBytes
- UnalignedBytes
) >> 2;
1442 RemainingBytes
= (TotalBytes
- UnalignedBytes
) & 3;
1445 // Copy 4-byte block and remaining bytes to physical frame buffer.
1447 if (CopyBlockNum
!= 0) {
1448 Status
= PciIo
->Mem
.Write (
1450 EfiPciIoWidthUint32
,
1451 EFI_PCI_IO_PASS_THROUGH_BAR
,
1452 (UINT64
) FrameBufferAddr
,
1456 ASSERT_EFI_ERROR (Status
);
1459 if (RemainingBytes
!= 0) {
1460 FrameBufferAddr
+= (CopyBlockNum
<< 2);
1461 VbeBuffer
+= (CopyBlockNum
<< 2);
1462 Status
= PciIo
->Mem
.Write (
1465 EFI_PCI_IO_PASS_THROUGH_BAR
,
1466 (UINT64
) FrameBufferAddr
,
1470 ASSERT_EFI_ERROR (Status
);
1475 // BUGBUG : Add Blt for 16 bit color, 15 bit color, and 8 bit color modes
1479 BiosVideoUgaDrawVbeBlt (
1480 IN EFI_UGA_DRAW_PROTOCOL
*This
,
1481 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
1482 IN EFI_UGA_BLT_OPERATION BltOperation
,
1485 IN UINTN DestinationX
,
1486 IN UINTN DestinationY
,
1493 Routine Description:
1495 UGA draw protocol instance to block transfer for VBE device
1499 This - Pointer to UGA draw protocol instance
1500 BltBuffer - The data to transfer to screen
1501 BltOperation - The operation to perform
1502 SourceX - The X coordinate of the source for BltOperation
1503 SourceY - The Y coordinate of the source for BltOperation
1504 DestinationX - The X coordinate of the destination for BltOperation
1505 DestinationY - The Y coordinate of the destination for BltOperation
1506 Width - The width of a rectangle in the blt rectangle in pixels
1507 Height - The height of a rectangle in the blt rectangle in pixels
1508 Delta - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.
1509 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1510 If a subrectangle of the BltBuffer is used, then Delta represents
1511 the number of bytes in a row of the BltBuffer.
1515 EFI_INVALID_PARAMETER - Invalid parameter passed in
1516 EFI_SUCCESS - Blt operation success
1520 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1521 BIOS_VIDEO_MODE_DATA
*Mode
;
1522 EFI_PCI_IO_PROTOCOL
*PciIo
;
1523 EFI_TPL OriginalTPL
;
1529 EFI_UGA_PIXEL
*VbeFrameBuffer
;
1530 UINTN BytesPerScanLine
;
1535 UINT32 VbePixelWidth
;
1539 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This
);
1540 Mode
= &BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
];
1541 PciIo
= BiosVideoPrivate
->PciIo
;
1543 VbeFrameBuffer
= BiosVideoPrivate
->VbeFrameBuffer
;
1544 MemAddress
= Mode
->LinearFrameBuffer
;
1545 BytesPerScanLine
= Mode
->BytesPerScanLine
;
1546 VbePixelWidth
= Mode
->BitsPerPixel
/ 8;
1547 BltUint8
= (UINT8
*) BltBuffer
;
1548 TotalBytes
= Width
* VbePixelWidth
;
1550 if ((BltOperation
< EfiUgaVideoFill
) || (BltOperation
>= EfiUgaBltMax
)) {
1551 return EFI_INVALID_PARAMETER
;
1554 if (Width
== 0 || Height
== 0) {
1555 return EFI_INVALID_PARAMETER
;
1558 // We need to fill the Virtual Screen buffer with the blt data.
1559 // The virtual screen is upside down, as the first row is the bootom row of
1562 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
1564 // Video to BltBuffer: Source is Video, destination is BltBuffer
1566 if (SourceY
+ Height
> Mode
->VerticalResolution
) {
1567 return EFI_INVALID_PARAMETER
;
1570 if (SourceX
+ Width
> Mode
->HorizontalResolution
) {
1571 return EFI_INVALID_PARAMETER
;
1575 // BltBuffer to Video: Source is BltBuffer, destination is Video
1577 if (DestinationY
+ Height
> Mode
->VerticalResolution
) {
1578 return EFI_INVALID_PARAMETER
;
1581 if (DestinationX
+ Width
> Mode
->HorizontalResolution
) {
1582 return EFI_INVALID_PARAMETER
;
1586 // If Delta is zero, then the entire BltBuffer is being used, so Delta
1587 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
1588 // the number of bytes in each row can be computed.
1591 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
1594 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
1595 // We would not want a timer based event (Cursor, ...) to come in while we are
1596 // doing this operation.
1598 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
1600 switch (BltOperation
) {
1601 case EfiUgaVideoToBltBuffer
:
1602 for (SrcY
= SourceY
, DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); SrcY
++, DstY
++) {
1603 Blt
= (EFI_UGA_PIXEL
*) (BltUint8
+ DstY
* Delta
+ DestinationX
* sizeof (EFI_UGA_PIXEL
));
1605 // Shuffle the packed bytes in the hardware buffer to match EFI_UGA_PIXEL
1607 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
));
1608 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1609 Pixel
= *(UINT32
*) (VbeBuffer
);
1610 Blt
->Red
= (UINT8
) ((Pixel
>> Mode
->Red
.Position
) & Mode
->Red
.Mask
);
1611 Blt
->Blue
= (UINT8
) ((Pixel
>> Mode
->Blue
.Position
) & Mode
->Blue
.Mask
);
1612 Blt
->Green
= (UINT8
) ((Pixel
>> Mode
->Green
.Position
) & Mode
->Green
.Mask
);
1615 VbeBuffer
+= VbePixelWidth
;
1621 case EfiUgaVideoToVideo
:
1622 for (Index
= 0; Index
< Height
; Index
++) {
1623 if (DestinationY
<= SourceY
) {
1624 SrcY
= SourceY
+ Index
;
1625 DstY
= DestinationY
+ Index
;
1627 SrcY
= SourceY
+ Height
- Index
- 1;
1628 DstY
= DestinationY
+ Height
- Index
- 1;
1631 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
);
1632 VbeBuffer1
= ((UINT8
*) VbeFrameBuffer
+ SrcY
* BytesPerScanLine
+ SourceX
* VbePixelWidth
);
1641 // Update physical frame buffer.
1656 case EfiUgaVideoFill
:
1657 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1658 Blt
= (EFI_UGA_PIXEL
*) BltUint8
;
1660 // Shuffle the RGB fields in EFI_UGA_PIXEL to match the hardware buffer
1662 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1664 (Blt
->Green
& Mode
->Green
.Mask
) <<
1665 Mode
->Green
.Position
1667 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1669 for (Index
= 0; Index
< Width
; Index
++) {
1675 VbeBuffer
+= VbePixelWidth
;
1678 VbeBuffer
= (UINT8
*) ((UINTN
) VbeFrameBuffer
+ (DestinationY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
);
1679 for (DstY
= DestinationY
+ 1; DstY
< (Height
+ DestinationY
); DstY
++) {
1681 (VOID
*) ((UINTN
) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
) + DestinationX
* VbePixelWidth
),
1686 for (DstY
= DestinationY
; DstY
< (Height
+ DestinationY
); DstY
++) {
1688 // Update physical frame buffer.
1704 case EfiUgaBltBufferToVideo
:
1705 for (SrcY
= SourceY
, DstY
= DestinationY
; SrcY
< (Height
+ SourceY
); SrcY
++, DstY
++) {
1706 Blt
= (EFI_UGA_PIXEL
*) (BltUint8
+ (SrcY
* Delta
) + (SourceX
) * sizeof (EFI_UGA_PIXEL
));
1707 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1708 for (DstX
= DestinationX
; DstX
< (Width
+ DestinationX
); DstX
++) {
1710 // Shuffle the RGB fields in EFI_UGA_PIXEL to match the hardware buffer
1712 Pixel
= ((Blt
->Red
& Mode
->Red
.Mask
) << Mode
->Red
.Position
) |
1713 ((Blt
->Green
& Mode
->Green
.Mask
) << Mode
->Green
.Position
) |
1714 ((Blt
->Blue
& Mode
->Blue
.Mask
) << Mode
->Blue
.Position
);
1721 VbeBuffer
+= VbePixelWidth
;
1724 VbeBuffer
= ((UINT8
*) VbeFrameBuffer
+ (DstY
* BytesPerScanLine
+ DestinationX
* VbePixelWidth
));
1727 // Update physical frame buffer.
1745 gBS
->RestoreTPL (OriginalTPL
);
1752 WriteGraphicsController (
1753 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1759 Routine Description:
1761 Write graphics controller registers
1765 PciIo - Pointer to PciIo protocol instance of the controller
1766 Address - Register address
1767 Data - Data to be written to register
1775 Address
= Address
| (Data
<< 8);
1778 EfiPciIoWidthUint16
,
1779 EFI_PCI_IO_PASS_THROUGH_BAR
,
1780 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
1788 EFI_PCI_IO_PROTOCOL
*PciIo
,
1789 UINT8
*HardwareBuffer
,
1790 UINT8
*MemoryBuffer
,
1796 Routine Description:
1798 Read the four bit plane of VGA frame buffer
1802 PciIo - Pointer to PciIo protocol instance of the controller
1803 HardwareBuffer - Hardware VGA frame buffer address
1804 MemoryBuffer - Memory buffer address
1805 WidthInBytes - Number of bytes in a line to read
1806 Height - Height of the area to read
1816 UINTN FrameBufferOffset
;
1821 // Program the Mode Register Write mode 0, Read mode 0
1823 WriteGraphicsController (
1825 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
1826 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
1829 for (BitPlane
= 0, FrameBufferOffset
= 0;
1830 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
1831 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
1834 // Program the Read Map Select Register to select the correct bit plane
1836 WriteGraphicsController (
1838 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
1842 Source
= HardwareBuffer
;
1843 Destination
= MemoryBuffer
+ FrameBufferOffset
;
1845 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
1849 EFI_PCI_IO_PASS_THROUGH_BAR
,
1850 (UINT64
) (UINTN
)Source
,
1852 (VOID
*) Destination
1859 VgaConvertToUgaColor (
1860 UINT8
*MemoryBuffer
,
1863 EFI_UGA_PIXEL
*BltBuffer
1867 Routine Description:
1869 Internal routine to convert VGA color to UGA color
1873 MemoryBuffer - Buffer containing VGA color
1874 X - The X coordinate of pixel on screen
1875 Y - The Y coordinate of pixel on screen
1876 BltBuffer - Buffer to contain converted UGA color
1888 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
1889 Mask
= mVgaBitMaskTable
[X
& 0x07];
1890 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
1891 if (*MemoryBuffer
& Mask
) {
1896 *BltBuffer
= mVgaColorToUgaColor
[Color
];
1901 IN EFI_UGA_PIXEL
*BltBuffer
1905 Routine Description:
1907 Internal routine to convert UGA color to VGA color
1911 BltBuffer - buffer containing UGA color
1921 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
1922 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
1931 BiosVideoUgaDrawVgaBlt (
1932 IN EFI_UGA_DRAW_PROTOCOL
*This
,
1933 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
1934 IN EFI_UGA_BLT_OPERATION BltOperation
,
1937 IN UINTN DestinationX
,
1938 IN UINTN DestinationY
,
1945 Routine Description:
1947 UGA draw protocol instance to block transfer for VGA device
1951 This - Pointer to UGA draw protocol instance
1952 BltBuffer - The data to transfer to screen
1953 BltOperation - The operation to perform
1954 SourceX - The X coordinate of the source for BltOperation
1955 SourceY - The Y coordinate of the source for BltOperation
1956 DestinationX - The X coordinate of the destination for BltOperation
1957 DestinationY - The Y coordinate of the destination for BltOperation
1958 Width - The width of a rectangle in the blt rectangle in pixels
1959 Height - The height of a rectangle in the blt rectangle in pixels
1960 Delta - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.
1961 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1962 If a subrectangle of the BltBuffer is used, then Delta represents
1963 the number of bytes in a row of the BltBuffer.
1967 EFI_INVALID_PARAMETER - Invalid parameter passed in
1968 EFI_SUCCESS - Blt operation success
1972 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1973 EFI_TPL OriginalTPL
;
1975 UINTN BytesPerScanLine
;
1976 UINTN BytesPerBitPlane
;
1988 UINT8
*SourceAddress
;
1989 UINT8
*DestinationAddress
;
1990 EFI_PCI_IO_PROTOCOL
*PciIo
;
1993 UINT8
*VgaFrameBuffer
;
2001 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This
);
2003 PciIo
= BiosVideoPrivate
->PciIo
;
2004 MemAddress
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].LinearFrameBuffer
;
2005 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].BytesPerScanLine
>> 3;
2006 BytesPerBitPlane
= BytesPerScanLine
* BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
;
2007 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2009 if ((BltOperation
< EfiUgaVideoFill
) || (BltOperation
>= EfiUgaBltMax
)) {
2010 return EFI_INVALID_PARAMETER
;
2013 if (Width
== 0 || Height
== 0) {
2014 return EFI_INVALID_PARAMETER
;
2017 // We need to fill the Virtual Screen buffer with the blt data.
2018 // The virtual screen is upside down, as the first row is the bootom row of
2021 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
2023 // Video to BltBuffer: Source is Video, destination is BltBuffer
2025 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
) {
2026 return EFI_INVALID_PARAMETER
;
2029 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].HorizontalResolution
) {
2030 return EFI_INVALID_PARAMETER
;
2034 // BltBuffer to Video: Source is BltBuffer, destination is Video
2036 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
) {
2037 return EFI_INVALID_PARAMETER
;
2040 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].HorizontalResolution
) {
2041 return EFI_INVALID_PARAMETER
;
2045 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2046 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2047 // the number of bytes in each row can be computed.
2050 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
2053 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2054 // We would not want a timer based event (Cursor, ...) to come in while we are
2055 // doing this operation.
2057 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2060 // Compute some values we need for VGA
2062 switch (BltOperation
) {
2063 case EfiUgaVideoToBltBuffer
:
2065 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2066 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2069 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2073 MemAddress
+ SourceOffset
,
2074 VgaFrameBuffer
+ SourceOffset
,
2080 // Convert VGA Bit Planes to a UGA 32-bit color value
2082 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2083 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2084 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2085 VgaConvertToUgaColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2093 case EfiUgaVideoToVideo
:
2095 // Check for an aligned Video to Video operation
2097 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2099 // Program the Mode Register Write mode 1, Read mode 0
2101 WriteGraphicsController (
2102 BiosVideoPrivate
->PciIo
,
2103 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2104 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2107 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2108 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2110 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2114 EFI_PCI_IO_PASS_THROUGH_BAR
,
2115 (UINT64
) ((UINTN
)DestinationAddress
+ Offset
),
2116 EFI_PCI_IO_PASS_THROUGH_BAR
,
2117 (UINT64
) ((UINTN
)SourceAddress
+ Offset
),
2122 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2123 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2126 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2130 MemAddress
+ SourceOffset
,
2131 VgaFrameBuffer
+ SourceOffset
,
2139 case EfiUgaVideoFill
:
2140 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2141 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2142 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2143 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2145 LeftMask
&= RightMask
;
2149 if (LeftMask
== 0xff) {
2155 if (RightMask
== 0xff) {
2160 PixelColor
= VgaConvertColor (BltBuffer
);
2163 // Program the Mode Register Write mode 2, Read mode 0
2165 WriteGraphicsController (
2166 BiosVideoPrivate
->PciIo
,
2167 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2168 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2172 // Program the Data Rotate/Function Select Register to replace
2174 WriteGraphicsController (
2175 BiosVideoPrivate
->PciIo
,
2176 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2177 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2180 if (LeftMask
!= 0) {
2182 // Program the BitMask register with the Left column mask
2184 WriteGraphicsController (
2185 BiosVideoPrivate
->PciIo
,
2186 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2190 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2192 // Read data from the bit planes into the latches
2197 EFI_PCI_IO_PASS_THROUGH_BAR
,
2203 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2208 EFI_PCI_IO_PASS_THROUGH_BAR
,
2218 // Program the BitMask register with the middle column mask of 0xff
2220 WriteGraphicsController (
2221 BiosVideoPrivate
->PciIo
,
2222 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2226 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2229 EfiPciIoWidthFillUint8
,
2230 EFI_PCI_IO_PASS_THROUGH_BAR
,
2238 if (RightMask
!= 0) {
2240 // Program the BitMask register with the Right column mask
2242 WriteGraphicsController (
2243 BiosVideoPrivate
->PciIo
,
2244 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2248 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2250 // Read data from the bit planes into the latches
2255 EFI_PCI_IO_PASS_THROUGH_BAR
,
2261 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2266 EFI_PCI_IO_PASS_THROUGH_BAR
,
2275 case EfiUgaBltBufferToVideo
:
2276 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2277 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2280 // Program the Mode Register Write mode 2, Read mode 0
2282 WriteGraphicsController (
2283 BiosVideoPrivate
->PciIo
,
2284 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2285 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2289 // Program the Data Rotate/Function Select Register to replace
2291 WriteGraphicsController (
2292 BiosVideoPrivate
->PciIo
,
2293 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2294 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2297 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2298 for (Index1
= 0; Index1
< Width
; Index1
++) {
2299 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2301 AddressFix
= Address
;
2303 for (Bit
= 0; Bit
< 8; Bit
++) {
2305 // Program the BitMask register with the Left column mask
2307 WriteGraphicsController (
2308 BiosVideoPrivate
->PciIo
,
2309 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2313 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2315 // Read data from the bit planes into the latches
2320 EFI_PCI_IO_PASS_THROUGH_BAR
,
2321 (UINT64
) (UINTN
) Address1
,
2329 EFI_PCI_IO_PASS_THROUGH_BAR
,
2330 (UINT64
) (UINTN
) Address1
,
2332 &BiosVideoPrivate
->LineBuffer
[Index1
]
2336 LeftMask
= (UINT8
) (LeftMask
>> 1);
2337 if (LeftMask
== 0) {
2349 gBS
->RestoreTPL (OriginalTPL
);
2354 // VGA Mini Port Protocol Functions
2358 BiosVideoVgaMiniPortSetMode (
2359 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2364 Routine Description:
2366 VgaMiniPort protocol interface to set mode
2370 This - Pointer to VgaMiniPort protocol instance
2371 ModeNumber - The index of the mode
2375 EFI_UNSUPPORTED - The requested mode is not supported
2376 EFI_SUCCESS - The requested mode is set successfully
2380 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2381 EFI_IA32_REGISTER_SET Regs
;
2384 // Make sure the ModeNumber is a valid value
2386 if (ModeNumber
>= This
->MaxMode
) {
2387 return EFI_UNSUPPORTED
;
2390 // Get the device structure for this device
2392 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2394 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2396 switch (ModeNumber
) {
2399 // Set the 80x25 Text VGA Mode
2403 LegacyBiosInt86 (0x10, &Regs
);
2408 LegacyBiosInt86 (0x10, &Regs
);
2413 // Set the 80x50 Text VGA Mode
2417 LegacyBiosInt86 (0x10, &Regs
);
2421 LegacyBiosInt86 (0x10, &Regs
);
2425 return EFI_UNSUPPORTED
;
2432 InitializeBiosIntCaller (
2437 UINT32 RealModeBufferSize
;
2438 UINT32 ExtraStackSize
;
2439 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
2444 AsmGetThunk16Properties (&RealModeBufferSize
, &ExtraStackSize
);
2446 LegacyRegionBase
= 0x100000;
2447 Status
= gBS
->AllocatePages (
2450 EFI_SIZE_TO_PAGES(RealModeBufferSize
+ ExtraStackSize
+ 200),
2453 ASSERT_EFI_ERROR (Status
);
2455 mThunkContext
.RealModeBuffer
= (VOID
*)(UINTN
)LegacyRegionBase
;
2456 mThunkContext
.RealModeBufferSize
= EFI_PAGES_TO_SIZE (RealModeBufferSize
);
2457 mThunkContext
.ThunkAttributes
= 3;
2458 AsmPrepareThunk16(&mThunkContext
);
2460 //Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);
2461 //ASSERT_EFI_ERROR (Status);
2465 InitializeInterruptRedirection (
2470 Routine Description:
2471 Initialize interrupt redirection code and entries, because
2472 IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.
2473 Or the interrupt will lost when we do thunk.
2474 NOTE: We do not reset 8259 vector base, because it will cause pending
2485 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
2486 UINTN LegacyRegionLength
;
2489 UINT8 ProtectedModeBaseVector
;
2490 UINT32 InterruptRedirectionCode
[] = {
2491 0x90CF08CD, // INT8; IRET; NOP
2492 0x90CF09CD, // INT9; IRET; NOP
2493 0x90CF0ACD, // INTA; IRET; NOP
2494 0x90CF0BCD, // INTB; IRET; NOP
2495 0x90CF0CCD, // INTC; IRET; NOP
2496 0x90CF0DCD, // INTD; IRET; NOP
2497 0x90CF0ECD, // INTE; IRET; NOP
2498 0x90CF0FCD // INTF; IRET; NOP
2504 LegacyRegionLength
= sizeof(InterruptRedirectionCode
);
2505 LegacyRegionBase
= 0x100000;
2506 Status
= gBS
->AllocatePages (
2509 EFI_SIZE_TO_PAGES(LegacyRegionLength
),
2512 ASSERT_EFI_ERROR (Status
);
2515 // Copy code to legacy region
2517 CopyMem ((VOID
*)(UINTN
)LegacyRegionBase
, InterruptRedirectionCode
, sizeof (InterruptRedirectionCode
));
2520 // Get VectorBase, it should be 0x68
2522 Status
= mLegacy8259
->GetVector (mLegacy8259
, Efi8259Irq0
, &ProtectedModeBaseVector
);
2523 ASSERT_EFI_ERROR (Status
);
2526 // Patch IVT 0x68 ~ 0x6f
2528 IdtArray
= (UINT32
*) 0;
2529 for (Index
= 0; Index
< 8; Index
++) {
2530 IdtArray
[ProtectedModeBaseVector
+ Index
] = ((EFI_SEGMENT (LegacyRegionBase
+ Index
* 4)) << 16) | (EFI_OFFSET (LegacyRegionBase
+ Index
* 4));
2540 IN EFI_IA32_REGISTER_SET
*Regs
2544 Routine Description:
2545 Thunk to 16-bit real mode and execute a software interrupt with a vector
2546 of BiosInt. Regs will contain the 16-bit register context on entry and
2550 This - Protocol instance pointer.
2551 BiosInt - Processor interrupt vector to invoke
2552 Reg - Register contexted passed into (and returned) from thunk to
2556 FALSE - Thunk completed, and there were no BIOS errors in the target code.
2557 See Regs for status.
2558 TRUE - There was a BIOS erro in the target code.
2564 IA32_REGISTER_SET ThunkRegSet
;
2568 Regs
->X
.Flags
.Reserved1
= 1;
2569 Regs
->X
.Flags
.Reserved2
= 0;
2570 Regs
->X
.Flags
.Reserved3
= 0;
2571 Regs
->X
.Flags
.Reserved4
= 0;
2572 Regs
->X
.Flags
.IOPL
= 3;
2573 Regs
->X
.Flags
.NT
= 0;
2574 Regs
->X
.Flags
.IF
= 1;
2575 Regs
->X
.Flags
.TF
= 0;
2576 Regs
->X
.Flags
.CF
= 0;
2578 ZeroMem (&ThunkRegSet
, sizeof (ThunkRegSet
));
2579 ThunkRegSet
.E
.EDI
= Regs
->E
.EDI
;
2580 ThunkRegSet
.E
.ESI
= Regs
->E
.ESI
;
2581 ThunkRegSet
.E
.EBP
= Regs
->E
.EBP
;
2582 ThunkRegSet
.E
.EBX
= Regs
->E
.EBX
;
2583 ThunkRegSet
.E
.EDX
= Regs
->E
.EDX
;
2584 ThunkRegSet
.E
.ECX
= Regs
->E
.ECX
;
2585 ThunkRegSet
.E
.EAX
= Regs
->E
.EAX
;
2586 ThunkRegSet
.E
.DS
= Regs
->E
.DS
;
2587 ThunkRegSet
.E
.ES
= Regs
->E
.ES
;
2589 CopyMem (&(ThunkRegSet
.E
.EFLAGS
), &(Regs
->E
.EFlags
), sizeof (UINT32
));
2592 // The call to Legacy16 is a critical section to EFI
2594 Eflags
= AsmReadEflags ();
2595 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
2596 DisableInterrupts ();
2600 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
2602 Status
= mLegacy8259
->SetMode (mLegacy8259
, Efi8259LegacyMode
, NULL
, NULL
);
2603 ASSERT_EFI_ERROR (Status
);
2605 Stack16
= (UINT16
*)((UINT8
*) mThunkContext
.RealModeBuffer
+ mThunkContext
.RealModeBufferSize
- sizeof (UINT16
));
2606 Stack16
-= sizeof (ThunkRegSet
.E
.EFLAGS
) / sizeof (UINT16
);
2607 CopyMem (Stack16
, &ThunkRegSet
.E
.EFLAGS
, sizeof (ThunkRegSet
.E
.EFLAGS
));
2609 ThunkRegSet
.E
.SS
= (UINT16
) (((UINTN
) Stack16
>> 16) << 12);
2610 ThunkRegSet
.E
.ESP
= (UINT16
) (UINTN
) Stack16
;
2611 ThunkRegSet
.E
.Eip
= (UINT16
)((UINT32
*)NULL
)[BiosInt
];
2612 ThunkRegSet
.E
.CS
= (UINT16
)(((UINT32
*)NULL
)[BiosInt
] >> 16);
2613 mThunkContext
.RealModeState
= &ThunkRegSet
;
2614 AsmThunk16 (&mThunkContext
);
2617 // Restore protected mode interrupt state
2619 Status
= mLegacy8259
->SetMode (mLegacy8259
, Efi8259ProtectedMode
, NULL
, NULL
);
2620 ASSERT_EFI_ERROR (Status
);
2623 // End critical section
2625 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
2626 EnableInterrupts ();
2629 Regs
->E
.EDI
= ThunkRegSet
.E
.EDI
;
2630 Regs
->E
.ESI
= ThunkRegSet
.E
.ESI
;
2631 Regs
->E
.EBP
= ThunkRegSet
.E
.EBP
;
2632 Regs
->E
.EBX
= ThunkRegSet
.E
.EBX
;
2633 Regs
->E
.EDX
= ThunkRegSet
.E
.EDX
;
2634 Regs
->E
.ECX
= ThunkRegSet
.E
.ECX
;
2635 Regs
->E
.EAX
= ThunkRegSet
.E
.EAX
;
2636 Regs
->E
.SS
= ThunkRegSet
.E
.SS
;
2637 Regs
->E
.CS
= ThunkRegSet
.E
.CS
;
2638 Regs
->E
.DS
= ThunkRegSet
.E
.DS
;
2639 Regs
->E
.ES
= ThunkRegSet
.E
.ES
;
2641 CopyMem (&(Regs
->E
.EFlags
), &(ThunkRegSet
.E
.EFLAGS
), sizeof (UINT32
));
2643 Ret
= (BOOLEAN
) (Regs
->E
.EFlags
.CF
== 1);