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
),
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 &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 &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 &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 &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.
1743 gBS
->RestoreTPL (OriginalTPL
);
1750 WriteGraphicsController (
1751 IN EFI_PCI_IO_PROTOCOL
*PciIo
,
1757 Routine Description:
1759 Write graphics controller registers
1763 PciIo - Pointer to PciIo protocol instance of the controller
1764 Address - Register address
1765 Data - Data to be written to register
1773 Address
= Address
| (Data
<< 8);
1776 EfiPciIoWidthUint16
,
1777 EFI_PCI_IO_PASS_THROUGH_BAR
,
1778 VGA_GRAPHICS_CONTROLLER_ADDRESS_REGISTER
,
1786 EFI_PCI_IO_PROTOCOL
*PciIo
,
1787 UINT8
*HardwareBuffer
,
1788 UINT8
*MemoryBuffer
,
1794 Routine Description:
1796 Read the four bit plane of VGA frame buffer
1800 PciIo - Pointer to PciIo protocol instance of the controller
1801 HardwareBuffer - Hardware VGA frame buffer address
1802 MemoryBuffer - Memory buffer address
1803 WidthInBytes - Number of bytes in a line to read
1804 Height - Height of the area to read
1814 UINTN FrameBufferOffset
;
1819 // Program the Mode Register Write mode 0, Read mode 0
1821 WriteGraphicsController (
1823 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
1824 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_0
1827 for (BitPlane
= 0, FrameBufferOffset
= 0;
1828 BitPlane
< VGA_NUMBER_OF_BIT_PLANES
;
1829 BitPlane
++, FrameBufferOffset
+= VGA_BYTES_PER_BIT_PLANE
1832 // Program the Read Map Select Register to select the correct bit plane
1834 WriteGraphicsController (
1836 VGA_GRAPHICS_CONTROLLER_READ_MAP_SELECT_REGISTER
,
1840 Source
= HardwareBuffer
;
1841 Destination
= MemoryBuffer
+ FrameBufferOffset
;
1843 for (Rows
= 0; Rows
< Height
; Rows
++, Source
+= VGA_BYTES_PER_SCAN_LINE
, Destination
+= VGA_BYTES_PER_SCAN_LINE
) {
1847 EFI_PCI_IO_PASS_THROUGH_BAR
,
1850 (VOID
*) Destination
1857 VgaConvertToUgaColor (
1858 UINT8
*MemoryBuffer
,
1861 EFI_UGA_PIXEL
*BltBuffer
1865 Routine Description:
1867 Internal routine to convert VGA color to UGA color
1871 MemoryBuffer - Buffer containing VGA color
1872 X - The X coordinate of pixel on screen
1873 Y - The Y coordinate of pixel on screen
1874 BltBuffer - Buffer to contain converted UGA color
1886 MemoryBuffer
+= ((Y
<< 6) + (Y
<< 4) + (X
>> 3));
1887 Mask
= mVgaBitMaskTable
[X
& 0x07];
1888 for (Bit
= 0x01, Color
= 0; Bit
< 0x10; Bit
<<= 1, MemoryBuffer
+= VGA_BYTES_PER_BIT_PLANE
) {
1889 if (*MemoryBuffer
& Mask
) {
1894 *BltBuffer
= mVgaColorToUgaColor
[Color
];
1899 IN EFI_UGA_PIXEL
*BltBuffer
1903 Routine Description:
1905 Internal routine to convert UGA color to VGA color
1909 BltBuffer - buffer containing UGA color
1919 Color
= (UINT8
) ((BltBuffer
->Blue
>> 7) | ((BltBuffer
->Green
>> 6) & 0x02) | ((BltBuffer
->Red
>> 5) & 0x04));
1920 if ((BltBuffer
->Red
+ BltBuffer
->Green
+ BltBuffer
->Blue
) > 0x180) {
1929 BiosVideoUgaDrawVgaBlt (
1930 IN EFI_UGA_DRAW_PROTOCOL
*This
,
1931 IN EFI_UGA_PIXEL
*BltBuffer
, OPTIONAL
1932 IN EFI_UGA_BLT_OPERATION BltOperation
,
1935 IN UINTN DestinationX
,
1936 IN UINTN DestinationY
,
1943 Routine Description:
1945 UGA draw protocol instance to block transfer for VGA device
1949 This - Pointer to UGA draw protocol instance
1950 BltBuffer - The data to transfer to screen
1951 BltOperation - The operation to perform
1952 SourceX - The X coordinate of the source for BltOperation
1953 SourceY - The Y coordinate of the source for BltOperation
1954 DestinationX - The X coordinate of the destination for BltOperation
1955 DestinationY - The Y coordinate of the destination for BltOperation
1956 Width - The width of a rectangle in the blt rectangle in pixels
1957 Height - The height of a rectangle in the blt rectangle in pixels
1958 Delta - Not used for EfiUgaVideoFill and EfiUgaVideoToVideo operation.
1959 If a Delta of 0 is used, the entire BltBuffer will be operated on.
1960 If a subrectangle of the BltBuffer is used, then Delta represents
1961 the number of bytes in a row of the BltBuffer.
1965 EFI_INVALID_PARAMETER - Invalid parameter passed in
1966 EFI_SUCCESS - Blt operation success
1970 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
1971 EFI_TPL OriginalTPL
;
1973 UINTN BytesPerScanLine
;
1974 UINTN BytesPerBitPlane
;
1986 UINT8
*SourceAddress
;
1987 UINT8
*DestinationAddress
;
1988 EFI_PCI_IO_PROTOCOL
*PciIo
;
1991 UINT8
*VgaFrameBuffer
;
1999 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_UGA_DRAW_THIS (This
);
2001 PciIo
= BiosVideoPrivate
->PciIo
;
2002 MemAddress
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].LinearFrameBuffer
;
2003 BytesPerScanLine
= BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].BytesPerScanLine
>> 3;
2004 BytesPerBitPlane
= BytesPerScanLine
* BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
;
2005 VgaFrameBuffer
= BiosVideoPrivate
->VgaFrameBuffer
;
2007 if ((BltOperation
< EfiUgaVideoFill
) || (BltOperation
>= EfiUgaBltMax
)) {
2008 return EFI_INVALID_PARAMETER
;
2011 if (Width
== 0 || Height
== 0) {
2012 return EFI_INVALID_PARAMETER
;
2015 // We need to fill the Virtual Screen buffer with the blt data.
2016 // The virtual screen is upside down, as the first row is the bootom row of
2019 if (BltOperation
== EfiUgaVideoToBltBuffer
) {
2021 // Video to BltBuffer: Source is Video, destination is BltBuffer
2023 if (SourceY
+ Height
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
) {
2024 return EFI_INVALID_PARAMETER
;
2027 if (SourceX
+ Width
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].HorizontalResolution
) {
2028 return EFI_INVALID_PARAMETER
;
2032 // BltBuffer to Video: Source is BltBuffer, destination is Video
2034 if (DestinationY
+ Height
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].VerticalResolution
) {
2035 return EFI_INVALID_PARAMETER
;
2038 if (DestinationX
+ Width
> BiosVideoPrivate
->ModeData
[BiosVideoPrivate
->CurrentMode
].HorizontalResolution
) {
2039 return EFI_INVALID_PARAMETER
;
2043 // If Delta is zero, then the entire BltBuffer is being used, so Delta
2044 // is the number of bytes in each row of BltBuffer. Since BltBuffer is Width pixels size,
2045 // the number of bytes in each row can be computed.
2048 Delta
= Width
* sizeof (EFI_UGA_PIXEL
);
2051 // We have to raise to TPL Notify, so we make an atomic write the frame buffer.
2052 // We would not want a timer based event (Cursor, ...) to come in while we are
2053 // doing this operation.
2055 OriginalTPL
= gBS
->RaiseTPL (TPL_NOTIFY
);
2058 // Compute some values we need for VGA
2060 switch (BltOperation
) {
2061 case EfiUgaVideoToBltBuffer
:
2063 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2064 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2067 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2071 MemAddress
+ SourceOffset
,
2072 VgaFrameBuffer
+ SourceOffset
,
2078 // Convert VGA Bit Planes to a UGA 32-bit color value
2080 BltBuffer
+= (DestinationY
* (Delta
>> 2) + DestinationX
);
2081 for (Rows
= 0, Y
= SourceY
; Rows
< Height
; Rows
++, Y
++, BltBuffer
+= (Delta
>> 2)) {
2082 for (Columns
= 0, X
= SourceX
; Columns
< Width
; Columns
++, X
++, BltBuffer
++) {
2083 VgaConvertToUgaColor (VgaFrameBuffer
, X
, Y
, BltBuffer
);
2091 case EfiUgaVideoToVideo
:
2093 // Check for an aligned Video to Video operation
2095 if ((SourceX
& 0x07) == 0x00 && (DestinationX
& 0x07) == 0x00 && (Width
& 0x07) == 0x00) {
2097 // Program the Mode Register Write mode 1, Read mode 0
2099 WriteGraphicsController (
2100 BiosVideoPrivate
->PciIo
,
2101 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2102 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_1
2105 SourceAddress
= (UINT8
*) (MemAddress
+ (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3));
2106 DestinationAddress
= (UINT8
*) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2108 for (Index
= 0, Offset
= 0; Index
< Height
; Index
++, Offset
+= BytesPerScanLine
) {
2112 EFI_PCI_IO_PASS_THROUGH_BAR
,
2113 (UINT64
) (DestinationAddress
+ Offset
),
2114 EFI_PCI_IO_PASS_THROUGH_BAR
,
2115 (UINT64
) (SourceAddress
+ Offset
),
2120 SourceOffset
= (SourceY
<< 6) + (SourceY
<< 4) + (SourceX
>> 3);
2121 SourceWidth
= ((SourceX
+ Width
- 1) >> 3) - (SourceX
>> 3) + 1;
2124 // Read all the pixels in the 4 bit planes into a memory buffer that looks like the VGA buffer
2128 MemAddress
+ SourceOffset
,
2129 VgaFrameBuffer
+ SourceOffset
,
2137 case EfiUgaVideoFill
:
2138 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2139 Bytes
= ((DestinationX
+ Width
- 1) >> 3) - (DestinationX
>> 3);
2140 LeftMask
= mVgaLeftMaskTable
[DestinationX
& 0x07];
2141 RightMask
= mVgaRightMaskTable
[(DestinationX
+ Width
- 1) & 0x07];
2143 LeftMask
&= RightMask
;
2147 if (LeftMask
== 0xff) {
2153 if (RightMask
== 0xff) {
2158 PixelColor
= VgaConvertColor (BltBuffer
);
2161 // Program the Mode Register Write mode 2, Read mode 0
2163 WriteGraphicsController (
2164 BiosVideoPrivate
->PciIo
,
2165 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2166 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2170 // Program the Data Rotate/Function Select Register to replace
2172 WriteGraphicsController (
2173 BiosVideoPrivate
->PciIo
,
2174 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2175 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2178 if (LeftMask
!= 0) {
2180 // Program the BitMask register with the Left column mask
2182 WriteGraphicsController (
2183 BiosVideoPrivate
->PciIo
,
2184 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2188 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2190 // Read data from the bit planes into the latches
2195 EFI_PCI_IO_PASS_THROUGH_BAR
,
2201 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2206 EFI_PCI_IO_PASS_THROUGH_BAR
,
2216 // Program the BitMask register with the middle column mask of 0xff
2218 WriteGraphicsController (
2219 BiosVideoPrivate
->PciIo
,
2220 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2224 for (Index
= 0, Address
= StartAddress
+ 1; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2227 EfiPciIoWidthFillUint8
,
2228 EFI_PCI_IO_PASS_THROUGH_BAR
,
2236 if (RightMask
!= 0) {
2238 // Program the BitMask register with the Right column mask
2240 WriteGraphicsController (
2241 BiosVideoPrivate
->PciIo
,
2242 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2246 for (Index
= 0, Address
= StartAddress
+ Bytes
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2248 // Read data from the bit planes into the latches
2253 EFI_PCI_IO_PASS_THROUGH_BAR
,
2259 // Write the lower 4 bits of PixelColor to the bit planes in the pixels enabled by BitMask
2264 EFI_PCI_IO_PASS_THROUGH_BAR
,
2273 case EfiUgaBltBufferToVideo
:
2274 StartAddress
= (UINTN
) (MemAddress
+ (DestinationY
<< 6) + (DestinationY
<< 4) + (DestinationX
>> 3));
2275 LeftMask
= mVgaBitMaskTable
[DestinationX
& 0x07];
2278 // Program the Mode Register Write mode 2, Read mode 0
2280 WriteGraphicsController (
2281 BiosVideoPrivate
->PciIo
,
2282 VGA_GRAPHICS_CONTROLLER_MODE_REGISTER
,
2283 VGA_GRAPHICS_CONTROLLER_READ_MODE_0
| VGA_GRAPHICS_CONTROLLER_WRITE_MODE_2
2287 // Program the Data Rotate/Function Select Register to replace
2289 WriteGraphicsController (
2290 BiosVideoPrivate
->PciIo
,
2291 VGA_GRAPHICS_CONTROLLER_DATA_ROTATE_REGISTER
,
2292 VGA_GRAPHICS_CONTROLLER_FUNCTION_REPLACE
2295 for (Index
= 0, Address
= StartAddress
; Index
< Height
; Index
++, Address
+= BytesPerScanLine
) {
2296 for (Index1
= 0; Index1
< Width
; Index1
++) {
2297 BiosVideoPrivate
->LineBuffer
[Index1
] = VgaConvertColor (&BltBuffer
[(SourceY
+ Index
) * (Delta
>> 2) + SourceX
+ Index1
]);
2299 AddressFix
= Address
;
2301 for (Bit
= 0; Bit
< 8; Bit
++) {
2303 // Program the BitMask register with the Left column mask
2305 WriteGraphicsController (
2306 BiosVideoPrivate
->PciIo
,
2307 VGA_GRAPHICS_CONTROLLER_BIT_MASK_REGISTER
,
2311 for (Index1
= Bit
, Address1
= (UINT8
*) AddressFix
; Index1
< Width
; Index1
+= 8, Address1
++) {
2313 // Read data from the bit planes into the latches
2318 EFI_PCI_IO_PASS_THROUGH_BAR
,
2327 EFI_PCI_IO_PASS_THROUGH_BAR
,
2330 &BiosVideoPrivate
->LineBuffer
[Index1
]
2334 LeftMask
= (UINT8
) (LeftMask
>> 1);
2335 if (LeftMask
== 0) {
2345 gBS
->RestoreTPL (OriginalTPL
);
2350 // VGA Mini Port Protocol Functions
2354 BiosVideoVgaMiniPortSetMode (
2355 IN EFI_VGA_MINI_PORT_PROTOCOL
*This
,
2360 Routine Description:
2362 VgaMiniPort protocol interface to set mode
2366 This - Pointer to VgaMiniPort protocol instance
2367 ModeNumber - The index of the mode
2371 EFI_UNSUPPORTED - The requested mode is not supported
2372 EFI_SUCCESS - The requested mode is set successfully
2376 BIOS_VIDEO_DEV
*BiosVideoPrivate
;
2377 EFI_IA32_REGISTER_SET Regs
;
2380 // Make sure the ModeNumber is a valid value
2382 if (ModeNumber
>= This
->MaxMode
) {
2383 return EFI_UNSUPPORTED
;
2386 // Get the device structure for this device
2388 BiosVideoPrivate
= BIOS_VIDEO_DEV_FROM_VGA_MINI_PORT_THIS (This
);
2390 gBS
->SetMem (&Regs
, sizeof (Regs
), 0);
2392 switch (ModeNumber
) {
2395 // Set the 80x25 Text VGA Mode
2399 LegacyBiosInt86 (0x10, &Regs
);
2404 LegacyBiosInt86 (0x10, &Regs
);
2409 // Set the 80x50 Text VGA Mode
2413 LegacyBiosInt86 (0x10, &Regs
);
2417 LegacyBiosInt86 (0x10, &Regs
);
2421 return EFI_UNSUPPORTED
;
2428 InitializeBiosIntCaller (
2433 UINT32 RealModeBufferSize
;
2434 UINT32 ExtraStackSize
;
2435 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
2440 AsmGetThunk16Properties (&RealModeBufferSize
, &ExtraStackSize
);
2442 LegacyRegionBase
= 0x100000;
2443 Status
= gBS
->AllocatePages (
2446 EFI_SIZE_TO_PAGES(RealModeBufferSize
+ ExtraStackSize
+ 200),
2449 ASSERT_EFI_ERROR (Status
);
2451 mThunkContext
.RealModeBuffer
= (VOID
*)(UINTN
)LegacyRegionBase
;
2452 mThunkContext
.RealModeBufferSize
= EFI_PAGES_TO_SIZE (RealModeBufferSize
);
2453 mThunkContext
.ThunkAttributes
= 3;
2454 AsmPrepareThunk16(&mThunkContext
);
2456 //Status = gBS->LocateProtocol (&gEfiLegacy8259ProtocolGuid, NULL, (VOID **) &mLegacy8259);
2457 //ASSERT_EFI_ERROR (Status);
2461 InitializeInterruptRedirection (
2466 Routine Description:
2467 Initialize interrupt redirection code and entries, because
2468 IDT Vectors 0x68-0x6f must be redirected to IDT Vectors 0x08-0x0f.
2469 Or the interrupt will lost when we do thunk.
2470 NOTE: We do not reset 8259 vector base, because it will cause pending
2481 EFI_PHYSICAL_ADDRESS LegacyRegionBase
;
2482 UINTN LegacyRegionLength
;
2485 UINT8 ProtectedModeBaseVector
;
2486 UINT32 InterruptRedirectionCode
[] = {
2487 0x90CF08CD, // INT8; IRET; NOP
2488 0x90CF09CD, // INT9; IRET; NOP
2489 0x90CF0ACD, // INTA; IRET; NOP
2490 0x90CF0BCD, // INTB; IRET; NOP
2491 0x90CF0CCD, // INTC; IRET; NOP
2492 0x90CF0DCD, // INTD; IRET; NOP
2493 0x90CF0ECD, // INTE; IRET; NOP
2494 0x90CF0FCD // INTF; IRET; NOP
2500 LegacyRegionLength
= sizeof(InterruptRedirectionCode
);
2501 LegacyRegionBase
= 0x100000;
2502 Status
= gBS
->AllocatePages (
2505 EFI_SIZE_TO_PAGES(LegacyRegionLength
),
2508 ASSERT_EFI_ERROR (Status
);
2511 // Copy code to legacy region
2513 CopyMem ((VOID
*)(UINTN
)LegacyRegionBase
, InterruptRedirectionCode
, sizeof (InterruptRedirectionCode
));
2516 // Get VectorBase, it should be 0x68
2518 Status
= mLegacy8259
->GetVector (mLegacy8259
, Efi8259Irq0
, &ProtectedModeBaseVector
);
2519 ASSERT_EFI_ERROR (Status
);
2522 // Patch IVT 0x68 ~ 0x6f
2524 IdtArray
= (UINT32
*) 0;
2525 for (Index
= 0; Index
< 8; Index
++) {
2526 IdtArray
[ProtectedModeBaseVector
+ Index
] = ((EFI_SEGMENT (LegacyRegionBase
+ Index
* 4)) << 16) | (EFI_OFFSET (LegacyRegionBase
+ Index
* 4));
2536 IN EFI_IA32_REGISTER_SET
*Regs
2540 Routine Description:
2541 Thunk to 16-bit real mode and execute a software interrupt with a vector
2542 of BiosInt. Regs will contain the 16-bit register context on entry and
2546 This - Protocol instance pointer.
2547 BiosInt - Processor interrupt vector to invoke
2548 Reg - Register contexted passed into (and returned) from thunk to
2552 FALSE - Thunk completed, and there were no BIOS errors in the target code.
2553 See Regs for status.
2554 TRUE - There was a BIOS erro in the target code.
2560 IA32_REGISTER_SET ThunkRegSet
;
2564 Regs
->X
.Flags
.Reserved1
= 1;
2565 Regs
->X
.Flags
.Reserved2
= 0;
2566 Regs
->X
.Flags
.Reserved3
= 0;
2567 Regs
->X
.Flags
.Reserved4
= 0;
2568 Regs
->X
.Flags
.IOPL
= 3;
2569 Regs
->X
.Flags
.NT
= 0;
2570 Regs
->X
.Flags
.IF
= 1;
2571 Regs
->X
.Flags
.TF
= 0;
2572 Regs
->X
.Flags
.CF
= 0;
2574 ZeroMem (&ThunkRegSet
, sizeof (ThunkRegSet
));
2575 ThunkRegSet
.E
.EDI
= Regs
->E
.EDI
;
2576 ThunkRegSet
.E
.ESI
= Regs
->E
.ESI
;
2577 ThunkRegSet
.E
.EBP
= Regs
->E
.EBP
;
2578 ThunkRegSet
.E
.EBX
= Regs
->E
.EBX
;
2579 ThunkRegSet
.E
.EDX
= Regs
->E
.EDX
;
2580 ThunkRegSet
.E
.ECX
= Regs
->E
.ECX
;
2581 ThunkRegSet
.E
.EAX
= Regs
->E
.EAX
;
2582 ThunkRegSet
.E
.DS
= Regs
->E
.DS
;
2583 ThunkRegSet
.E
.ES
= Regs
->E
.ES
;
2585 CopyMem (&(ThunkRegSet
.E
.EFLAGS
), &(Regs
->E
.EFlags
), sizeof (UINT32
));
2588 // The call to Legacy16 is a critical section to EFI
2590 Eflags
= AsmReadEflags ();
2591 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
2592 DisableInterrupts ();
2596 // Set Legacy16 state. 0x08, 0x70 is legacy 8259 vector bases.
2598 Status
= mLegacy8259
->SetMode (mLegacy8259
, Efi8259LegacyMode
, NULL
, NULL
);
2599 ASSERT_EFI_ERROR (Status
);
2601 Stack16
= (UINT16
*)((UINT8
*) mThunkContext
.RealModeBuffer
+ mThunkContext
.RealModeBufferSize
- sizeof (UINT16
));
2602 Stack16
-= sizeof (ThunkRegSet
.E
.EFLAGS
) / sizeof (UINT16
);
2603 CopyMem (Stack16
, &ThunkRegSet
.E
.EFLAGS
, sizeof (ThunkRegSet
.E
.EFLAGS
));
2605 ThunkRegSet
.E
.SS
= (UINT16
) (((UINTN
) Stack16
>> 16) << 12);
2606 ThunkRegSet
.E
.ESP
= (UINT16
) (UINTN
) Stack16
;
2607 ThunkRegSet
.E
.Eip
= (UINT16
)((UINT32
*)NULL
)[BiosInt
];
2608 ThunkRegSet
.E
.CS
= (UINT16
)(((UINT32
*)NULL
)[BiosInt
] >> 16);
2609 mThunkContext
.RealModeState
= &ThunkRegSet
;
2610 AsmThunk16 (&mThunkContext
);
2613 // Restore protected mode interrupt state
2615 Status
= mLegacy8259
->SetMode (mLegacy8259
, Efi8259ProtectedMode
, NULL
, NULL
);
2616 ASSERT_EFI_ERROR (Status
);
2619 // End critical section
2621 if ((Eflags
| EFI_CPU_EFLAGS_IF
) != 0) {
2622 EnableInterrupts ();
2625 Regs
->E
.EDI
= ThunkRegSet
.E
.EDI
;
2626 Regs
->E
.ESI
= ThunkRegSet
.E
.ESI
;
2627 Regs
->E
.EBP
= ThunkRegSet
.E
.EBP
;
2628 Regs
->E
.EBX
= ThunkRegSet
.E
.EBX
;
2629 Regs
->E
.EDX
= ThunkRegSet
.E
.EDX
;
2630 Regs
->E
.ECX
= ThunkRegSet
.E
.ECX
;
2631 Regs
->E
.EAX
= ThunkRegSet
.E
.EAX
;
2632 Regs
->E
.SS
= ThunkRegSet
.E
.SS
;
2633 Regs
->E
.CS
= ThunkRegSet
.E
.CS
;
2634 Regs
->E
.DS
= ThunkRegSet
.E
.DS
;
2635 Regs
->E
.ES
= ThunkRegSet
.E
.ES
;
2637 CopyMem (&(Regs
->E
.EFlags
), &(ThunkRegSet
.E
.EFLAGS
), sizeof (UINT32
));
2639 Ret
= (BOOLEAN
) (Regs
->E
.EFlags
.CF
== 1);